brintos

brintos / linux-shallow public Read only

0
0
Text · 41.0 KiB · a8a004f Raw
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