1554 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for the NXP SAA7164 PCIe bridge4 *5 * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>6 */7 8#include <linux/init.h>9#include <linux/list.h>10#include <linux/module.h>11#include <linux/moduleparam.h>12#include <linux/kmod.h>13#include <linux/kernel.h>14#include <linux/slab.h>15#include <linux/interrupt.h>16#include <linux/debugfs.h>17#include <linux/delay.h>18#include <asm/div64.h>19 20#include "saa7164.h"21 22MODULE_DESCRIPTION("Driver for NXP SAA7164 based TV cards");23MODULE_AUTHOR("Steven Toth <stoth@kernellabs.com>");24MODULE_LICENSE("GPL");25 26/*27 * 1 Basic28 * 229 * 4 i2c30 * 8 api31 * 16 cmd32 * 32 bus33 */34 35unsigned int saa_debug;36module_param_named(debug, saa_debug, int, 0644);37MODULE_PARM_DESC(debug, "enable debug messages");38 39static unsigned int fw_debug;40module_param(fw_debug, int, 0644);41MODULE_PARM_DESC(fw_debug, "Firmware debug level def:2");42 43unsigned int encoder_buffers = SAA7164_MAX_ENCODER_BUFFERS;44module_param(encoder_buffers, int, 0644);45MODULE_PARM_DESC(encoder_buffers, "Total buffers in read queue 16-512 def:64");46 47unsigned int vbi_buffers = SAA7164_MAX_VBI_BUFFERS;48module_param(vbi_buffers, int, 0644);49MODULE_PARM_DESC(vbi_buffers, "Total buffers in read queue 16-512 def:64");50 51unsigned int waitsecs = 10;52module_param(waitsecs, int, 0644);53MODULE_PARM_DESC(waitsecs, "timeout on firmware messages");54 55static unsigned int card[] = {[0 ... (SAA7164_MAXBOARDS - 1)] = UNSET };56module_param_array(card, int, NULL, 0444);57MODULE_PARM_DESC(card, "card type");58 59static unsigned int print_histogram = 64;60module_param(print_histogram, int, 0644);61MODULE_PARM_DESC(print_histogram, "print histogram values once");62 63unsigned int crc_checking = 1;64module_param(crc_checking, int, 0644);65MODULE_PARM_DESC(crc_checking, "enable crc sanity checking on buffers");66 67static unsigned int guard_checking = 1;68module_param(guard_checking, int, 0644);69MODULE_PARM_DESC(guard_checking,70 "enable dma sanity checking for buffer overruns");71 72static bool enable_msi = true;73module_param(enable_msi, bool, 0444);74MODULE_PARM_DESC(enable_msi,75 "enable the use of an msi interrupt if available");76 77static unsigned int saa7164_devcount;78 79static DEFINE_MUTEX(devlist);80LIST_HEAD(saa7164_devlist);81 82#define INT_SIZE 1683 84static void saa7164_pack_verifier(struct saa7164_buffer *buf)85{86 u8 *p = (u8 *)buf->cpu;87 int i;88 89 for (i = 0; i < buf->actual_size; i += 2048) {90 91 if ((*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) ||92 (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA)) {93 printk(KERN_ERR "No pack at 0x%x\n", i);94#if 095 print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,96 p + 1, 32, false);97#endif98 }99 }100}101 102#define FIXED_VIDEO_PID 0xf1103#define FIXED_AUDIO_PID 0xf2104 105static void saa7164_ts_verifier(struct saa7164_buffer *buf)106{107 struct saa7164_port *port = buf->port;108 u32 i;109 u8 cc, a;110 u16 pid;111 u8 *bufcpu = (u8 *)buf->cpu;112 113 port->sync_errors = 0;114 port->v_cc_errors = 0;115 port->a_cc_errors = 0;116 117 for (i = 0; i < buf->actual_size; i += 188) {118 if (*(bufcpu + i) != 0x47)119 port->sync_errors++;120 121 /* TODO: Query pid lower 8 bits, ignoring upper bits intensionally */122 pid = ((*(bufcpu + i + 1) & 0x1f) << 8) | *(bufcpu + i + 2);123 cc = *(bufcpu + i + 3) & 0x0f;124 125 if (pid == FIXED_VIDEO_PID) {126 a = ((port->last_v_cc + 1) & 0x0f);127 if (a != cc) {128 printk(KERN_ERR "video cc last = %x current = %x i = %d\n",129 port->last_v_cc, cc, i);130 port->v_cc_errors++;131 }132 133 port->last_v_cc = cc;134 } else135 if (pid == FIXED_AUDIO_PID) {136 a = ((port->last_a_cc + 1) & 0x0f);137 if (a != cc) {138 printk(KERN_ERR "audio cc last = %x current = %x i = %d\n",139 port->last_a_cc, cc, i);140 port->a_cc_errors++;141 }142 143 port->last_a_cc = cc;144 }145 146 }147 148 /* Only report errors if we've been through this function at least149 * once already and the cached cc values are primed. First time through150 * always generates errors.151 */152 if (port->v_cc_errors && (port->done_first_interrupt > 1))153 printk(KERN_ERR "video pid cc, %d errors\n", port->v_cc_errors);154 155 if (port->a_cc_errors && (port->done_first_interrupt > 1))156 printk(KERN_ERR "audio pid cc, %d errors\n", port->a_cc_errors);157 158 if (port->sync_errors && (port->done_first_interrupt > 1))159 printk(KERN_ERR "sync_errors = %d\n", port->sync_errors);160 161 if (port->done_first_interrupt == 1)162 port->done_first_interrupt++;163}164 165static void saa7164_histogram_reset(struct saa7164_histogram *hg, char *name)166{167 int i;168 169 memset(hg, 0, sizeof(struct saa7164_histogram));170 strscpy(hg->name, name, sizeof(hg->name));171 172 /* First 30ms x 1ms */173 for (i = 0; i < 30; i++)174 hg->counter1[0 + i].val = i;175 176 /* 30 - 200ms x 10ms */177 for (i = 0; i < 18; i++)178 hg->counter1[30 + i].val = 30 + (i * 10);179 180 /* 200 - 2000ms x 100ms */181 for (i = 0; i < 15; i++)182 hg->counter1[48 + i].val = 200 + (i * 200);183 184 /* Catch all massive value (2secs) */185 hg->counter1[55].val = 2000;186 187 /* Catch all massive value (4secs) */188 hg->counter1[56].val = 4000;189 190 /* Catch all massive value (8secs) */191 hg->counter1[57].val = 8000;192 193 /* Catch all massive value (15secs) */194 hg->counter1[58].val = 15000;195 196 /* Catch all massive value (30secs) */197 hg->counter1[59].val = 30000;198 199 /* Catch all massive value (60secs) */200 hg->counter1[60].val = 60000;201 202 /* Catch all massive value (5mins) */203 hg->counter1[61].val = 300000;204 205 /* Catch all massive value (15mins) */206 hg->counter1[62].val = 900000;207 208 /* Catch all massive values (1hr) */209 hg->counter1[63].val = 3600000;210}211 212void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val)213{214 int i;215 for (i = 0; i < 64; i++) {216 if (val <= hg->counter1[i].val) {217 hg->counter1[i].count++;218 hg->counter1[i].update_time = jiffies;219 break;220 }221 }222}223 224static void saa7164_histogram_print(struct saa7164_port *port,225 struct saa7164_histogram *hg)226{227 u32 entries = 0;228 int i;229 230 printk(KERN_ERR "Histogram named %s (ms, count, last_update_jiffy)\n", hg->name);231 for (i = 0; i < 64; i++) {232 if (hg->counter1[i].count == 0)233 continue;234 235 printk(KERN_ERR " %4d %12d %Ld\n",236 hg->counter1[i].val,237 hg->counter1[i].count,238 hg->counter1[i].update_time);239 240 entries++;241 }242 printk(KERN_ERR "Total: %d\n", entries);243}244 245static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr)246{247 struct saa7164_dev *dev = port->dev;248 struct saa7164_buffer *buf = NULL;249 struct saa7164_user_buffer *ubuf = NULL;250 struct list_head *c, *n;251 int i = 0;252 u8 *p;253 254 mutex_lock(&port->dmaqueue_lock);255 list_for_each_safe(c, n, &port->dmaqueue.list) {256 257 buf = list_entry(c, struct saa7164_buffer, list);258 if (i++ > port->hwcfg.buffercount) {259 printk(KERN_ERR "%s() illegal i count %d\n",260 __func__, i);261 break;262 }263 264 if (buf->idx == bufnr) {265 266 /* Found the buffer, deal with it */267 dprintk(DBGLVL_IRQ, "%s() bufnr: %d\n", __func__, bufnr);268 269 if (crc_checking) {270 /* Throw a new checksum on the dma buffer */271 buf->crc = crc32(0, buf->cpu, buf->actual_size);272 }273 274 if (guard_checking) {275 p = (u8 *)buf->cpu;276 if ((*(p + buf->actual_size + 0) != 0xff) ||277 (*(p + buf->actual_size + 1) != 0xff) ||278 (*(p + buf->actual_size + 2) != 0xff) ||279 (*(p + buf->actual_size + 3) != 0xff) ||280 (*(p + buf->actual_size + 0x10) != 0xff) ||281 (*(p + buf->actual_size + 0x11) != 0xff) ||282 (*(p + buf->actual_size + 0x12) != 0xff) ||283 (*(p + buf->actual_size + 0x13) != 0xff)) {284 printk(KERN_ERR "%s() buf %p guard buffer breach\n",285 __func__, buf);286#if 0287 print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,288 p + buf->actual_size - 32, 64, false);289#endif290 }291 }292 293 if ((port->nr != SAA7164_PORT_VBI1) && (port->nr != SAA7164_PORT_VBI2)) {294 /* Validate the incoming buffer content */295 if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)296 saa7164_ts_verifier(buf);297 else if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)298 saa7164_pack_verifier(buf);299 }300 301 /* find a free user buffer and clone to it */302 if (!list_empty(&port->list_buf_free.list)) {303 304 /* Pull the first buffer from the used list */305 ubuf = list_first_entry(&port->list_buf_free.list,306 struct saa7164_user_buffer, list);307 308 if (buf->actual_size <= ubuf->actual_size) {309 310 memcpy(ubuf->data, buf->cpu, ubuf->actual_size);311 312 if (crc_checking) {313 /* Throw a new checksum on the read buffer */314 ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size);315 }316 317 /* Requeue the buffer on the free list */318 ubuf->pos = 0;319 320 list_move_tail(&ubuf->list,321 &port->list_buf_used.list);322 323 /* Flag any userland waiters */324 wake_up_interruptible(&port->wait_read);325 326 } else {327 printk(KERN_ERR "buf %p bufsize fails match\n", buf);328 }329 330 } else331 printk(KERN_ERR "encirq no free buffers, increase param encoder_buffers\n");332 333 /* Ensure offset into buffer remains 0, fill buffer334 * with known bad data. We check for this data at a later point335 * in time. */336 saa7164_buffer_zero_offsets(port, bufnr);337 memset(buf->cpu, 0xff, buf->pci_size);338 if (crc_checking) {339 /* Throw yet aanother new checksum on the dma buffer */340 buf->crc = crc32(0, buf->cpu, buf->actual_size);341 }342 343 break;344 }345 }346 mutex_unlock(&port->dmaqueue_lock);347}348 349static void saa7164_work_enchandler(struct work_struct *w)350{351 struct saa7164_port *port =352 container_of(w, struct saa7164_port, workenc);353 struct saa7164_dev *dev = port->dev;354 355 u32 wp, mcb, rp;356 357 port->last_svc_msecs_diff = port->last_svc_msecs;358 port->last_svc_msecs = jiffies_to_msecs(jiffies);359 360 port->last_svc_msecs_diff = port->last_svc_msecs -361 port->last_svc_msecs_diff;362 363 saa7164_histogram_update(&port->svc_interval,364 port->last_svc_msecs_diff);365 366 port->last_irq_svc_msecs_diff = port->last_svc_msecs -367 port->last_irq_msecs;368 369 saa7164_histogram_update(&port->irq_svc_interval,370 port->last_irq_svc_msecs_diff);371 372 dprintk(DBGLVL_IRQ,373 "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",374 __func__,375 port->last_svc_msecs_diff,376 port->last_irq_svc_msecs_diff,377 port->last_svc_wp,378 port->last_svc_rp379 );380 381 /* Current write position */382 wp = saa7164_readl(port->bufcounter);383 if (wp > (port->hwcfg.buffercount - 1)) {384 printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);385 return;386 }387 388 /* Most current complete buffer */389 if (wp == 0)390 mcb = (port->hwcfg.buffercount - 1);391 else392 mcb = wp - 1;393 394 while (1) {395 if (port->done_first_interrupt == 0) {396 port->done_first_interrupt++;397 rp = mcb;398 } else399 rp = (port->last_svc_rp + 1) % 8;400 401 if (rp > (port->hwcfg.buffercount - 1)) {402 printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);403 break;404 }405 406 saa7164_work_enchandler_helper(port, rp);407 port->last_svc_rp = rp;408 409 if (rp == mcb)410 break;411 }412 413 /* TODO: Convert this into a /proc/saa7164 style readable file */414 if (print_histogram == port->nr) {415 saa7164_histogram_print(port, &port->irq_interval);416 saa7164_histogram_print(port, &port->svc_interval);417 saa7164_histogram_print(port, &port->irq_svc_interval);418 saa7164_histogram_print(port, &port->read_interval);419 saa7164_histogram_print(port, &port->poll_interval);420 /* TODO: fix this to preserve any previous state */421 print_histogram = 64 + port->nr;422 }423}424 425static void saa7164_work_vbihandler(struct work_struct *w)426{427 struct saa7164_port *port =428 container_of(w, struct saa7164_port, workenc);429 struct saa7164_dev *dev = port->dev;430 431 u32 wp, mcb, rp;432 433 port->last_svc_msecs_diff = port->last_svc_msecs;434 port->last_svc_msecs = jiffies_to_msecs(jiffies);435 port->last_svc_msecs_diff = port->last_svc_msecs -436 port->last_svc_msecs_diff;437 438 saa7164_histogram_update(&port->svc_interval,439 port->last_svc_msecs_diff);440 441 port->last_irq_svc_msecs_diff = port->last_svc_msecs -442 port->last_irq_msecs;443 444 saa7164_histogram_update(&port->irq_svc_interval,445 port->last_irq_svc_msecs_diff);446 447 dprintk(DBGLVL_IRQ,448 "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",449 __func__,450 port->last_svc_msecs_diff,451 port->last_irq_svc_msecs_diff,452 port->last_svc_wp,453 port->last_svc_rp454 );455 456 /* Current write position */457 wp = saa7164_readl(port->bufcounter);458 if (wp > (port->hwcfg.buffercount - 1)) {459 printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);460 return;461 }462 463 /* Most current complete buffer */464 if (wp == 0)465 mcb = (port->hwcfg.buffercount - 1);466 else467 mcb = wp - 1;468 469 while (1) {470 if (port->done_first_interrupt == 0) {471 port->done_first_interrupt++;472 rp = mcb;473 } else474 rp = (port->last_svc_rp + 1) % 8;475 476 if (rp > (port->hwcfg.buffercount - 1)) {477 printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);478 break;479 }480 481 saa7164_work_enchandler_helper(port, rp);482 port->last_svc_rp = rp;483 484 if (rp == mcb)485 break;486 }487 488 /* TODO: Convert this into a /proc/saa7164 style readable file */489 if (print_histogram == port->nr) {490 saa7164_histogram_print(port, &port->irq_interval);491 saa7164_histogram_print(port, &port->svc_interval);492 saa7164_histogram_print(port, &port->irq_svc_interval);493 saa7164_histogram_print(port, &port->read_interval);494 saa7164_histogram_print(port, &port->poll_interval);495 /* TODO: fix this to preserve any previous state */496 print_histogram = 64 + port->nr;497 }498}499 500static void saa7164_work_cmdhandler(struct work_struct *w)501{502 struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);503 504 /* Wake up any complete commands */505 saa7164_irq_dequeue(dev);506}507 508static void saa7164_buffer_deliver(struct saa7164_buffer *buf)509{510 struct saa7164_port *port = buf->port;511 512 /* Feed the transport payload into the kernel demux */513 dvb_dmx_swfilter_packets(&port->dvb.demux, (u8 *)buf->cpu,514 SAA7164_TS_NUMBER_OF_LINES);515 516}517 518static irqreturn_t saa7164_irq_vbi(struct saa7164_port *port)519{520 struct saa7164_dev *dev = port->dev;521 522 /* Store old time */523 port->last_irq_msecs_diff = port->last_irq_msecs;524 525 /* Collect new stats */526 port->last_irq_msecs = jiffies_to_msecs(jiffies);527 528 /* Calculate stats */529 port->last_irq_msecs_diff = port->last_irq_msecs -530 port->last_irq_msecs_diff;531 532 saa7164_histogram_update(&port->irq_interval,533 port->last_irq_msecs_diff);534 535 dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,536 port->last_irq_msecs_diff);537 538 /* Tis calls the vbi irq handler */539 schedule_work(&port->workenc);540 return 0;541}542 543static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)544{545 struct saa7164_dev *dev = port->dev;546 547 /* Store old time */548 port->last_irq_msecs_diff = port->last_irq_msecs;549 550 /* Collect new stats */551 port->last_irq_msecs = jiffies_to_msecs(jiffies);552 553 /* Calculate stats */554 port->last_irq_msecs_diff = port->last_irq_msecs -555 port->last_irq_msecs_diff;556 557 saa7164_histogram_update(&port->irq_interval,558 port->last_irq_msecs_diff);559 560 dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,561 port->last_irq_msecs_diff);562 563 schedule_work(&port->workenc);564 return 0;565}566 567static irqreturn_t saa7164_irq_ts(struct saa7164_port *port)568{569 struct saa7164_dev *dev = port->dev;570 struct saa7164_buffer *buf;571 struct list_head *c, *n;572 int wp, i = 0, rp;573 574 /* Find the current write point from the hardware */575 wp = saa7164_readl(port->bufcounter);576 577 BUG_ON(wp > (port->hwcfg.buffercount - 1));578 579 /* Find the previous buffer to the current write point */580 if (wp == 0)581 rp = (port->hwcfg.buffercount - 1);582 else583 rp = wp - 1;584 585 /* Lookup the WP in the buffer list */586 /* TODO: turn this into a worker thread */587 list_for_each_safe(c, n, &port->dmaqueue.list) {588 buf = list_entry(c, struct saa7164_buffer, list);589 BUG_ON(i > port->hwcfg.buffercount);590 i++;591 592 if (buf->idx == rp) {593 /* Found the buffer, deal with it */594 dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d\n",595 __func__, wp, rp);596 saa7164_buffer_deliver(buf);597 break;598 }599 600 }601 return 0;602}603 604/* Primary IRQ handler and dispatch mechanism */605static irqreturn_t saa7164_irq(int irq, void *dev_id)606{607 struct saa7164_dev *dev = dev_id;608 struct saa7164_port *porta, *portb, *portc, *portd, *porte, *portf;609 610 u32 intid, intstat[INT_SIZE/4];611 int i, handled = 0, bit;612 613 if (dev == NULL) {614 printk(KERN_ERR "%s() No device specified\n", __func__);615 handled = 0;616 goto out;617 }618 619 porta = &dev->ports[SAA7164_PORT_TS1];620 portb = &dev->ports[SAA7164_PORT_TS2];621 portc = &dev->ports[SAA7164_PORT_ENC1];622 portd = &dev->ports[SAA7164_PORT_ENC2];623 porte = &dev->ports[SAA7164_PORT_VBI1];624 portf = &dev->ports[SAA7164_PORT_VBI2];625 626 /* Check that the hardware is accessible. If the status bytes are627 * 0xFF then the device is not accessible, the IRQ belongs628 * to another driver.629 * 4 x u32 interrupt registers.630 */631 for (i = 0; i < INT_SIZE/4; i++) {632 633 /* TODO: Convert into saa7164_readl() */634 /* Read the 4 hardware interrupt registers */635 intstat[i] = saa7164_readl(dev->int_status + (i * 4));636 637 if (intstat[i])638 handled = 1;639 }640 if (handled == 0)641 goto out;642 643 /* For each of the HW interrupt registers */644 for (i = 0; i < INT_SIZE/4; i++) {645 646 if (intstat[i]) {647 /* Each function of the board has it's own interruptid.648 * Find the function that triggered then call649 * it's handler.650 */651 for (bit = 0; bit < 32; bit++) {652 653 if (((intstat[i] >> bit) & 0x00000001) == 0)654 continue;655 656 /* Calculate the interrupt id (0x00 to 0x7f) */657 658 intid = (i * 32) + bit;659 if (intid == dev->intfdesc.bInterruptId) {660 /* A response to an cmd/api call */661 schedule_work(&dev->workcmd);662 } else if (intid == porta->hwcfg.interruptid) {663 664 /* Transport path 1 */665 saa7164_irq_ts(porta);666 667 } else if (intid == portb->hwcfg.interruptid) {668 669 /* Transport path 2 */670 saa7164_irq_ts(portb);671 672 } else if (intid == portc->hwcfg.interruptid) {673 674 /* Encoder path 1 */675 saa7164_irq_encoder(portc);676 677 } else if (intid == portd->hwcfg.interruptid) {678 679 /* Encoder path 2 */680 saa7164_irq_encoder(portd);681 682 } else if (intid == porte->hwcfg.interruptid) {683 684 /* VBI path 1 */685 saa7164_irq_vbi(porte);686 687 } else if (intid == portf->hwcfg.interruptid) {688 689 /* VBI path 2 */690 saa7164_irq_vbi(portf);691 692 } else {693 /* Find the function */694 dprintk(DBGLVL_IRQ,695 "%s() unhandled interrupt reg 0x%x bit 0x%x intid = 0x%x\n",696 __func__, i, bit, intid);697 }698 }699 700 /* Ack it */701 saa7164_writel(dev->int_ack + (i * 4), intstat[i]);702 703 }704 }705out:706 return IRQ_RETVAL(handled);707}708 709void saa7164_getfirmwarestatus(struct saa7164_dev *dev)710{711 struct saa7164_fw_status *s = &dev->fw_status;712 713 dev->fw_status.status = saa7164_readl(SAA_DEVICE_SYSINIT_STATUS);714 dev->fw_status.mode = saa7164_readl(SAA_DEVICE_SYSINIT_MODE);715 dev->fw_status.spec = saa7164_readl(SAA_DEVICE_SYSINIT_SPEC);716 dev->fw_status.inst = saa7164_readl(SAA_DEVICE_SYSINIT_INST);717 dev->fw_status.cpuload = saa7164_readl(SAA_DEVICE_SYSINIT_CPULOAD);718 dev->fw_status.remainheap =719 saa7164_readl(SAA_DEVICE_SYSINIT_REMAINHEAP);720 721 dprintk(1, "Firmware status:\n");722 dprintk(1, " .status = 0x%08x\n", s->status);723 dprintk(1, " .mode = 0x%08x\n", s->mode);724 dprintk(1, " .spec = 0x%08x\n", s->spec);725 dprintk(1, " .inst = 0x%08x\n", s->inst);726 dprintk(1, " .cpuload = 0x%08x\n", s->cpuload);727 dprintk(1, " .remainheap = 0x%08x\n", s->remainheap);728}729 730u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev)731{732 u32 reg;733 734 reg = saa7164_readl(SAA_DEVICE_VERSION);735 dprintk(1, "Device running firmware version %d.%d.%d.%d (0x%x)\n",736 (reg & 0x0000fc00) >> 10,737 (reg & 0x000003e0) >> 5,738 (reg & 0x0000001f),739 (reg & 0xffff0000) >> 16,740 reg);741 742 return reg;743}744 745/* TODO: Debugging func, remove */746void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr)747{748 int i;749 750 dprintk(1, "--------------------> 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");751 752 for (i = 0; i < 0x100; i += 16)753 dprintk(1, "region0[0x%08x] = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",754 i,755 (u8)saa7164_readb(addr + i + 0),756 (u8)saa7164_readb(addr + i + 1),757 (u8)saa7164_readb(addr + i + 2),758 (u8)saa7164_readb(addr + i + 3),759 (u8)saa7164_readb(addr + i + 4),760 (u8)saa7164_readb(addr + i + 5),761 (u8)saa7164_readb(addr + i + 6),762 (u8)saa7164_readb(addr + i + 7),763 (u8)saa7164_readb(addr + i + 8),764 (u8)saa7164_readb(addr + i + 9),765 (u8)saa7164_readb(addr + i + 10),766 (u8)saa7164_readb(addr + i + 11),767 (u8)saa7164_readb(addr + i + 12),768 (u8)saa7164_readb(addr + i + 13),769 (u8)saa7164_readb(addr + i + 14),770 (u8)saa7164_readb(addr + i + 15)771 );772}773 774static void saa7164_dump_hwdesc(struct saa7164_dev *dev)775{776 dprintk(1, "@0x%p hwdesc sizeof(struct tmComResHWDescr) = %d bytes\n",777 &dev->hwdesc, (u32)sizeof(struct tmComResHWDescr));778 779 dprintk(1, " .bLength = 0x%x\n", dev->hwdesc.bLength);780 dprintk(1, " .bDescriptorType = 0x%x\n", dev->hwdesc.bDescriptorType);781 dprintk(1, " .bDescriptorSubtype = 0x%x\n",782 dev->hwdesc.bDescriptorSubtype);783 784 dprintk(1, " .bcdSpecVersion = 0x%x\n", dev->hwdesc.bcdSpecVersion);785 dprintk(1, " .dwClockFrequency = 0x%x\n", dev->hwdesc.dwClockFrequency);786 dprintk(1, " .dwClockUpdateRes = 0x%x\n", dev->hwdesc.dwClockUpdateRes);787 dprintk(1, " .bCapabilities = 0x%x\n", dev->hwdesc.bCapabilities);788 dprintk(1, " .dwDeviceRegistersLocation = 0x%x\n",789 dev->hwdesc.dwDeviceRegistersLocation);790 791 dprintk(1, " .dwHostMemoryRegion = 0x%x\n",792 dev->hwdesc.dwHostMemoryRegion);793 794 dprintk(1, " .dwHostMemoryRegionSize = 0x%x\n",795 dev->hwdesc.dwHostMemoryRegionSize);796 797 dprintk(1, " .dwHostHibernatMemRegion = 0x%x\n",798 dev->hwdesc.dwHostHibernatMemRegion);799 800 dprintk(1, " .dwHostHibernatMemRegionSize = 0x%x\n",801 dev->hwdesc.dwHostHibernatMemRegionSize);802}803 804static void saa7164_dump_intfdesc(struct saa7164_dev *dev)805{806 dprintk(1, "@0x%p intfdesc sizeof(struct tmComResInterfaceDescr) = %d bytes\n",807 &dev->intfdesc, (u32)sizeof(struct tmComResInterfaceDescr));808 809 dprintk(1, " .bLength = 0x%x\n", dev->intfdesc.bLength);810 dprintk(1, " .bDescriptorType = 0x%x\n", dev->intfdesc.bDescriptorType);811 dprintk(1, " .bDescriptorSubtype = 0x%x\n",812 dev->intfdesc.bDescriptorSubtype);813 814 dprintk(1, " .bFlags = 0x%x\n", dev->intfdesc.bFlags);815 dprintk(1, " .bInterfaceType = 0x%x\n", dev->intfdesc.bInterfaceType);816 dprintk(1, " .bInterfaceId = 0x%x\n", dev->intfdesc.bInterfaceId);817 dprintk(1, " .bBaseInterface = 0x%x\n", dev->intfdesc.bBaseInterface);818 dprintk(1, " .bInterruptId = 0x%x\n", dev->intfdesc.bInterruptId);819 dprintk(1, " .bDebugInterruptId = 0x%x\n",820 dev->intfdesc.bDebugInterruptId);821 822 dprintk(1, " .BARLocation = 0x%x\n", dev->intfdesc.BARLocation);823}824 825static void saa7164_dump_busdesc(struct saa7164_dev *dev)826{827 dprintk(1, "@0x%p busdesc sizeof(struct tmComResBusDescr) = %d bytes\n",828 &dev->busdesc, (u32)sizeof(struct tmComResBusDescr));829 830 dprintk(1, " .CommandRing = 0x%016Lx\n", dev->busdesc.CommandRing);831 dprintk(1, " .ResponseRing = 0x%016Lx\n", dev->busdesc.ResponseRing);832 dprintk(1, " .CommandWrite = 0x%x\n", dev->busdesc.CommandWrite);833 dprintk(1, " .CommandRead = 0x%x\n", dev->busdesc.CommandRead);834 dprintk(1, " .ResponseWrite = 0x%x\n", dev->busdesc.ResponseWrite);835 dprintk(1, " .ResponseRead = 0x%x\n", dev->busdesc.ResponseRead);836}837 838/* Much of the hardware configuration and PCI registers are configured839 * dynamically depending on firmware. We have to cache some initial840 * structures then use these to locate other important structures841 * from PCI space.842 */843static void saa7164_get_descriptors(struct saa7164_dev *dev)844{845 memcpy_fromio(&dev->hwdesc, dev->bmmio, sizeof(struct tmComResHWDescr));846 memcpy_fromio(&dev->intfdesc, dev->bmmio + sizeof(struct tmComResHWDescr),847 sizeof(struct tmComResInterfaceDescr));848 memcpy_fromio(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation,849 sizeof(struct tmComResBusDescr));850 851 if (dev->hwdesc.bLength != sizeof(struct tmComResHWDescr)) {852 printk(KERN_ERR "Structure struct tmComResHWDescr is mangled\n");853 printk(KERN_ERR "Need %x got %d\n", dev->hwdesc.bLength,854 (u32)sizeof(struct tmComResHWDescr));855 } else856 saa7164_dump_hwdesc(dev);857 858 if (dev->intfdesc.bLength != sizeof(struct tmComResInterfaceDescr)) {859 printk(KERN_ERR "struct struct tmComResInterfaceDescr is mangled\n");860 printk(KERN_ERR "Need %x got %d\n", dev->intfdesc.bLength,861 (u32)sizeof(struct tmComResInterfaceDescr));862 } else863 saa7164_dump_intfdesc(dev);864 865 saa7164_dump_busdesc(dev);866}867 868static int saa7164_pci_quirks(struct saa7164_dev *dev)869{870 return 0;871}872 873static int get_resources(struct saa7164_dev *dev)874{875 if (request_mem_region(pci_resource_start(dev->pci, 0),876 pci_resource_len(dev->pci, 0), dev->name)) {877 878 if (request_mem_region(pci_resource_start(dev->pci, 2),879 pci_resource_len(dev->pci, 2), dev->name))880 return 0;881 }882 883 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx or 0x%llx\n",884 dev->name,885 (u64)pci_resource_start(dev->pci, 0),886 (u64)pci_resource_start(dev->pci, 2));887 888 return -EBUSY;889}890 891static int saa7164_port_init(struct saa7164_dev *dev, int portnr)892{893 struct saa7164_port *port = NULL;894 895 BUG_ON((portnr < 0) || (portnr >= SAA7164_MAX_PORTS));896 897 port = &dev->ports[portnr];898 899 port->dev = dev;900 port->nr = portnr;901 902 if ((portnr == SAA7164_PORT_TS1) || (portnr == SAA7164_PORT_TS2))903 port->type = SAA7164_MPEG_DVB;904 else905 if ((portnr == SAA7164_PORT_ENC1) || (portnr == SAA7164_PORT_ENC2)) {906 port->type = SAA7164_MPEG_ENCODER;907 908 /* We need a deferred interrupt handler for cmd handling */909 INIT_WORK(&port->workenc, saa7164_work_enchandler);910 } else if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) {911 port->type = SAA7164_MPEG_VBI;912 913 /* We need a deferred interrupt handler for cmd handling */914 INIT_WORK(&port->workenc, saa7164_work_vbihandler);915 } else916 BUG();917 918 /* Init all the critical resources */919 mutex_init(&port->dvb.lock);920 INIT_LIST_HEAD(&port->dmaqueue.list);921 mutex_init(&port->dmaqueue_lock);922 923 INIT_LIST_HEAD(&port->list_buf_used.list);924 INIT_LIST_HEAD(&port->list_buf_free.list);925 init_waitqueue_head(&port->wait_read);926 927 928 saa7164_histogram_reset(&port->irq_interval, "irq intervals");929 saa7164_histogram_reset(&port->svc_interval, "deferred intervals");930 saa7164_histogram_reset(&port->irq_svc_interval,931 "irq to deferred intervals");932 saa7164_histogram_reset(&port->read_interval,933 "encoder/vbi read() intervals");934 saa7164_histogram_reset(&port->poll_interval,935 "encoder/vbi poll() intervals");936 937 return 0;938}939 940static int saa7164_dev_setup(struct saa7164_dev *dev)941{942 int i;943 944 mutex_init(&dev->lock);945 atomic_inc(&dev->refcount);946 dev->nr = saa7164_devcount++;947 948 snprintf(dev->name, sizeof(dev->name), "saa7164[%d]", dev->nr);949 950 mutex_lock(&devlist);951 list_add_tail(&dev->devlist, &saa7164_devlist);952 mutex_unlock(&devlist);953 954 /* board config */955 dev->board = UNSET;956 if (card[dev->nr] < saa7164_bcount)957 dev->board = card[dev->nr];958 959 for (i = 0; UNSET == dev->board && i < saa7164_idcount; i++)960 if (dev->pci->subsystem_vendor == saa7164_subids[i].subvendor &&961 dev->pci->subsystem_device ==962 saa7164_subids[i].subdevice)963 dev->board = saa7164_subids[i].card;964 965 if (UNSET == dev->board) {966 dev->board = SAA7164_BOARD_UNKNOWN;967 saa7164_card_list(dev);968 }969 970 dev->pci_bus = dev->pci->bus->number;971 dev->pci_slot = PCI_SLOT(dev->pci->devfn);972 973 /* I2C Defaults / setup */974 dev->i2c_bus[0].dev = dev;975 dev->i2c_bus[0].nr = 0;976 dev->i2c_bus[1].dev = dev;977 dev->i2c_bus[1].nr = 1;978 dev->i2c_bus[2].dev = dev;979 dev->i2c_bus[2].nr = 2;980 981 /* Transport + Encoder ports 1, 2, 3, 4 - Defaults / setup */982 saa7164_port_init(dev, SAA7164_PORT_TS1);983 saa7164_port_init(dev, SAA7164_PORT_TS2);984 saa7164_port_init(dev, SAA7164_PORT_ENC1);985 saa7164_port_init(dev, SAA7164_PORT_ENC2);986 saa7164_port_init(dev, SAA7164_PORT_VBI1);987 saa7164_port_init(dev, SAA7164_PORT_VBI2);988 989 if (get_resources(dev) < 0) {990 printk(KERN_ERR "CORE %s No more PCIe resources for subsystem: %04x:%04x\n",991 dev->name, dev->pci->subsystem_vendor,992 dev->pci->subsystem_device);993 994 saa7164_devcount--;995 return -ENODEV;996 }997 998 /* PCI/e allocations */999 dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),1000 pci_resource_len(dev->pci, 0));1001 1002 dev->lmmio2 = ioremap(pci_resource_start(dev->pci, 2),1003 pci_resource_len(dev->pci, 2));1004 1005 dev->bmmio = (u8 __iomem *)dev->lmmio;1006 dev->bmmio2 = (u8 __iomem *)dev->lmmio2;1007 1008 /* Interrupt and ack register locations offset of bmmio */1009 dev->int_status = 0x183000 + 0xf80;1010 dev->int_ack = 0x183000 + 0xf90;1011 1012 printk(KERN_INFO1013 "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",1014 dev->name, dev->pci->subsystem_vendor,1015 dev->pci->subsystem_device, saa7164_boards[dev->board].name,1016 dev->board, card[dev->nr] == dev->board ?1017 "insmod option" : "autodetected");1018 1019 saa7164_pci_quirks(dev);1020 1021 return 0;1022}1023 1024static void saa7164_dev_unregister(struct saa7164_dev *dev)1025{1026 dprintk(1, "%s()\n", __func__);1027 1028 release_mem_region(pci_resource_start(dev->pci, 0),1029 pci_resource_len(dev->pci, 0));1030 1031 release_mem_region(pci_resource_start(dev->pci, 2),1032 pci_resource_len(dev->pci, 2));1033 1034 if (!atomic_dec_and_test(&dev->refcount))1035 return;1036 1037 iounmap(dev->lmmio);1038 iounmap(dev->lmmio2);1039 1040 return;1041}1042 1043#ifdef CONFIG_DEBUG_FS1044static void *saa7164_seq_start(struct seq_file *s, loff_t *pos)1045{1046 struct saa7164_dev *dev;1047 loff_t index = *pos;1048 1049 mutex_lock(&devlist);1050 list_for_each_entry(dev, &saa7164_devlist, devlist) {1051 if (index-- == 0) {1052 mutex_unlock(&devlist);1053 return dev;1054 }1055 }1056 mutex_unlock(&devlist);1057 1058 return NULL;1059}1060 1061static void *saa7164_seq_next(struct seq_file *s, void *v, loff_t *pos)1062{1063 struct saa7164_dev *dev = v;1064 void *ret;1065 1066 mutex_lock(&devlist);1067 if (list_is_last(&dev->devlist, &saa7164_devlist))1068 ret = NULL;1069 else1070 ret = list_next_entry(dev, devlist);1071 mutex_unlock(&devlist);1072 1073 ++*pos;1074 1075 return ret;1076}1077 1078static void saa7164_seq_stop(struct seq_file *s, void *v)1079{1080}1081 1082static int saa7164_seq_show(struct seq_file *m, void *v)1083{1084 struct saa7164_dev *dev = v;1085 struct tmComResBusInfo *b;1086 int i, c;1087 1088 seq_printf(m, "%s = %p\n", dev->name, dev);1089 1090 /* Lock the bus from any other access */1091 b = &dev->bus;1092 mutex_lock(&b->lock);1093 1094 seq_printf(m, " .m_pdwSetWritePos = 0x%x (0x%08x)\n",1095 b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));1096 1097 seq_printf(m, " .m_pdwSetReadPos = 0x%x (0x%08x)\n",1098 b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));1099 1100 seq_printf(m, " .m_pdwGetWritePos = 0x%x (0x%08x)\n",1101 b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));1102 1103 seq_printf(m, " .m_pdwGetReadPos = 0x%x (0x%08x)\n",1104 b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));1105 c = 0;1106 seq_puts(m, "\n Set Ring:\n");1107 seq_puts(m, "\n addr 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");1108 for (i = 0; i < b->m_dwSizeSetRing; i++) {1109 if (c == 0)1110 seq_printf(m, " %04x:", i);1111 1112 seq_printf(m, " %02x", readb(b->m_pdwSetRing + i));1113 1114 if (++c == 16) {1115 seq_puts(m, "\n");1116 c = 0;1117 }1118 }1119 1120 c = 0;1121 seq_puts(m, "\n Get Ring:\n");1122 seq_puts(m, "\n addr 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");1123 for (i = 0; i < b->m_dwSizeGetRing; i++) {1124 if (c == 0)1125 seq_printf(m, " %04x:", i);1126 1127 seq_printf(m, " %02x", readb(b->m_pdwGetRing + i));1128 1129 if (++c == 16) {1130 seq_puts(m, "\n");1131 c = 0;1132 }1133 }1134 1135 mutex_unlock(&b->lock);1136 1137 return 0;1138}1139 1140static const struct seq_operations saa7164_sops = {1141 .start = saa7164_seq_start,1142 .next = saa7164_seq_next,1143 .stop = saa7164_seq_stop,1144 .show = saa7164_seq_show,1145};1146 1147DEFINE_SEQ_ATTRIBUTE(saa7164);1148 1149static struct dentry *saa7614_dentry;1150 1151static void __init saa7164_debugfs_create(void)1152{1153 saa7614_dentry = debugfs_create_file("saa7164", 0444, NULL, NULL,1154 &saa7164_fops);1155}1156 1157static void __exit saa7164_debugfs_remove(void)1158{1159 debugfs_remove(saa7614_dentry);1160}1161#else1162static void saa7164_debugfs_create(void) { }1163static void saa7164_debugfs_remove(void) { }1164#endif1165 1166static int saa7164_thread_function(void *data)1167{1168 struct saa7164_dev *dev = data;1169 struct tmFwInfoStruct fwinfo;1170 u64 last_poll_time = 0;1171 1172 dprintk(DBGLVL_THR, "thread started\n");1173 1174 set_freezable();1175 1176 while (1) {1177 msleep_interruptible(100);1178 if (kthread_should_stop())1179 break;1180 try_to_freeze();1181 1182 dprintk(DBGLVL_THR, "thread running\n");1183 1184 /* Dump the firmware debug message to console */1185 /* Polling this costs us 1-2% of the arm CPU */1186 /* convert this into a respnde to interrupt 0x7a */1187 saa7164_api_collect_debug(dev);1188 1189 /* Monitor CPU load every 1 second */1190 if ((last_poll_time + 1000 /* ms */) < jiffies_to_msecs(jiffies)) {1191 saa7164_api_get_load_info(dev, &fwinfo);1192 last_poll_time = jiffies_to_msecs(jiffies);1193 }1194 1195 }1196 1197 dprintk(DBGLVL_THR, "thread exiting\n");1198 return 0;1199}1200 1201static bool saa7164_enable_msi(struct pci_dev *pci_dev, struct saa7164_dev *dev)1202{1203 int err;1204 1205 if (!enable_msi) {1206 printk(KERN_WARNING "%s() MSI disabled by module parameter 'enable_msi'"1207 , __func__);1208 return false;1209 }1210 1211 err = pci_enable_msi(pci_dev);1212 1213 if (err) {1214 printk(KERN_ERR "%s() Failed to enable MSI interrupt. Falling back to a shared IRQ\n",1215 __func__);1216 return false;1217 }1218 1219 /* no error - so request an msi interrupt */1220 err = request_irq(pci_dev->irq, saa7164_irq, 0,1221 dev->name, dev);1222 1223 if (err) {1224 /* fall back to legacy interrupt */1225 printk(KERN_ERR "%s() Failed to get an MSI interrupt. Falling back to a shared IRQ\n",1226 __func__);1227 pci_disable_msi(pci_dev);1228 return false;1229 }1230 1231 return true;1232}1233 1234static int saa7164_initdev(struct pci_dev *pci_dev,1235 const struct pci_device_id *pci_id)1236{1237 struct saa7164_dev *dev;1238 int err, i;1239 u32 version;1240 1241 dev = kzalloc(sizeof(*dev), GFP_KERNEL);1242 if (NULL == dev)1243 return -ENOMEM;1244 1245 err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);1246 if (err < 0) {1247 dev_err(&pci_dev->dev, "v4l2_device_register failed\n");1248 goto fail_free;1249 }1250 1251 /* pci init */1252 dev->pci = pci_dev;1253 if (pci_enable_device(pci_dev)) {1254 err = -EIO;1255 goto fail_free;1256 }1257 1258 if (saa7164_dev_setup(dev) < 0) {1259 err = -EINVAL;1260 goto fail_dev;1261 }1262 1263 /* print pci info */1264 dev->pci_rev = pci_dev->revision;1265 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);1266 printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n",1267 dev->name,1268 pci_name(pci_dev), dev->pci_rev, pci_dev->irq,1269 dev->pci_lat,1270 (unsigned long long)pci_resource_start(pci_dev, 0));1271 1272 pci_set_master(pci_dev);1273 /* TODO */1274 err = dma_set_mask(&pci_dev->dev, 0xffffffff);1275 if (err) {1276 printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);1277 goto fail_irq;1278 }1279 1280 /* irq bit */1281 if (saa7164_enable_msi(pci_dev, dev)) {1282 dev->msi = true;1283 } else {1284 /* if we have an error (i.e. we don't have an interrupt)1285 or msi is not enabled - fallback to shared interrupt */1286 1287 err = request_irq(pci_dev->irq, saa7164_irq,1288 IRQF_SHARED, dev->name, dev);1289 1290 if (err < 0) {1291 printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,1292 pci_dev->irq);1293 err = -EIO;1294 goto fail_irq;1295 }1296 }1297 1298 pci_set_drvdata(pci_dev, dev);1299 1300 /* Init the internal command list */1301 for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {1302 dev->cmds[i].seqno = i;1303 dev->cmds[i].inuse = 0;1304 mutex_init(&dev->cmds[i].lock);1305 init_waitqueue_head(&dev->cmds[i].wait);1306 }1307 1308 /* We need a deferred interrupt handler for cmd handling */1309 INIT_WORK(&dev->workcmd, saa7164_work_cmdhandler);1310 1311 /* Only load the firmware if we know the board */1312 if (dev->board != SAA7164_BOARD_UNKNOWN) {1313 1314 err = saa7164_downloadfirmware(dev);1315 if (err < 0) {1316 printk(KERN_ERR1317 "Failed to boot firmware, no features registered\n");1318 goto fail_fw;1319 }1320 1321 saa7164_get_descriptors(dev);1322 saa7164_dumpregs(dev, 0);1323 saa7164_getcurrentfirmwareversion(dev);1324 saa7164_getfirmwarestatus(dev);1325 err = saa7164_bus_setup(dev);1326 if (err < 0)1327 printk(KERN_ERR1328 "Failed to setup the bus, will continue\n");1329 saa7164_bus_dump(dev);1330 1331 /* Ping the running firmware via the command bus and get the1332 * firmware version, this checks the bus is running OK.1333 */1334 version = 0;1335 if (saa7164_api_get_fw_version(dev, &version) == SAA_OK)1336 dprintk(1, "Bus is operating correctly using version %d.%d.%d.%d (0x%x)\n",1337 (version & 0x0000fc00) >> 10,1338 (version & 0x000003e0) >> 5,1339 (version & 0x0000001f),1340 (version & 0xffff0000) >> 16,1341 version);1342 else1343 printk(KERN_ERR1344 "Failed to communicate with the firmware\n");1345 1346 /* Bring up the I2C buses */1347 saa7164_i2c_register(&dev->i2c_bus[0]);1348 saa7164_i2c_register(&dev->i2c_bus[1]);1349 saa7164_i2c_register(&dev->i2c_bus[2]);1350 saa7164_gpio_setup(dev);1351 saa7164_card_setup(dev);1352 1353 /* Parse the dynamic device configuration, find various1354 * media endpoints (MPEG, WMV, PS, TS) and cache their1355 * configuration details into the driver, so we can1356 * reference them later during simething_register() func,1357 * interrupt handlers, deferred work handlers etc.1358 */1359 saa7164_api_enum_subdevs(dev);1360 1361 /* Begin to create the video sub-systems and register funcs */1362 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) {1363 if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS1]) < 0) {1364 printk(KERN_ERR "%s() Failed to register dvb adapters on porta\n",1365 __func__);1366 }1367 }1368 1369 if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) {1370 if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS2]) < 0) {1371 printk(KERN_ERR"%s() Failed to register dvb adapters on portb\n",1372 __func__);1373 }1374 }1375 1376 if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER) {1377 if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC1]) < 0) {1378 printk(KERN_ERR"%s() Failed to register mpeg encoder\n",1379 __func__);1380 }1381 }1382 1383 if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER) {1384 if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC2]) < 0) {1385 printk(KERN_ERR"%s() Failed to register mpeg encoder\n",1386 __func__);1387 }1388 }1389 1390 if (saa7164_boards[dev->board].porte == SAA7164_MPEG_VBI) {1391 if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI1]) < 0) {1392 printk(KERN_ERR"%s() Failed to register vbi device\n",1393 __func__);1394 }1395 }1396 1397 if (saa7164_boards[dev->board].portf == SAA7164_MPEG_VBI) {1398 if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI2]) < 0) {1399 printk(KERN_ERR"%s() Failed to register vbi device\n",1400 __func__);1401 }1402 }1403 saa7164_api_set_debug(dev, fw_debug);1404 1405 if (fw_debug) {1406 dev->kthread = kthread_run(saa7164_thread_function, dev,1407 "saa7164 debug");1408 if (IS_ERR(dev->kthread)) {1409 dev->kthread = NULL;1410 printk(KERN_ERR "%s() Failed to create debug kernel thread\n",1411 __func__);1412 }1413 }1414 1415 } /* != BOARD_UNKNOWN */1416 else1417 printk(KERN_ERR "%s() Unsupported board detected, registering without firmware\n",1418 __func__);1419 1420 dprintk(1, "%s() parameter debug = %d\n", __func__, saa_debug);1421 dprintk(1, "%s() parameter waitsecs = %d\n", __func__, waitsecs);1422 1423fail_fw:1424 return 0;1425 1426fail_irq:1427 saa7164_dev_unregister(dev);1428fail_dev:1429 pci_disable_device(pci_dev);1430fail_free:1431 v4l2_device_unregister(&dev->v4l2_dev);1432 kfree(dev);1433 return err;1434}1435 1436static void saa7164_shutdown(struct saa7164_dev *dev)1437{1438 dprintk(1, "%s()\n", __func__);1439}1440 1441static void saa7164_finidev(struct pci_dev *pci_dev)1442{1443 struct saa7164_dev *dev = pci_get_drvdata(pci_dev);1444 1445 if (dev->board != SAA7164_BOARD_UNKNOWN) {1446 if (fw_debug && dev->kthread) {1447 kthread_stop(dev->kthread);1448 dev->kthread = NULL;1449 }1450 if (dev->firmwareloaded)1451 saa7164_api_set_debug(dev, 0x00);1452 }1453 1454 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],1455 &dev->ports[SAA7164_PORT_ENC1].irq_interval);1456 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],1457 &dev->ports[SAA7164_PORT_ENC1].svc_interval);1458 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],1459 &dev->ports[SAA7164_PORT_ENC1].irq_svc_interval);1460 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],1461 &dev->ports[SAA7164_PORT_ENC1].read_interval);1462 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],1463 &dev->ports[SAA7164_PORT_ENC1].poll_interval);1464 saa7164_histogram_print(&dev->ports[SAA7164_PORT_VBI1],1465 &dev->ports[SAA7164_PORT_VBI1].read_interval);1466 saa7164_histogram_print(&dev->ports[SAA7164_PORT_VBI2],1467 &dev->ports[SAA7164_PORT_VBI2].poll_interval);1468 1469 saa7164_shutdown(dev);1470 1471 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB)1472 saa7164_dvb_unregister(&dev->ports[SAA7164_PORT_TS1]);1473 1474 if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB)1475 saa7164_dvb_unregister(&dev->ports[SAA7164_PORT_TS2]);1476 1477 if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER)1478 saa7164_encoder_unregister(&dev->ports[SAA7164_PORT_ENC1]);1479 1480 if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER)1481 saa7164_encoder_unregister(&dev->ports[SAA7164_PORT_ENC2]);1482 1483 if (saa7164_boards[dev->board].porte == SAA7164_MPEG_VBI)1484 saa7164_vbi_unregister(&dev->ports[SAA7164_PORT_VBI1]);1485 1486 if (saa7164_boards[dev->board].portf == SAA7164_MPEG_VBI)1487 saa7164_vbi_unregister(&dev->ports[SAA7164_PORT_VBI2]);1488 1489 saa7164_i2c_unregister(&dev->i2c_bus[0]);1490 saa7164_i2c_unregister(&dev->i2c_bus[1]);1491 saa7164_i2c_unregister(&dev->i2c_bus[2]);1492 1493 /* unregister stuff */1494 free_irq(pci_dev->irq, dev);1495 1496 if (dev->msi) {1497 pci_disable_msi(pci_dev);1498 dev->msi = false;1499 }1500 1501 pci_disable_device(pci_dev);1502 1503 mutex_lock(&devlist);1504 list_del(&dev->devlist);1505 mutex_unlock(&devlist);1506 1507 saa7164_dev_unregister(dev);1508 v4l2_device_unregister(&dev->v4l2_dev);1509 kfree(dev);1510}1511 1512static const struct pci_device_id saa7164_pci_tbl[] = {1513 {1514 /* SAA7164 */1515 .vendor = 0x1131,1516 .device = 0x7164,1517 .subvendor = PCI_ANY_ID,1518 .subdevice = PCI_ANY_ID,1519 }, {1520 /* --- end of list --- */1521 }1522};1523MODULE_DEVICE_TABLE(pci, saa7164_pci_tbl);1524 1525static struct pci_driver saa7164_pci_driver = {1526 .name = "saa7164",1527 .id_table = saa7164_pci_tbl,1528 .probe = saa7164_initdev,1529 .remove = saa7164_finidev,1530};1531 1532static int __init saa7164_init(void)1533{1534 int ret = pci_register_driver(&saa7164_pci_driver);1535 1536 if (ret)1537 return ret;1538 1539 saa7164_debugfs_create();1540 1541 pr_info("saa7164 driver loaded\n");1542 1543 return 0;1544}1545 1546static void __exit saa7164_fini(void)1547{1548 saa7164_debugfs_remove();1549 pci_unregister_driver(&saa7164_pci_driver);1550}1551 1552module_init(saa7164_init);1553module_exit(saa7164_fini);1554