[media] saa7164: irqhandler cleanup and helper function added
[deliverable/linux.git] / drivers / media / video / saa7164 / saa7164-core.c
CommitLineData
443c1228
ST
1/*
2 * Driver for the NXP SAA7164 PCIe bridge
3 *
9b8b0199 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
443c1228
ST
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 *
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <linux/init.h>
23#include <linux/list.h>
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/kmod.h>
27#include <linux/kernel.h>
28#include <linux/slab.h>
29#include <linux/interrupt.h>
30#include <linux/delay.h>
31#include <asm/div64.h>
32
33#include "saa7164.h"
34
35MODULE_DESCRIPTION("Driver for NXP SAA7164 based TV cards");
9d119c33 36MODULE_AUTHOR("Steven Toth <stoth@kernellabs.com>");
443c1228
ST
37MODULE_LICENSE("GPL");
38
39/*
40 1 Basic
41 2
42 4 i2c
43 8 api
44 16 cmd
45 32 bus
46 */
47
b1912a85
IM
48unsigned int saa_debug;
49module_param_named(debug, saa_debug, int, 0644);
443c1228
ST
50MODULE_PARM_DESC(debug, "enable debug messages");
51
66e1d378
ST
52unsigned int encoder_buffers = SAA7164_MAX_ENCODER_BUFFERS;
53module_param(encoder_buffers, int, 0644);
54MODULE_PARM_DESC(encoder_buffers, "Total buffers in read queue 16-512 def:64");
55
bbf504c3 56unsigned int waitsecs = 10;
dd1ee444 57module_param(waitsecs, int, 0644);
66e1d378 58MODULE_PARM_DESC(waitsecs, "timeout on firmware messages");
dd1ee444 59
443c1228
ST
60static unsigned int card[] = {[0 ... (SAA7164_MAXBOARDS - 1)] = UNSET };
61module_param_array(card, int, NULL, 0444);
62MODULE_PARM_DESC(card, "card type");
63
91d80189
ST
64unsigned int print_histogram = 64;
65module_param(print_histogram, int, 0644);
66e1d378 66MODULE_PARM_DESC(print_histogram, "print histogram values once");
91d80189 67
443c1228
ST
68static unsigned int saa7164_devcount;
69
70static DEFINE_MUTEX(devlist);
71LIST_HEAD(saa7164_devlist);
72
73#define INT_SIZE 16
74
12d3203e
ST
75void saa7164_dumphex16FF(struct saa7164_dev *dev, u8 *buf, int len)
76{
77 int i;
78 u8 tmp[16];
79 memset(&tmp[0], 0xff, sizeof(tmp));
80
81 printk(KERN_INFO "--------------------> "
82 "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
83
84 for (i = 0; i < len; i += 16) {
85 if (memcmp(&tmp, buf + i, sizeof(tmp)) != 0) {
86 printk(KERN_INFO " [0x%08x] "
87 "%02x %02x %02x %02x %02x %02x %02x %02x "
88 "%02x %02x %02x %02x %02x %02x %02x %02x\n", i,
89 *(buf+i+0), *(buf+i+1), *(buf+i+2), *(buf+i+3),
90 *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7),
91 *(buf+i+8), *(buf+i+9), *(buf+i+10), *(buf+i+11),
92 *(buf+i+12), *(buf+i+13), *(buf+i+14), *(buf+i+15));
93 }
94 }
95}
96
a97781ac
ST
97static void saa7164_pack_verifier(struct saa7164_buffer *buf)
98{
99 u8 *p = (u8 *)buf->cpu;
100 int i;
101
102 for (i = 0; i < buf->actual_size; i += 2048) {
103
104 if ( (*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) || (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA) )
105 printk(KERN_ERR "No pack at 0x%x\n", i);
106 }
107}
108
9230acaa
ST
109static void saa7164_ts_verifier(struct saa7164_buffer *buf)
110{
111 struct saa7164_port *port = buf->port;
9230acaa
ST
112 u32 i;
113 u8 tmp, cc, a;
114 u8 *bufcpu = (u8 *)buf->cpu;
115
116 port->sync_errors = 0;
117 port->v_cc_errors = 0;
118 port->a_cc_errors = 0;
119
120 for (i = 0; i < buf->actual_size; i += 188) {
121 if (*(bufcpu + i) != 0x47)
122 port->sync_errors++;
123
124 /* Query pid lower 8 bits */
125 tmp = *(bufcpu + i + 2);
126 cc = *(bufcpu + i + 3) & 0x0f;
127
128 if (tmp == 0xf1) {
129 a = ((port->last_v_cc + 1) & 0x0f);
130 if (a != cc) {
131 printk(KERN_ERR "video cc last = %x current = %x i = %d\n", port->last_v_cc, cc, i);
132 port->v_cc_errors++;
133 }
134
135 port->last_v_cc = cc;
136 } else
137 if (tmp == 0xf2) {
138 a = ((port->last_a_cc + 1) & 0x0f);
139 if (a != cc) {
140 printk(KERN_ERR "audio cc last = %x current = %x i = %d\n", port->last_a_cc, cc, i);
141 port->a_cc_errors++;
142 }
143
144 port->last_a_cc = cc;
145 }
146
147 }
148
149 if (port->v_cc_errors)
150 printk(KERN_ERR "video pid cc, %d errors\n", port->v_cc_errors);
151
152 if (port->a_cc_errors)
153 printk(KERN_ERR "audio pid cc, %d errors\n", port->a_cc_errors);
154
155 if (port->sync_errors)
156 printk(KERN_ERR "sync_errors = %d\n", port->sync_errors);
157}
158
91d80189 159static void saa7164_histogram_reset(struct saa7164_histogram *hg, char *name)
443c1228 160{
91d80189 161 int i;
443c1228 162
91d80189
ST
163 memset(hg, 0, sizeof(struct saa7164_histogram));
164 strcpy(hg->name, name);
165
166 /* First 30ms x 1ms */
167 for (i = 0; i < 30; i++) {
168 hg->counter1[0 + i].val = i;
169 }
170
171 /* 30 - 200ms x 10ms */
172 for (i = 0; i < 18; i++) {
173 hg->counter1[30 + i].val = 30 + (i * 10);
174 }
175
176 /* 200 - 2000ms x 100ms */
177 for (i = 0; i < 15; i++) {
58acca10 178 hg->counter1[48 + i].val = 200 + (i * 200);
91d80189
ST
179 }
180
58acca10
ST
181 /* Catch all massive value (2secs) */
182 hg->counter1[55].val = 2000;
183
184 /* Catch all massive value (4secs) */
185 hg->counter1[56].val = 4000;
186
187 /* Catch all massive value (8secs) */
188 hg->counter1[57].val = 8000;
189
190 /* Catch all massive value (15secs) */
191 hg->counter1[58].val = 15000;
192
193 /* Catch all massive value (30secs) */
194 hg->counter1[59].val = 30000;
195
196 /* Catch all massive value (60secs) */
197 hg->counter1[60].val = 60000;
198
199 /* Catch all massive value (5mins) */
200 hg->counter1[61].val = 300000;
201
202 /* Catch all massive value (15mins) */
203 hg->counter1[62].val = 900000;
204
205 /* Catch all massive values (1hr) */
91d80189 206 hg->counter1[63].val = 3600000;
443c1228
ST
207}
208
58acca10 209void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val)
443c1228 210{
91d80189
ST
211 int i;
212 for (i = 0; i < 64; i++ ) {
213 if (val <= hg->counter1[i].val) {
214 hg->counter1[i].count++;
215 hg->counter1[i].update_time = jiffies;
216 break;
217 }
218 }
219}
443c1228 220
91d80189
ST
221static void saa7164_histogram_print(struct saa7164_port *port,
222 struct saa7164_histogram *hg)
223{
91d80189
ST
224 u32 entries = 0;
225 int i;
226
58acca10 227 printk(KERN_ERR "Histogram named %s (ms, count, last_update_jiffy)\n", hg->name);
91d80189
ST
228 for (i = 0; i < 64; i++ ) {
229 if (hg->counter1[i].count == 0)
230 continue;
443c1228 231
91d80189
ST
232 printk(KERN_ERR " %4d %12d %Ld\n",
233 hg->counter1[i].val,
234 hg->counter1[i].count,
235 hg->counter1[i].update_time);
236
237 entries++;
238 }
239 printk(KERN_ERR "Total: %d\n", entries);
443c1228
ST
240}
241
cfbaf337 242static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr)
7615e434
ST
243{
244 struct saa7164_dev *dev = port->dev;
cfbaf337
ST
245 struct saa7164_buffer *buf = 0;
246 struct saa7164_user_buffer *ubuf = 0;
7615e434 247 struct list_head *c, *n;
cfbaf337 248 int i = 0;
91d80189
ST
249
250 mutex_lock(&port->dmaqueue_lock);
7615e434 251 list_for_each_safe(c, n, &port->dmaqueue.list) {
91d80189 252
7615e434 253 buf = list_entry(c, struct saa7164_buffer, list);
91d80189
ST
254 if (i++ > port->hwcfg.buffercount) {
255 printk(KERN_ERR "%s() illegal i count %d\n",
256 __func__, i);
257 break;
258 }
7615e434 259
cfbaf337 260 if (buf->idx == bufnr) {
12d3203e 261
7615e434 262 /* Found the buffer, deal with it */
cfbaf337 263 dprintk(DBGLVL_IRQ, "%s() rp: %d\n", __func__, bufnr);
7615e434 264
9230acaa
ST
265 /* Validate the incoming buffer content */
266 if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
267 saa7164_ts_verifier(buf);
a97781ac
ST
268 if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)
269 saa7164_pack_verifier(buf);
9230acaa 270
7615e434
ST
271 /* find a free user buffer and clone to it */
272 if (!list_empty(&port->list_buf_free.list)) {
273
274 /* Pull the first buffer from the used list */
275 ubuf = list_first_entry(&port->list_buf_free.list,
276 struct saa7164_user_buffer, list);
277
a97781ac
ST
278 if (buf->actual_size <= ubuf->actual_size) {
279
cfbaf337 280 memcpy_fromio(ubuf->data, buf->cpu,
f6eeece8 281 ubuf->actual_size);
12d3203e
ST
282
283 /* Throw a new checksum on the read buffer */
284 ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size);
285
a97781ac
ST
286 /* Requeue the buffer on the free list */
287 ubuf->pos = 0;
7615e434 288
a97781ac
ST
289 list_move_tail(&ubuf->list,
290 &port->list_buf_used.list);
7615e434 291
a97781ac
ST
292 /* Flag any userland waiters */
293 wake_up_interruptible(&port->wait_read);
7615e434 294
a97781ac
ST
295 } else {
296 printk(KERN_ERR "buf %p bufsize fails match\n", buf);
297 }
7615e434
ST
298
299 } else
66e1d378 300 printk(KERN_ERR "encirq no free buffers, increase param encoder_buffers\n");
7615e434 301
9230acaa 302 /* Ensure offset into buffer remains 0, fill buffer
a97781ac
ST
303 * with known bad data. We check for this data at a later point
304 * in time. */
cfbaf337 305 saa7164_buffer_zero_offsets(port, bufnr);
12d3203e 306 memset_io(buf->cpu, 0xff, buf->pci_size);
12d3203e 307
a97781ac 308 break;
cfbaf337
ST
309 }
310 }
311 mutex_unlock(&port->dmaqueue_lock);
312}
313
314static void saa7164_work_enchandler(struct work_struct *w)
315{
316 struct saa7164_port *port =
317 container_of(w, struct saa7164_port, workenc);
318 struct saa7164_dev *dev = port->dev;
319
320 u32 wp, mcb, rp, cnt = 0;
321
322 port->last_svc_msecs_diff = port->last_svc_msecs;
323 port->last_svc_msecs = jiffies_to_msecs(jiffies);
324
325 port->last_svc_msecs_diff = port->last_svc_msecs -
326 port->last_svc_msecs_diff;
327
328 saa7164_histogram_update(&port->svc_interval,
329 port->last_svc_msecs_diff);
330
331 port->last_irq_svc_msecs_diff = port->last_svc_msecs -
332 port->last_irq_msecs;
333
334 saa7164_histogram_update(&port->irq_svc_interval,
335 port->last_irq_svc_msecs_diff);
9230acaa 336
cfbaf337
ST
337 dprintk(DBGLVL_IRQ,
338 "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
339 __func__,
340 port->last_svc_msecs_diff,
341 port->last_irq_svc_msecs_diff,
342 port->last_svc_wp,
343 port->last_svc_rp
344 );
345
346 /* Current write position */
347 wp = saa7164_readl(port->bufcounter);
348 if (wp > (port->hwcfg.buffercount - 1)) {
349 printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
350 return;
351 }
352
353 /* Most current complete buffer */
354 if (wp == 0)
355 mcb = 7;
356 else
357 mcb = wp - 1;
358
359 while (1) {
360 rp = (port->last_svc_rp + 1) % 8;
361
362 if ((rp < 0) || (rp > 7)) {
363 printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
364 break;
7615e434
ST
365 }
366
cfbaf337
ST
367 /* Process a buffer */
368 if (port->nr == SAA7164_PORT_ENC1)
369 printk(KERN_ERR "Port enc1 processing buffer %d\n", rp);
370 saa7164_work_enchandler_helper(port, rp);
371 port->last_svc_rp = rp;
372 cnt++;
373
374 if (rp == mcb)
375 break;
7615e434 376 }
cfbaf337
ST
377
378 if (port->nr == SAA7164_PORT_ENC1)
379 printk(KERN_ERR "Enc1 processed %d buffers for port %p\n", cnt, port);
91d80189
ST
380
381 if (print_histogram == port->nr) {
382 saa7164_histogram_print(port, &port->irq_interval);
383 saa7164_histogram_print(port, &port->svc_interval);
384 saa7164_histogram_print(port, &port->irq_svc_interval);
58acca10
ST
385 saa7164_histogram_print(port, &port->read_interval);
386 saa7164_histogram_print(port, &port->poll_interval);
91d80189
ST
387 print_histogram = 64 + port->nr;
388 }
389}
cfbaf337 390
91d80189
ST
391static void saa7164_work_cmdhandler(struct work_struct *w)
392{
393 struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);
394
395 /* Wake up any complete commands */
396 saa7164_irq_dequeue(dev);
397}
398
399static void saa7164_buffer_deliver(struct saa7164_buffer *buf)
400{
401 struct saa7164_port *port = buf->port;
402
403 /* Feed the transport payload into the kernel demux */
404 dvb_dmx_swfilter_packets(&port->dvb.demux, (u8 *)buf->cpu,
405 SAA7164_TS_NUMBER_OF_LINES);
406
407}
408
409static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
410{
411 struct saa7164_dev *dev = port->dev;
07603131
ST
412
413 /* Store old time */
91d80189
ST
414 port->last_irq_msecs_diff = port->last_irq_msecs;
415
416 /* Collect new stats */
417 port->last_irq_msecs = jiffies_to_msecs(jiffies);
91d80189
ST
418
419 /* Calculate stats */
420 port->last_irq_msecs_diff = port->last_irq_msecs -
421 port->last_irq_msecs_diff;
422
423 saa7164_histogram_update(&port->irq_interval,
424 port->last_irq_msecs_diff);
425
cfbaf337
ST
426 dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,
427 port->last_irq_msecs_diff);
12d3203e 428
91d80189 429 schedule_work(&port->workenc);
7615e434
ST
430 return 0;
431}
432
add3f580 433static irqreturn_t saa7164_irq_ts(struct saa7164_port *port)
443c1228
ST
434{
435 struct saa7164_dev *dev = port->dev;
436 struct saa7164_buffer *buf;
437 struct list_head *c, *n;
438 int wp, i = 0, rp;
439
440 /* Find the current write point from the hardware */
441 wp = saa7164_readl(port->bufcounter);
442 if (wp > (port->hwcfg.buffercount - 1))
443 BUG();
444
445 /* Find the previous buffer to the current write point */
446 if (wp == 0)
447 rp = 7;
448 else
449 rp = wp - 1;
450
451 /* Lookup the WP in the buffer list */
452 /* TODO: turn this into a worker thread */
453 list_for_each_safe(c, n, &port->dmaqueue.list) {
454 buf = list_entry(c, struct saa7164_buffer, list);
455 if (i++ > port->hwcfg.buffercount)
456 BUG();
457
add3f580 458 if (buf->idx == rp) {
443c1228
ST
459 /* Found the buffer, deal with it */
460 dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d\n",
461 __func__, wp, rp);
462 saa7164_buffer_deliver(buf);
463 break;
464 }
465
466 }
467 return 0;
468}
469
470/* Primary IRQ handler and dispatch mechanism */
471static irqreturn_t saa7164_irq(int irq, void *dev_id)
472{
473 struct saa7164_dev *dev = dev_id;
7615e434
ST
474 struct saa7164_port *porta = &dev->ports[ SAA7164_PORT_TS1 ];
475 struct saa7164_port *portb = &dev->ports[ SAA7164_PORT_TS2 ];
476 struct saa7164_port *portc = &dev->ports[ SAA7164_PORT_ENC1 ];
477 struct saa7164_port *portd = &dev->ports[ SAA7164_PORT_ENC2 ];
478
50bcb4ae 479 u32 intid, intstat[INT_SIZE/4];
443c1228
ST
480 int i, handled = 0, bit;
481
d888ea03
ST
482 if (dev == 0) {
483 printk(KERN_ERR "%s() No device specified\n", __func__);
484 handled = 0;
485 goto out;
486 }
487
443c1228
ST
488 /* Check that the hardware is accessable. If the status bytes are
489 * 0xFF then the device is not accessable, the the IRQ belongs
490 * to another driver.
1a6450d4 491 * 4 x u32 interrupt registers.
443c1228
ST
492 */
493 for (i = 0; i < INT_SIZE/4; i++) {
494
495 /* TODO: Convert into saa7164_readl() */
496 /* Read the 4 hardware interrupt registers */
1a6450d4 497 intstat[i] = saa7164_readl(dev->int_status + (i * 4));
443c1228 498
50bcb4ae
ST
499 if (intstat[i])
500 handled = 1;
443c1228 501 }
50bcb4ae 502 if (handled == 0)
443c1228 503 goto out;
443c1228
ST
504
505 /* For each of the HW interrupt registers */
506 for (i = 0; i < INT_SIZE/4; i++) {
507
508 if (intstat[i]) {
509 /* Each function of the board has it's own interruptid.
510 * Find the function that triggered then call
511 * it's handler.
512 */
513 for (bit = 0; bit < 32; bit++) {
514
515 if (((intstat[i] >> bit) & 0x00000001) == 0)
516 continue;
517
518 /* Calculate the interrupt id (0x00 to 0x7f) */
519
50bcb4ae
ST
520 intid = (i * 32) + bit;
521 if (intid == dev->intfdesc.bInterruptId) {
443c1228
ST
522 /* A response to an cmd/api call */
523 schedule_work(&dev->workcmd);
7615e434 524 } else if (intid == porta->hwcfg.interruptid) {
443c1228
ST
525
526 /* Transport path 1 */
7615e434 527 saa7164_irq_ts(porta);
443c1228 528
7615e434 529 } else if (intid == portb->hwcfg.interruptid) {
443c1228
ST
530
531 /* Transport path 2 */
7615e434
ST
532 saa7164_irq_ts(portb);
533
534 } else if (intid == portc->hwcfg.interruptid) {
535
536 /* Encoder path 1 */
537 saa7164_irq_encoder(portc);
538
539 } else if (intid == portd->hwcfg.interruptid) {
540
541 /* Encoder path 1 */
542 saa7164_irq_encoder(portd);
443c1228
ST
543
544 } else {
545 /* Find the function */
546 dprintk(DBGLVL_IRQ,
547 "%s() unhandled interrupt "
548 "reg 0x%x bit 0x%x "
549 "intid = 0x%x\n",
50bcb4ae 550 __func__, i, bit, intid);
443c1228
ST
551 }
552 }
553
443c1228 554 /* Ack it */
1a6450d4 555 saa7164_writel(dev->int_ack + (i * 4), intstat[i]);
443c1228
ST
556
557 }
558 }
559out:
560 return IRQ_RETVAL(handled);
561}
562
563void saa7164_getfirmwarestatus(struct saa7164_dev *dev)
564{
565 struct saa7164_fw_status *s = &dev->fw_status;
566
567 dev->fw_status.status = saa7164_readl(SAA_DEVICE_SYSINIT_STATUS);
568 dev->fw_status.mode = saa7164_readl(SAA_DEVICE_SYSINIT_MODE);
569 dev->fw_status.spec = saa7164_readl(SAA_DEVICE_SYSINIT_SPEC);
570 dev->fw_status.inst = saa7164_readl(SAA_DEVICE_SYSINIT_INST);
571 dev->fw_status.cpuload = saa7164_readl(SAA_DEVICE_SYSINIT_CPULOAD);
572 dev->fw_status.remainheap =
573 saa7164_readl(SAA_DEVICE_SYSINIT_REMAINHEAP);
574
575 dprintk(1, "Firmware status:\n");
576 dprintk(1, " .status = 0x%08x\n", s->status);
577 dprintk(1, " .mode = 0x%08x\n", s->mode);
578 dprintk(1, " .spec = 0x%08x\n", s->spec);
579 dprintk(1, " .inst = 0x%08x\n", s->inst);
580 dprintk(1, " .cpuload = 0x%08x\n", s->cpuload);
581 dprintk(1, " .remainheap = 0x%08x\n", s->remainheap);
582}
583
584u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev)
585{
586 u32 reg;
587
588 reg = saa7164_readl(SAA_DEVICE_VERSION);
589 dprintk(1, "Device running firmware version %d.%d.%d.%d (0x%x)\n",
590 (reg & 0x0000fc00) >> 10,
591 (reg & 0x000003e0) >> 5,
592 (reg & 0x0000001f),
593 (reg & 0xffff0000) >> 16,
594 reg);
595
596 return reg;
597}
598
599/* TODO: Debugging func, remove */
600void saa7164_dumphex16(struct saa7164_dev *dev, u8 *buf, int len)
601{
602 int i;
603
604 printk(KERN_INFO "--------------------> "
605 "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
606
607 for (i = 0; i < len; i += 16)
608 printk(KERN_INFO " [0x%08x] "
609 "%02x %02x %02x %02x %02x %02x %02x %02x "
610 "%02x %02x %02x %02x %02x %02x %02x %02x\n", i,
611 *(buf+i+0), *(buf+i+1), *(buf+i+2), *(buf+i+3),
612 *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7),
613 *(buf+i+8), *(buf+i+9), *(buf+i+10), *(buf+i+11),
614 *(buf+i+12), *(buf+i+13), *(buf+i+14), *(buf+i+15));
615}
616
617/* TODO: Debugging func, remove */
618void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr)
619{
620 int i;
621
622 dprintk(1, "--------------------> "
623 "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
624
625 for (i = 0; i < 0x100; i += 16)
626 dprintk(1, "region0[0x%08x] = "
627 "%02x %02x %02x %02x %02x %02x %02x %02x"
628 " %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
629 (u8)saa7164_readb(addr + i + 0),
630 (u8)saa7164_readb(addr + i + 1),
631 (u8)saa7164_readb(addr + i + 2),
632 (u8)saa7164_readb(addr + i + 3),
633 (u8)saa7164_readb(addr + i + 4),
634 (u8)saa7164_readb(addr + i + 5),
635 (u8)saa7164_readb(addr + i + 6),
636 (u8)saa7164_readb(addr + i + 7),
637 (u8)saa7164_readb(addr + i + 8),
638 (u8)saa7164_readb(addr + i + 9),
639 (u8)saa7164_readb(addr + i + 10),
640 (u8)saa7164_readb(addr + i + 11),
641 (u8)saa7164_readb(addr + i + 12),
642 (u8)saa7164_readb(addr + i + 13),
643 (u8)saa7164_readb(addr + i + 14),
644 (u8)saa7164_readb(addr + i + 15)
645 );
646}
647
648static void saa7164_dump_hwdesc(struct saa7164_dev *dev)
649{
207b42c4
ST
650 dprintk(1, "@0x%p hwdesc sizeof(tmComResHWDescr_t) = %d bytes\n",
651 &dev->hwdesc, (u32)sizeof(tmComResHWDescr_t));
443c1228
ST
652
653 dprintk(1, " .bLength = 0x%x\n", dev->hwdesc.bLength);
654 dprintk(1, " .bDescriptorType = 0x%x\n", dev->hwdesc.bDescriptorType);
655 dprintk(1, " .bDescriptorSubtype = 0x%x\n",
656 dev->hwdesc.bDescriptorSubtype);
657
658 dprintk(1, " .bcdSpecVersion = 0x%x\n", dev->hwdesc.bcdSpecVersion);
659 dprintk(1, " .dwClockFrequency = 0x%x\n", dev->hwdesc.dwClockFrequency);
660 dprintk(1, " .dwClockUpdateRes = 0x%x\n", dev->hwdesc.dwClockUpdateRes);
661 dprintk(1, " .bCapabilities = 0x%x\n", dev->hwdesc.bCapabilities);
662 dprintk(1, " .dwDeviceRegistersLocation = 0x%x\n",
663 dev->hwdesc.dwDeviceRegistersLocation);
664
665 dprintk(1, " .dwHostMemoryRegion = 0x%x\n",
666 dev->hwdesc.dwHostMemoryRegion);
667
668 dprintk(1, " .dwHostMemoryRegionSize = 0x%x\n",
669 dev->hwdesc.dwHostMemoryRegionSize);
670
671 dprintk(1, " .dwHostHibernatMemRegion = 0x%x\n",
672 dev->hwdesc.dwHostHibernatMemRegion);
673
674 dprintk(1, " .dwHostHibernatMemRegionSize = 0x%x\n",
675 dev->hwdesc.dwHostHibernatMemRegionSize);
676}
677
678static void saa7164_dump_intfdesc(struct saa7164_dev *dev)
679{
680 dprintk(1, "@0x%p intfdesc "
207b42c4
ST
681 "sizeof(tmComResInterfaceDescr_t) = %d bytes\n",
682 &dev->intfdesc, (u32)sizeof(tmComResInterfaceDescr_t));
443c1228
ST
683
684 dprintk(1, " .bLength = 0x%x\n", dev->intfdesc.bLength);
685 dprintk(1, " .bDescriptorType = 0x%x\n", dev->intfdesc.bDescriptorType);
686 dprintk(1, " .bDescriptorSubtype = 0x%x\n",
687 dev->intfdesc.bDescriptorSubtype);
688
689 dprintk(1, " .bFlags = 0x%x\n", dev->intfdesc.bFlags);
690 dprintk(1, " .bInterfaceType = 0x%x\n", dev->intfdesc.bInterfaceType);
691 dprintk(1, " .bInterfaceId = 0x%x\n", dev->intfdesc.bInterfaceId);
692 dprintk(1, " .bBaseInterface = 0x%x\n", dev->intfdesc.bBaseInterface);
693 dprintk(1, " .bInterruptId = 0x%x\n", dev->intfdesc.bInterruptId);
694 dprintk(1, " .bDebugInterruptId = 0x%x\n",
695 dev->intfdesc.bDebugInterruptId);
696
697 dprintk(1, " .BARLocation = 0x%x\n", dev->intfdesc.BARLocation);
698}
699
700static void saa7164_dump_busdesc(struct saa7164_dev *dev)
701{
207b42c4
ST
702 dprintk(1, "@0x%p busdesc sizeof(tmComResBusDescr_t) = %d bytes\n",
703 &dev->busdesc, (u32)sizeof(tmComResBusDescr_t));
443c1228
ST
704
705 dprintk(1, " .CommandRing = 0x%016Lx\n", dev->busdesc.CommandRing);
706 dprintk(1, " .ResponseRing = 0x%016Lx\n", dev->busdesc.ResponseRing);
707 dprintk(1, " .CommandWrite = 0x%x\n", dev->busdesc.CommandWrite);
708 dprintk(1, " .CommandRead = 0x%x\n", dev->busdesc.CommandRead);
709 dprintk(1, " .ResponseWrite = 0x%x\n", dev->busdesc.ResponseWrite);
710 dprintk(1, " .ResponseRead = 0x%x\n", dev->busdesc.ResponseRead);
711}
712
713/* Much of the hardware configuration and PCI registers are configured
714 * dynamically depending on firmware. We have to cache some initial
715 * structures then use these to locate other important structures
716 * from PCI space.
717 */
718static void saa7164_get_descriptors(struct saa7164_dev *dev)
719{
12d3203e
ST
720 memcpy_fromio(&dev->hwdesc, dev->bmmio, sizeof(tmComResHWDescr_t));
721 memcpy_fromio(&dev->intfdesc, dev->bmmio + sizeof(tmComResHWDescr_t),
443c1228 722 sizeof(tmComResInterfaceDescr_t));
12d3203e 723 memcpy_fromio(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation,
443c1228
ST
724 sizeof(tmComResBusDescr_t));
725
726 if (dev->hwdesc.bLength != sizeof(tmComResHWDescr_t)) {
727 printk(KERN_ERR "Structure tmComResHWDescr_t is mangled\n");
207b42c4
ST
728 printk(KERN_ERR "Need %x got %d\n", dev->hwdesc.bLength,
729 (u32)sizeof(tmComResHWDescr_t));
443c1228
ST
730 } else
731 saa7164_dump_hwdesc(dev);
732
733 if (dev->intfdesc.bLength != sizeof(tmComResInterfaceDescr_t)) {
734 printk(KERN_ERR "struct tmComResInterfaceDescr_t is mangled\n");
207b42c4
ST
735 printk(KERN_ERR "Need %x got %d\n", dev->intfdesc.bLength,
736 (u32)sizeof(tmComResInterfaceDescr_t));
443c1228
ST
737 } else
738 saa7164_dump_intfdesc(dev);
739
740 saa7164_dump_busdesc(dev);
741}
742
743static int saa7164_pci_quirks(struct saa7164_dev *dev)
744{
745 return 0;
746}
747
748static int get_resources(struct saa7164_dev *dev)
749{
750 if (request_mem_region(pci_resource_start(dev->pci, 0),
751 pci_resource_len(dev->pci, 0), dev->name)) {
752
753 if (request_mem_region(pci_resource_start(dev->pci, 2),
754 pci_resource_len(dev->pci, 2), dev->name))
755 return 0;
756 }
757
758 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx or 0x%llx\n",
759 dev->name,
760 (u64)pci_resource_start(dev->pci, 0),
761 (u64)pci_resource_start(dev->pci, 2));
762
763 return -EBUSY;
764}
765
7615e434
ST
766static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
767{
768 struct saa7164_port *port = 0;
12d3203e 769 int i;
7615e434
ST
770
771 if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS))
772 BUG();
773
774 port = &dev->ports[ portnr ];
775
776 port->dev = dev;
777 port->nr = portnr;
778
779 if ((portnr == SAA7164_PORT_TS1) || (portnr == SAA7164_PORT_TS2))
780 port->type = SAA7164_MPEG_DVB;
781 else
782 if ((portnr == SAA7164_PORT_ENC1) || (portnr == SAA7164_PORT_ENC2))
783 port->type = SAA7164_MPEG_ENCODER;
784 else
785 BUG();
786
787 /* Init all the critical resources */
788 mutex_init(&port->dvb.lock);
789 INIT_LIST_HEAD(&port->dmaqueue.list);
790 mutex_init(&port->dmaqueue_lock);
791
792 INIT_LIST_HEAD(&port->list_buf_used.list);
793 INIT_LIST_HEAD(&port->list_buf_free.list);
794 init_waitqueue_head(&port->wait_read);
91d80189
ST
795
796 /* We need a deferred interrupt handler for cmd handling */
797 INIT_WORK(&port->workenc, saa7164_work_enchandler);
798
799 saa7164_histogram_reset(&port->irq_interval, "irq intervals");
800 saa7164_histogram_reset(&port->svc_interval, "deferred intervals");
801 saa7164_histogram_reset(&port->irq_svc_interval,
802 "irq to deferred intervals");
58acca10
ST
803 saa7164_histogram_reset(&port->read_interval,
804 "encoder read() intervals");
805 saa7164_histogram_reset(&port->poll_interval,
806 "encoder poll() intervals");
91d80189 807
12d3203e
ST
808 if (port->type == SAA7164_MPEG_ENCODER) {
809 for (i = 0; i < 8; i ++) {
a97781ac 810 port->shadow_buf[i] = kzalloc(256 * 128, GFP_KERNEL);
12d3203e
ST
811 if (port->shadow_buf[i] == 0)
812 printk(KERN_ERR "%s() shadow_buf ENOMEM\n", __func__);
813 else {
a97781ac
ST
814 memset(port->shadow_buf[i], 0xff, 256 * 128);
815 port->shadow_crc[i] = crc32(0, port->shadow_buf[i], 256 * 128);
12d3203e
ST
816 }
817 }
818 }
819
7615e434
ST
820 return 0;
821}
822
443c1228
ST
823static int saa7164_dev_setup(struct saa7164_dev *dev)
824{
825 int i;
826
827 mutex_init(&dev->lock);
828 atomic_inc(&dev->refcount);
829 dev->nr = saa7164_devcount++;
830
831 sprintf(dev->name, "saa7164[%d]", dev->nr);
832
833 mutex_lock(&devlist);
834 list_add_tail(&dev->devlist, &saa7164_devlist);
835 mutex_unlock(&devlist);
836
837 /* board config */
838 dev->board = UNSET;
839 if (card[dev->nr] < saa7164_bcount)
840 dev->board = card[dev->nr];
841
842 for (i = 0; UNSET == dev->board && i < saa7164_idcount; i++)
843 if (dev->pci->subsystem_vendor == saa7164_subids[i].subvendor &&
844 dev->pci->subsystem_device ==
845 saa7164_subids[i].subdevice)
846 dev->board = saa7164_subids[i].card;
847
848 if (UNSET == dev->board) {
849 dev->board = SAA7164_BOARD_UNKNOWN;
850 saa7164_card_list(dev);
851 }
852
853 dev->pci_bus = dev->pci->bus->number;
854 dev->pci_slot = PCI_SLOT(dev->pci->devfn);
855
856 /* I2C Defaults / setup */
857 dev->i2c_bus[0].dev = dev;
858 dev->i2c_bus[0].nr = 0;
859 dev->i2c_bus[1].dev = dev;
860 dev->i2c_bus[1].nr = 1;
861 dev->i2c_bus[2].dev = dev;
862 dev->i2c_bus[2].nr = 2;
863
7615e434
ST
864 /* Transport + Encoder ports 1, 2, 3, 4 - Defaults / setup */
865 saa7164_port_init(dev, SAA7164_PORT_TS1);
866 saa7164_port_init(dev, SAA7164_PORT_TS2);
867 saa7164_port_init(dev, SAA7164_PORT_ENC1);
868 saa7164_port_init(dev, SAA7164_PORT_ENC2);
443c1228
ST
869
870 if (get_resources(dev) < 0) {
871 printk(KERN_ERR "CORE %s No more PCIe resources for "
872 "subsystem: %04x:%04x\n",
873 dev->name, dev->pci->subsystem_vendor,
874 dev->pci->subsystem_device);
875
876 saa7164_devcount--;
877 return -ENODEV;
878 }
879
880 /* PCI/e allocations */
881 dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
882 pci_resource_len(dev->pci, 0));
883
884 dev->lmmio2 = ioremap(pci_resource_start(dev->pci, 2),
885 pci_resource_len(dev->pci, 2));
886
443c1228
ST
887 dev->bmmio = (u8 __iomem *)dev->lmmio;
888 dev->bmmio2 = (u8 __iomem *)dev->lmmio2;
443c1228 889
1a6450d4
ST
890 /* Inerrupt and ack register locations offset of bmmio */
891 dev->int_status = 0x183000 + 0xf80;
892 dev->int_ack = 0x183000 + 0xf90;
443c1228
ST
893
894 printk(KERN_INFO
895 "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
896 dev->name, dev->pci->subsystem_vendor,
897 dev->pci->subsystem_device, saa7164_boards[dev->board].name,
898 dev->board, card[dev->nr] == dev->board ?
899 "insmod option" : "autodetected");
900
901 saa7164_pci_quirks(dev);
902
903 return 0;
904}
905
906static void saa7164_dev_unregister(struct saa7164_dev *dev)
907{
908 dprintk(1, "%s()\n", __func__);
909
910 release_mem_region(pci_resource_start(dev->pci, 0),
911 pci_resource_len(dev->pci, 0));
912
913 release_mem_region(pci_resource_start(dev->pci, 2),
914 pci_resource_len(dev->pci, 2));
915
916 if (!atomic_dec_and_test(&dev->refcount))
917 return;
918
919 iounmap(dev->lmmio);
920 iounmap(dev->lmmio2);
921
922 return;
923}
924
925static int __devinit saa7164_initdev(struct pci_dev *pci_dev,
926 const struct pci_device_id *pci_id)
927{
928 struct saa7164_dev *dev;
929 int err, i;
930 u32 version;
931
932 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
933 if (NULL == dev)
934 return -ENOMEM;
935
936 /* pci init */
937 dev->pci = pci_dev;
938 if (pci_enable_device(pci_dev)) {
939 err = -EIO;
940 goto fail_free;
941 }
942
943 if (saa7164_dev_setup(dev) < 0) {
944 err = -EINVAL;
945 goto fail_free;
946 }
947
948 /* print pci info */
949 pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
950 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
951 printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
952 "latency: %d, mmio: 0x%llx\n", dev->name,
953 pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
954 dev->pci_lat,
955 (unsigned long long)pci_resource_start(pci_dev, 0));
956
957 pci_set_master(pci_dev);
958 /* TODO */
959 if (!pci_dma_supported(pci_dev, 0xffffffff)) {
960 printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
961 err = -EIO;
962 goto fail_irq;
963 }
964
965 err = request_irq(pci_dev->irq, saa7164_irq,
966 IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
967 if (err < 0) {
968 printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
969 pci_dev->irq);
970 err = -EIO;
971 goto fail_irq;
972 }
973
974 pci_set_drvdata(pci_dev, dev);
975
443c1228
ST
976 /* Init the internal command list */
977 for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {
978 dev->cmds[i].seqno = i;
979 dev->cmds[i].inuse = 0;
980 mutex_init(&dev->cmds[i].lock);
981 init_waitqueue_head(&dev->cmds[i].wait);
982 }
983
984 /* We need a deferred interrupt handler for cmd handling */
985 INIT_WORK(&dev->workcmd, saa7164_work_cmdhandler);
986
987 /* Only load the firmware if we know the board */
988 if (dev->board != SAA7164_BOARD_UNKNOWN) {
989
990 err = saa7164_downloadfirmware(dev);
991 if (err < 0) {
992 printk(KERN_ERR
50bcb4ae
ST
993 "Failed to boot firmware, no features "
994 "registered\n");
995 goto fail_fw;
443c1228
ST
996 }
997
998 saa7164_get_descriptors(dev);
999 saa7164_dumpregs(dev, 0);
1000 saa7164_getcurrentfirmwareversion(dev);
1001 saa7164_getfirmwarestatus(dev);
1002 err = saa7164_bus_setup(dev);
1003 if (err < 0)
1004 printk(KERN_ERR
1005 "Failed to setup the bus, will continue\n");
1006 saa7164_bus_dump(dev);
1007
1008 /* Ping the running firmware via the command bus and get the
1009 * firmware version, this checks the bus is running OK.
1010 */
1011 version = 0;
1012 if (saa7164_api_get_fw_version(dev, &version) == SAA_OK)
1013 dprintk(1, "Bus is operating correctly using "
1014 "version %d.%d.%d.%d (0x%x)\n",
1015 (version & 0x0000fc00) >> 10,
1016 (version & 0x000003e0) >> 5,
1017 (version & 0x0000001f),
1018 (version & 0xffff0000) >> 16,
1019 version);
1020 else
1021 printk(KERN_ERR
1022 "Failed to communicate with the firmware\n");
1023
1024 /* Bring up the I2C buses */
1025 saa7164_i2c_register(&dev->i2c_bus[0]);
1026 saa7164_i2c_register(&dev->i2c_bus[1]);
1027 saa7164_i2c_register(&dev->i2c_bus[2]);
1028 saa7164_gpio_setup(dev);
1029 saa7164_card_setup(dev);
1030
1031
1032 /* Parse the dynamic device configuration, find various
1033 * media endpoints (MPEG, WMV, PS, TS) and cache their
1034 * configuration details into the driver, so we can
1035 * reference them later during simething_register() func,
1036 * interrupt handlers, deferred work handlers etc.
1037 */
1038 saa7164_api_enum_subdevs(dev);
1039
443c1228
ST
1040 /* Begin to create the video sub-systems and register funcs */
1041 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) {
7615e434 1042 if (saa7164_dvb_register(&dev->ports[ SAA7164_PORT_TS1 ]) < 0) {
443c1228
ST
1043 printk(KERN_ERR "%s() Failed to register "
1044 "dvb adapters on porta\n",
1045 __func__);
1046 }
1047 }
1048
1049 if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) {
7615e434 1050 if (saa7164_dvb_register(&dev->ports[ SAA7164_PORT_TS2 ]) < 0) {
443c1228
ST
1051 printk(KERN_ERR"%s() Failed to register "
1052 "dvb adapters on portb\n",
1053 __func__);
1054 }
1055 }
1056
7615e434
ST
1057 if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER) {
1058 if (saa7164_encoder_register(&dev->ports[ SAA7164_PORT_ENC1 ]) < 0) {
1059 printk(KERN_ERR"%s() Failed to register "
1060 "mpeg encoder\n", __func__);
1061 }
1062 }
1063
1064 if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER) {
1065 if (saa7164_encoder_register(&dev->ports[ SAA7164_PORT_ENC2 ]) < 0) {
1066 printk(KERN_ERR"%s() Failed to register "
1067 "mpeg encoder\n", __func__);
1068 }
1069 }
1070
443c1228
ST
1071 } /* != BOARD_UNKNOWN */
1072 else
1073 printk(KERN_ERR "%s() Unsupported board detected, "
1074 "registering without firmware\n", __func__);
1075
b1912a85 1076 dprintk(1, "%s() parameter debug = %d\n", __func__, saa_debug);
2ceae8fd
ST
1077 dprintk(1, "%s() parameter waitsecs = %d\n", __func__, waitsecs);
1078
50bcb4ae 1079fail_fw:
443c1228
ST
1080 return 0;
1081
1082fail_irq:
1083 saa7164_dev_unregister(dev);
1084fail_free:
1085 kfree(dev);
1086 return err;
1087}
1088
1089static void saa7164_shutdown(struct saa7164_dev *dev)
1090{
1091 dprintk(1, "%s()\n", __func__);
1092}
1093
1094static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
1095{
1096 struct saa7164_dev *dev = pci_get_drvdata(pci_dev);
12d3203e
ST
1097 struct saa7164_port *port;
1098 int i;
443c1228 1099
91d80189
ST
1100 saa7164_histogram_print(&dev->ports[ SAA7164_PORT_ENC1 ],
1101 &dev->ports[ SAA7164_PORT_ENC1 ].irq_interval);
1102 saa7164_histogram_print(&dev->ports[ SAA7164_PORT_ENC1 ],
1103 &dev->ports[ SAA7164_PORT_ENC1 ].svc_interval);
1104 saa7164_histogram_print(&dev->ports[ SAA7164_PORT_ENC1 ],
1105 &dev->ports[ SAA7164_PORT_ENC1 ].irq_svc_interval);
58acca10
ST
1106 saa7164_histogram_print(&dev->ports[ SAA7164_PORT_ENC1 ],
1107 &dev->ports[ SAA7164_PORT_ENC1 ].read_interval);
1108 saa7164_histogram_print(&dev->ports[ SAA7164_PORT_ENC1 ],
1109 &dev->ports[ SAA7164_PORT_ENC1 ].poll_interval);
91d80189 1110
443c1228
ST
1111 saa7164_shutdown(dev);
1112
12d3203e
ST
1113 port = &dev->ports[ SAA7164_PORT_ENC1 ];
1114 if (port->type == SAA7164_MPEG_ENCODER) {
1115 for (i = 0; i < 8; i ++) {
1116 kfree(port->shadow_buf[i]);
1117 port->shadow_buf[i] = 0;
1118 }
1119 }
1120 port = &dev->ports[ SAA7164_PORT_ENC2 ];
1121 if (port->type == SAA7164_MPEG_ENCODER) {
1122 for (i = 0; i < 8; i ++) {
1123 kfree(port->shadow_buf[i]);
1124 port->shadow_buf[i] = 0;
1125 }
1126 }
1127
1128
443c1228 1129 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB)
7615e434 1130 saa7164_dvb_unregister(&dev->ports[ SAA7164_PORT_TS1 ]);
443c1228
ST
1131
1132 if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB)
7615e434
ST
1133 saa7164_dvb_unregister(&dev->ports[ SAA7164_PORT_TS2 ]);
1134
1135 if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER)
1136 saa7164_encoder_unregister(&dev->ports[ SAA7164_PORT_ENC1 ]);
1137
1138 if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER)
1139 saa7164_encoder_unregister(&dev->ports[ SAA7164_PORT_ENC2 ]);
443c1228
ST
1140
1141 saa7164_i2c_unregister(&dev->i2c_bus[0]);
1142 saa7164_i2c_unregister(&dev->i2c_bus[1]);
1143 saa7164_i2c_unregister(&dev->i2c_bus[2]);
1144
1145 pci_disable_device(pci_dev);
1146
1147 /* unregister stuff */
1148 free_irq(pci_dev->irq, dev);
1149 pci_set_drvdata(pci_dev, NULL);
1150
1151 mutex_lock(&devlist);
1152 list_del(&dev->devlist);
1153 mutex_unlock(&devlist);
1154
1155 saa7164_dev_unregister(dev);
1156 kfree(dev);
1157}
1158
1159static struct pci_device_id saa7164_pci_tbl[] = {
1160 {
1161 /* SAA7164 */
1162 .vendor = 0x1131,
1163 .device = 0x7164,
1164 .subvendor = PCI_ANY_ID,
1165 .subdevice = PCI_ANY_ID,
1166 }, {
1167 /* --- end of list --- */
1168 }
1169};
1170MODULE_DEVICE_TABLE(pci, saa7164_pci_tbl);
1171
1172static struct pci_driver saa7164_pci_driver = {
1173 .name = "saa7164",
1174 .id_table = saa7164_pci_tbl,
1175 .probe = saa7164_initdev,
1176 .remove = __devexit_p(saa7164_finidev),
1177 /* TODO */
1178 .suspend = NULL,
1179 .resume = NULL,
1180};
1181
9d440a08 1182static int __init saa7164_init(void)
443c1228
ST
1183{
1184 printk(KERN_INFO "saa7164 driver loaded\n");
1185 return pci_register_driver(&saa7164_pci_driver);
1186}
1187
9d440a08 1188static void __exit saa7164_fini(void)
443c1228
ST
1189{
1190 pci_unregister_driver(&saa7164_pci_driver);
1191}
1192
1193module_init(saa7164_init);
1194module_exit(saa7164_fini);
1195
This page took 0.15991 seconds and 5 git commands to generate.