~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/media/video/cx88/cx88-mpeg.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

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