1/*
2 *
3 *  Support for the mpeg transport stream transfers
4 *  PCI function #2 of the cx2388x.
5 *
6 *    (c) 2004 Jelle Foks <jelle@foks.8m.com>
7 *    (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
8 *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
9 *
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License as published by
12 *  the Free Software Foundation; either version 2 of the License, or
13 *  (at your option) any later version.
14 *
15 *  This program is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with this program; if not, write to the Free Software
22 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/init.h>
28#include <linux/device.h>
29#include <linux/dma-mapping.h>
30#include <linux/interrupt.h>
31#include <linux/dma-mapping.h>
32#include <asm/delay.h>
33
34#include "cx88.h"
35
36/* ------------------------------------------------------------------ */
37
38MODULE_DESCRIPTION("mpeg driver for cx2388x based TV cards");
39MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>");
40MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
41MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
42MODULE_LICENSE("GPL");
43
44static unsigned int debug = 0;
45module_param(debug,int,0644);
46MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
47
48#define dprintk(level,fmt, arg...)	if (debug >= level) \
49	printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
50
51#define mpeg_dbg(level,fmt, arg...)	if (debug >= level) \
52	printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
53
54#if defined(CONFIG_MODULES) && defined(MODULE)
55static void request_module_async(struct work_struct *work)
56{
57	struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk);
58
59	if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_DVB)
60		request_module("cx88-dvb");
61	if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_BLACKBIRD)
62		request_module("cx88-blackbird");
63}
64
65static void request_modules(struct cx8802_dev *dev)
66{
67	INIT_WORK(&dev->request_module_wk, request_module_async);
68	schedule_work(&dev->request_module_wk);
69}
70#else
71#define request_modules(dev)
72#endif /* CONFIG_MODULES */
73
74
75static LIST_HEAD(cx8802_devlist);
76/* ------------------------------------------------------------------ */
77
78static int cx8802_start_dma(struct cx8802_dev    *dev,
79			    struct cx88_dmaqueue *q,
80			    struct cx88_buffer   *buf)
81{
82	struct cx88_core *core = dev->core;
83
84	dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field);
85
86	/* setup fifo + format */
87	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
88				dev->ts_packet_size, buf->risc.dma);
89
90	/* write TS length to chip */
91	cx_write(MO_TS_LNGTH, buf->vb.width);
92
93
94	dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
95
96	if ( (core->active_type_id == CX88_MPEG_DVB) &&
97		(cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) {
98
99		dprintk( 1, "cx8802_start_dma doing .dvb\n");
100		/* negedge driven & software reset */
101		cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
102		udelay(100);
103		cx_write(MO_PINMUX_IO, 0x00);
104		cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01);
105		switch (core->board) {
106		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
107		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
108		case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
109		case CX88_BOARD_PCHDTV_HD5500:
110			cx_write(TS_SOP_STAT, 1<<13);
111			break;
112		case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
113		case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
114			cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
115			udelay(100);
116			break;
117		case CX88_BOARD_HAUPPAUGE_HVR1300:
118			break;
119		default:
120			cx_write(TS_SOP_STAT, 0x00);
121			break;
122		}
123		cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
124		udelay(100);
125	} else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
126		(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) {
127		dprintk( 1, "cx8802_start_dma doing .blackbird\n");
128		cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
129
130		cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
131		udelay(100);
132
133		cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
134		cx_write(TS_VALERR_CNTRL, 0x2000);
135
136		cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
137		udelay(100);
138	} else {
139		printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
140			cx88_boards[core->board].mpeg );
141		return -EINVAL;
142	}
143
144	/* reset counter */
145	cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
146	q->count = 1;
147
148	/* enable irqs */
149	dprintk( 1, "setting the interrupt mask\n" );
150	cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
151	cx_set(MO_TS_INTMSK,  0x1f0011);
152
153	/* start dma */
154	cx_set(MO_DEV_CNTRL2, (1<<5));
155	cx_set(MO_TS_DMACNTRL, 0x11);
156	return 0;
157}
158
159static int cx8802_stop_dma(struct cx8802_dev *dev)
160{
161	struct cx88_core *core = dev->core;
162	dprintk( 1, "cx8802_stop_dma\n" );
163
164	/* stop dma */
165	cx_clear(MO_TS_DMACNTRL, 0x11);
166
167	/* disable irqs */
168	cx_clear(MO_PCI_INTMSK, 0x000004);
169	cx_clear(MO_TS_INTMSK, 0x1f0011);
170
171	/* Reset the controller */
172	cx_write(TS_GEN_CNTRL, 0xcd);
173	return 0;
174}
175
176static int cx8802_restart_queue(struct cx8802_dev    *dev,
177				struct cx88_dmaqueue *q)
178{
179	struct cx88_buffer *buf;
180	struct list_head *item;
181
182       dprintk( 1, "cx8802_restart_queue\n" );
183	if (list_empty(&q->active))
184	{
185	       struct cx88_buffer *prev;
186	       prev = NULL;
187
188	       dprintk(1, "cx8802_restart_queue: queue is empty\n" );
189
190	       for (;;) {
191		       if (list_empty(&q->queued))
192			       return 0;
193		       buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
194		       if (NULL == prev) {
195			       list_del(&buf->vb.queue);
196			       list_add_tail(&buf->vb.queue,&q->active);
197			       cx8802_start_dma(dev, q, buf);
198			       buf->vb.state = STATE_ACTIVE;
199			       buf->count    = q->count++;
200			       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
201			       dprintk(1,"[%p/%d] restart_queue - first active\n",
202				       buf,buf->vb.i);
203
204		       } else if (prev->vb.width  == buf->vb.width  &&
205				  prev->vb.height == buf->vb.height &&
206				  prev->fmt       == buf->fmt) {
207			       list_del(&buf->vb.queue);
208			       list_add_tail(&buf->vb.queue,&q->active);
209			       buf->vb.state = STATE_ACTIVE;
210			       buf->count    = q->count++;
211			       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
212			       dprintk(1,"[%p/%d] restart_queue - move to active\n",
213				       buf,buf->vb.i);
214		       } else {
215			       return 0;
216		       }
217		       prev = buf;
218	       }
219		return 0;
220	}
221
222	buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
223	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
224		buf, buf->vb.i);
225	cx8802_start_dma(dev, q, buf);
226	list_for_each(item,&q->active) {
227		buf = list_entry(item, struct cx88_buffer, vb.queue);
228		buf->count = q->count++;
229	}
230	mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
231	return 0;
232}
233
234/* ------------------------------------------------------------------ */
235
236int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
237			struct cx88_buffer *buf, enum v4l2_field field)
238{
239	int size = dev->ts_packet_size * dev->ts_packet_count;
240	int rc;
241
242	dprintk(1, "%s: %p\n", __FUNCTION__, buf);
243	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
244		return -EINVAL;
245
246	if (STATE_NEEDS_INIT == buf->vb.state) {
247		buf->vb.width  = dev->ts_packet_size;
248		buf->vb.height = dev->ts_packet_count;
249		buf->vb.size   = size;
250		buf->vb.field  = field /*V4L2_FIELD_TOP*/;
251
252		if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
253			goto fail;
254		cx88_risc_databuffer(dev->pci, &buf->risc,
255				     buf->vb.dma.sglist,
256				     buf->vb.width, buf->vb.height);
257	}
258	buf->vb.state = STATE_PREPARED;
259	return 0;
260
261 fail:
262	cx88_free_buffer(q,buf);
263	return rc;
264}
265
266void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
267{
268	struct cx88_buffer    *prev;
269	struct cx88_dmaqueue  *cx88q = &dev->mpegq;
270
271	dprintk( 1, "cx8802_buf_queue\n" );
272	/* add jump to stopper */
273	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
274	buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
275
276	if (list_empty(&cx88q->active)) {
277		dprintk( 1, "queue is empty - first active\n" );
278		list_add_tail(&buf->vb.queue,&cx88q->active);
279		cx8802_start_dma(dev, cx88q, buf);
280		buf->vb.state = STATE_ACTIVE;
281		buf->count    = cx88q->count++;
282		mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
283		dprintk(1,"[%p/%d] %s - first active\n",
284			buf, buf->vb.i, __FUNCTION__);
285
286	} else {
287		dprintk( 1, "queue is not empty - append to active\n" );
288		prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
289		list_add_tail(&buf->vb.queue,&cx88q->active);
290		buf->vb.state = STATE_ACTIVE;
291		buf->count    = cx88q->count++;
292		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
293		dprintk( 1, "[%p/%d] %s - append to active\n",
294			buf, buf->vb.i, __FUNCTION__);
295	}
296}
297
298/* ----------------------------------------------------------- */
299
300static void do_cancel_buffers(struct cx8802_dev *dev, char *reason, int restart)
301{
302	struct cx88_dmaqueue *q = &dev->mpegq;
303	struct cx88_buffer *buf;
304	unsigned long flags;
305
306	spin_lock_irqsave(&dev->slock,flags);
307	while (!list_empty(&q->active)) {
308		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
309		list_del(&buf->vb.queue);
310		buf->vb.state = STATE_ERROR;
311		wake_up(&buf->vb.done);
312		dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
313			buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
314	}
315	if (restart)
316	{
317		dprintk(1, "restarting queue\n" );
318		cx8802_restart_queue(dev,q);
319	}
320	spin_unlock_irqrestore(&dev->slock,flags);
321}
322
323void cx8802_cancel_buffers(struct cx8802_dev *dev)
324{
325	struct cx88_dmaqueue *q = &dev->mpegq;
326
327	dprintk( 1, "cx8802_cancel_buffers" );
328	del_timer_sync(&q->timeout);
329	cx8802_stop_dma(dev);
330	do_cancel_buffers(dev,"cancel",0);
331}
332
333static void cx8802_timeout(unsigned long data)
334{
335	struct cx8802_dev *dev = (struct cx8802_dev*)data;
336
337	dprintk(0, "%s\n",__FUNCTION__);
338
339	if (debug)
340		cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
341	cx8802_stop_dma(dev);
342	do_cancel_buffers(dev,"timeout",1);
343}
344
345static char *cx88_mpeg_irqs[32] = {
346	"ts_risci1", NULL, NULL, NULL,
347	"ts_risci2", NULL, NULL, NULL,
348	"ts_oflow",  NULL, NULL, NULL,
349	"ts_sync",   NULL, NULL, NULL,
350	"opc_err", "par_err", "rip_err", "pci_abort",
351	"ts_err?",
352};
353
354static void cx8802_mpeg_irq(struct cx8802_dev *dev)
355{
356	struct cx88_core *core = dev->core;
357	u32 status, mask, count;
358
359	dprintk( 1, "cx8802_mpeg_irq\n" );
360	status = cx_read(MO_TS_INTSTAT);
361	mask   = cx_read(MO_TS_INTMSK);
362	if (0 == (status & mask))
363		return;
364
365	cx_write(MO_TS_INTSTAT, status);
366
367	if (debug || (status & mask & ~0xff))
368		cx88_print_irqbits(core->name, "irq mpeg ",
369				   cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs),
370				   status, mask);
371
372	/* risc op code error */
373	if (status & (1 << 16)) {
374		printk(KERN_WARNING "%s: mpeg risc op code error\n",core->name);
375		cx_clear(MO_TS_DMACNTRL, 0x11);
376		cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
377	}
378
379	/* risc1 y */
380	if (status & 0x01) {
381		dprintk( 1, "wake up\n" );
382		spin_lock(&dev->slock);
383		count = cx_read(MO_TS_GPCNT);
384		cx88_wakeup(dev->core, &dev->mpegq, count);
385		spin_unlock(&dev->slock);
386	}
387
388	/* risc2 y */
389	if (status & 0x10) {
390		spin_lock(&dev->slock);
391		cx8802_restart_queue(dev,&dev->mpegq);
392		spin_unlock(&dev->slock);
393	}
394
395	/* other general errors */
396	if (status & 0x1f0100) {
397		dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
398		spin_lock(&dev->slock);
399		cx8802_stop_dma(dev);
400		cx8802_restart_queue(dev,&dev->mpegq);
401		spin_unlock(&dev->slock);
402	}
403}
404
405#define MAX_IRQ_LOOP 10
406
407static irqreturn_t cx8802_irq(int irq, void *dev_id)
408{
409	struct cx8802_dev *dev = dev_id;
410	struct cx88_core *core = dev->core;
411	u32 status;
412	int loop, handled = 0;
413
414	for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
415		status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);
416		if (0 == status)
417			goto out;
418		dprintk( 1, "cx8802_irq\n" );
419		dprintk( 1, "    loop: %d/%d\n", loop, MAX_IRQ_LOOP );
420		dprintk( 1, "    status: %d\n", status );
421		handled = 1;
422		cx_write(MO_PCI_INTSTAT, status);
423
424		if (status & core->pci_irqmask)
425			cx88_core_irq(core,status);
426		if (status & 0x04)
427			cx8802_mpeg_irq(dev);
428	};
429	if (MAX_IRQ_LOOP == loop) {
430		dprintk( 0, "clearing mask\n" );
431		printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
432		       core->name);
433		cx_write(MO_PCI_INTMSK,0);
434	}
435
436 out:
437	return IRQ_RETVAL(handled);
438}
439
440/* ----------------------------------------------------------- */
441/* exported stuff                                              */
442
443int cx8802_init_common(struct cx8802_dev *dev)
444{
445	struct cx88_core *core = dev->core;
446	int err;
447
448	/* pci init */
449	if (pci_enable_device(dev->pci))
450		return -EIO;
451	pci_set_master(dev->pci);
452	if (!pci_dma_supported(dev->pci,DMA_32BIT_MASK)) {
453		printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
454		return -EIO;
455	}
456
457	pci_read_config_byte(dev->pci, PCI_CLASS_REVISION, &dev->pci_rev);
458	pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER,  &dev->pci_lat);
459	printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, "
460	       "latency: %d, mmio: 0x%llx\n", dev->core->name,
461	       pci_name(dev->pci), dev->pci_rev, dev->pci->irq,
462	       dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0));
463
464	/* initialize driver struct */
465	spin_lock_init(&dev->slock);
466
467	/* init dma queue */
468	INIT_LIST_HEAD(&dev->mpegq.active);
469	INIT_LIST_HEAD(&dev->mpegq.queued);
470	dev->mpegq.timeout.function = cx8802_timeout;
471	dev->mpegq.timeout.data     = (unsigned long)dev;
472	init_timer(&dev->mpegq.timeout);
473	cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
474			  MO_TS_DMACNTRL,0x11,0x00);
475
476	/* get irq */
477	err = request_irq(dev->pci->irq, cx8802_irq,
478			  IRQF_SHARED | IRQF_DISABLED, dev->core->name, dev);
479	if (err < 0) {
480		printk(KERN_ERR "%s: can't get IRQ %d\n",
481		       dev->core->name, dev->pci->irq);
482		return err;
483	}
484	cx_set(MO_PCI_INTMSK, core->pci_irqmask);
485
486	/* everything worked */
487	pci_set_drvdata(dev->pci,dev);
488	return 0;
489}
490
491void cx8802_fini_common(struct cx8802_dev *dev)
492{
493	dprintk( 2, "cx8802_fini_common\n" );
494	cx8802_stop_dma(dev);
495	pci_disable_device(dev->pci);
496
497	/* unregister stuff */
498	free_irq(dev->pci->irq, dev);
499	pci_set_drvdata(dev->pci, NULL);
500
501	/* free memory */
502	btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
503}
504
505/* ----------------------------------------------------------- */
506
507int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
508{
509	struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
510	struct cx88_core *core = dev->core;
511
512	/* stop mpeg dma */
513	spin_lock(&dev->slock);
514	if (!list_empty(&dev->mpegq.active)) {
515		dprintk( 2, "suspend\n" );
516		printk("%s: suspend mpeg\n", core->name);
517		cx8802_stop_dma(dev);
518		del_timer(&dev->mpegq.timeout);
519	}
520	spin_unlock(&dev->slock);
521
522	cx88_shutdown(dev->core);
523
524	pci_save_state(pci_dev);
525	if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
526		pci_disable_device(pci_dev);
527		dev->state.disabled = 1;
528	}
529	return 0;
530}
531
532int cx8802_resume_common(struct pci_dev *pci_dev)
533{
534	struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
535	struct cx88_core *core = dev->core;
536	int err;
537
538	if (dev->state.disabled) {
539		err=pci_enable_device(pci_dev);
540		if (err) {
541			printk(KERN_ERR "%s: can't enable device\n",
542					       dev->core->name);
543			return err;
544		}
545		dev->state.disabled = 0;
546	}
547	err=pci_set_power_state(pci_dev, PCI_D0);
548	if (err) {
549		printk(KERN_ERR "%s: can't enable device\n",
550					       dev->core->name);
551		pci_disable_device(pci_dev);
552		dev->state.disabled = 1;
553
554		return err;
555	}
556	pci_restore_state(pci_dev);
557
558	cx88_reset(dev->core);
559
560	/* restart video+vbi capture */
561	spin_lock(&dev->slock);
562	if (!list_empty(&dev->mpegq.active)) {
563		printk("%s: resume mpeg\n", core->name);
564		cx8802_restart_queue(dev,&dev->mpegq);
565	}
566	spin_unlock(&dev->slock);
567
568	return 0;
569}
570
571struct cx8802_dev * cx8802_get_device(struct inode *inode)
572{
573	int minor = iminor(inode);
574	struct cx8802_dev *h = NULL;
575	struct list_head *list;
576
577	list_for_each(list,&cx8802_devlist) {
578		h = list_entry(list, struct cx8802_dev, devlist);
579		if (h->mpeg_dev->minor == minor)
580			return h;
581	}
582
583	return NULL;
584}
585
586struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
587{
588	struct cx8802_dev *h = NULL;
589	struct cx8802_driver *d = NULL;
590	struct list_head *list;
591	struct list_head *list2;
592
593	list_for_each(list,&cx8802_devlist) {
594		h = list_entry(list, struct cx8802_dev, devlist);
595		if (h != dev)
596			continue;
597
598		list_for_each(list2, &h->drvlist.devlist) {
599			d = list_entry(list2, struct cx8802_driver, devlist);
600
601			/* only unregister the correct driver type */
602			if (d->type_id == btype) {
603				return d;
604			}
605		}
606	}
607
608	return NULL;
609}
610
611/* Driver asked for hardware access. */
612static int cx8802_request_acquire(struct cx8802_driver *drv)
613{
614	struct cx88_core *core = drv->core;
615
616	/* Fail a request for hardware if the device is busy. */
617	if (core->active_type_id != CX88_BOARD_NONE)
618		return -EBUSY;
619
620	if (drv->advise_acquire)
621	{
622		core->active_type_id = drv->type_id;
623		drv->advise_acquire(drv);
624
625		mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
626	}
627
628	return 0;
629}
630
631/* Driver asked to release hardware. */
632static int cx8802_request_release(struct cx8802_driver *drv)
633{
634	struct cx88_core *core = drv->core;
635
636	if (drv->advise_release)
637	{
638		drv->advise_release(drv);
639		core->active_type_id = CX88_BOARD_NONE;
640		mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
641	}
642
643	return 0;
644}
645
646static int cx8802_check_driver(struct cx8802_driver *drv)
647{
648	if (drv == NULL)
649		return -ENODEV;
650
651	if ((drv->type_id != CX88_MPEG_DVB) &&
652		(drv->type_id != CX88_MPEG_BLACKBIRD))
653		return -EINVAL;
654
655	if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
656		(drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
657		return -EINVAL;
658
659	if ((drv->probe == NULL) ||
660		(drv->remove == NULL) ||
661		(drv->advise_acquire == NULL) ||
662		(drv->advise_release == NULL))
663		return -EINVAL;
664
665	return 0;
666}
667
668int cx8802_register_driver(struct cx8802_driver *drv)
669{
670	struct cx8802_dev *h;
671	struct cx8802_driver *driver;
672	struct list_head *list;
673	int err = 0, i = 0;
674
675	printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ ,
676		drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
677		drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
678
679	if ((err = cx8802_check_driver(drv)) != 0) {
680		printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ );
681		return err;
682	}
683
684	list_for_each(list,&cx8802_devlist) {
685		h = list_entry(list, struct cx8802_dev, devlist);
686
687		printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
688			h->core->name,h->pci->subsystem_vendor,
689			h->pci->subsystem_device,cx88_boards[h->core->board].name,
690			h->core->board);
691
692		/* Bring up a new struct for each driver instance */
693		driver = kzalloc(sizeof(*drv),GFP_KERNEL);
694		if (driver == NULL)
695			return -ENOMEM;
696
697		/* Snapshot of the driver registration data */
698		drv->core = h->core;
699		drv->suspend = cx8802_suspend_common;
700		drv->resume = cx8802_resume_common;
701		drv->request_acquire = cx8802_request_acquire;
702		drv->request_release = cx8802_request_release;
703		memcpy(driver, drv, sizeof(*driver));
704
705		err = drv->probe(driver);
706		if (err == 0) {
707			i++;
708			mutex_lock(&drv->core->lock);
709			list_add_tail(&driver->devlist,&h->drvlist.devlist);
710			mutex_unlock(&drv->core->lock);
711		} else {
712			printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err);
713		}
714
715	}
716	if (i == 0)
717		err = -ENODEV;
718	else
719		err = 0;
720
721	return err;
722}
723
724int cx8802_unregister_driver(struct cx8802_driver *drv)
725{
726	struct cx8802_dev *h;
727	struct cx8802_driver *d;
728	struct list_head *list;
729	struct list_head *list2, *q;
730	int err = 0, i = 0;
731
732	printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ ,
733		drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird");
734
735	list_for_each(list,&cx8802_devlist) {
736		i++;
737		h = list_entry(list, struct cx8802_dev, devlist);
738
739		printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
740			h->core->name,h->pci->subsystem_vendor,
741			h->pci->subsystem_device,cx88_boards[h->core->board].name,
742			h->core->board);
743
744		list_for_each_safe(list2, q, &h->drvlist.devlist) {
745			d = list_entry(list2, struct cx8802_driver, devlist);
746
747			/* only unregister the correct driver type */
748			if (d->type_id != drv->type_id)
749				continue;
750
751			err = d->remove(d);
752			if (err == 0) {
753				mutex_lock(&drv->core->lock);
754				list_del(list2);
755				mutex_unlock(&drv->core->lock);
756			} else
757				printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err);
758
759		}
760
761	}
762
763	return err;
764}
765
766/* ----------------------------------------------------------- */
767static int __devinit cx8802_probe(struct pci_dev *pci_dev,
768			       const struct pci_device_id *pci_id)
769{
770	struct cx8802_dev *dev;
771	struct cx88_core  *core;
772	int err;
773
774	/* general setup */
775	core = cx88_core_get(pci_dev);
776	if (NULL == core)
777		return -EINVAL;
778
779	printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
780
781	err = -ENODEV;
782	if (!cx88_boards[core->board].mpeg)
783		goto fail_core;
784
785	err = -ENOMEM;
786	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
787	if (NULL == dev)
788		goto fail_core;
789	dev->pci = pci_dev;
790	dev->core = core;
791
792	err = cx8802_init_common(dev);
793	if (err != 0)
794		goto fail_free;
795
796	INIT_LIST_HEAD(&dev->drvlist.devlist);
797	list_add_tail(&dev->devlist,&cx8802_devlist);
798
799	/* Maintain a reference so cx88-video can query the 8802 device. */
800	core->dvbdev = dev;
801
802	/* now autoload cx88-dvb or cx88-blackbird */
803	request_modules(dev);
804	return 0;
805
806 fail_free:
807	kfree(dev);
808 fail_core:
809	cx88_core_put(core,pci_dev);
810	return err;
811}
812
813static void __devexit cx8802_remove(struct pci_dev *pci_dev)
814{
815	struct cx8802_dev *dev;
816	struct cx8802_driver *h;
817	struct list_head *list;
818
819	dev = pci_get_drvdata(pci_dev);
820
821	dprintk( 1, "%s\n", __FUNCTION__);
822
823	list_for_each(list,&dev->drvlist.devlist) {
824		h = list_entry(list, struct cx8802_driver, devlist);
825		dprintk( 1, " ->driver\n");
826		if (h->remove == NULL) {
827			printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__);
828			continue;
829		}
830		printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id);
831		cx8802_unregister_driver(h);
832		list_del(&dev->drvlist.devlist);
833	}
834
835	/* Destroy any 8802 reference. */
836	dev->core->dvbdev = NULL;
837
838	/* common */
839	cx8802_fini_common(dev);
840	cx88_core_put(dev->core,dev->pci);
841	kfree(dev);
842}
843
844static struct pci_device_id cx8802_pci_tbl[] = {
845	{
846		.vendor       = 0x14f1,
847		.device       = 0x8802,
848		.subvendor    = PCI_ANY_ID,
849		.subdevice    = PCI_ANY_ID,
850	},{
851		/* --- end of list --- */
852	}
853};
854MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
855
856static struct pci_driver cx8802_pci_driver = {
857	.name     = "cx88-mpeg driver manager",
858	.id_table = cx8802_pci_tbl,
859	.probe    = cx8802_probe,
860	.remove   = __devexit_p(cx8802_remove),
861};
862
863static int cx8802_init(void)
864{
865	printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n",
866	       (CX88_VERSION_CODE >> 16) & 0xff,
867	       (CX88_VERSION_CODE >>  8) & 0xff,
868	       CX88_VERSION_CODE & 0xff);
869#ifdef SNAPSHOT
870	printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
871	       SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
872#endif
873	return pci_register_driver(&cx8802_pci_driver);
874}
875
876static void cx8802_fini(void)
877{
878	pci_unregister_driver(&cx8802_pci_driver);
879}
880
881module_init(cx8802_init);
882module_exit(cx8802_fini);
883EXPORT_SYMBOL(cx8802_buf_prepare);
884EXPORT_SYMBOL(cx8802_buf_queue);
885EXPORT_SYMBOL(cx8802_cancel_buffers);
886
887EXPORT_SYMBOL(cx8802_init_common);
888EXPORT_SYMBOL(cx8802_fini_common);
889
890EXPORT_SYMBOL(cx8802_register_driver);
891EXPORT_SYMBOL(cx8802_unregister_driver);
892EXPORT_SYMBOL(cx8802_get_device);
893EXPORT_SYMBOL(cx8802_get_driver);
894/* ----------------------------------------------------------- */
895/*
896 * Local variables:
897 * c-basic-offset: 8
898 * End:
899 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
900 */
901