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