xref: /linux/drivers/media/pci/cx88/cx88-core.c (revision c4ee0af3fa0dc65f690fc908f02b8355f9576ea0)
1 /*
2  *
3  * device driver for Conexant 2388x based TV cards
4  * driver core
5  *
6  * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7  *
8  * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
9  *     - Multituner support
10  *     - video_ioctl2 conversion
11  *     - PAL/M fixes
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 2 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, write to the Free Software
25  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27 
28 #include <linux/init.h>
29 #include <linux/list.h>
30 #include <linux/module.h>
31 #include <linux/kernel.h>
32 #include <linux/slab.h>
33 #include <linux/kmod.h>
34 #include <linux/sound.h>
35 #include <linux/interrupt.h>
36 #include <linux/pci.h>
37 #include <linux/delay.h>
38 #include <linux/videodev2.h>
39 #include <linux/mutex.h>
40 
41 #include "cx88.h"
42 #include <media/v4l2-common.h>
43 #include <media/v4l2-ioctl.h>
44 
45 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
46 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
47 MODULE_LICENSE("GPL");
48 
49 /* ------------------------------------------------------------------ */
50 
51 unsigned int cx88_core_debug;
52 module_param_named(core_debug, cx88_core_debug, int, 0644);
53 MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
54 
55 static unsigned int nicam;
56 module_param(nicam,int,0644);
57 MODULE_PARM_DESC(nicam,"tv audio is nicam");
58 
59 static unsigned int nocomb;
60 module_param(nocomb,int,0644);
61 MODULE_PARM_DESC(nocomb,"disable comb filter");
62 
63 #define dprintk(level,fmt, arg...)	do {				\
64 	if (cx88_core_debug >= level)					\
65 		printk(KERN_DEBUG "%s: " fmt, core->name , ## arg);	\
66 	} while(0)
67 
68 static unsigned int cx88_devcount;
69 static LIST_HEAD(cx88_devlist);
70 static DEFINE_MUTEX(devlist);
71 
72 #define NO_SYNC_LINE (-1U)
73 
74 /* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
75 	 generated _after_ lpi lines are transferred. */
76 static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
77 			    unsigned int offset, u32 sync_line,
78 			    unsigned int bpl, unsigned int padding,
79 			    unsigned int lines, unsigned int lpi)
80 {
81 	struct scatterlist *sg;
82 	unsigned int line,todo,sol;
83 
84 	/* sync instruction */
85 	if (sync_line != NO_SYNC_LINE)
86 		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
87 
88 	/* scan lines */
89 	sg = sglist;
90 	for (line = 0; line < lines; line++) {
91 		while (offset && offset >= sg_dma_len(sg)) {
92 			offset -= sg_dma_len(sg);
93 			sg++;
94 		}
95 		if (lpi && line>0 && !(line % lpi))
96 			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
97 		else
98 			sol = RISC_SOL;
99 		if (bpl <= sg_dma_len(sg)-offset) {
100 			/* fits into current chunk */
101 			*(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
102 			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
103 			offset+=bpl;
104 		} else {
105 			/* scanline needs to be split */
106 			todo = bpl;
107 			*(rp++)=cpu_to_le32(RISC_WRITE|sol|
108 					    (sg_dma_len(sg)-offset));
109 			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
110 			todo -= (sg_dma_len(sg)-offset);
111 			offset = 0;
112 			sg++;
113 			while (todo > sg_dma_len(sg)) {
114 				*(rp++)=cpu_to_le32(RISC_WRITE|
115 						    sg_dma_len(sg));
116 				*(rp++)=cpu_to_le32(sg_dma_address(sg));
117 				todo -= sg_dma_len(sg);
118 				sg++;
119 			}
120 			*(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
121 			*(rp++)=cpu_to_le32(sg_dma_address(sg));
122 			offset += todo;
123 		}
124 		offset += padding;
125 	}
126 
127 	return rp;
128 }
129 
130 int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
131 		     struct scatterlist *sglist,
132 		     unsigned int top_offset, unsigned int bottom_offset,
133 		     unsigned int bpl, unsigned int padding, unsigned int lines)
134 {
135 	u32 instructions,fields;
136 	__le32 *rp;
137 	int rc;
138 
139 	fields = 0;
140 	if (UNSET != top_offset)
141 		fields++;
142 	if (UNSET != bottom_offset)
143 		fields++;
144 
145 	/* estimate risc mem: worst case is one write per page border +
146 	   one write per scan line + syncs + jump (all 2 dwords).  Padding
147 	   can cause next bpl to start close to a page border.  First DMA
148 	   region may be smaller than PAGE_SIZE */
149 	instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
150 	instructions += 2;
151 	if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
152 		return rc;
153 
154 	/* write risc instructions */
155 	rp = risc->cpu;
156 	if (UNSET != top_offset)
157 		rp = cx88_risc_field(rp, sglist, top_offset, 0,
158 				     bpl, padding, lines, 0);
159 	if (UNSET != bottom_offset)
160 		rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
161 				     bpl, padding, lines, 0);
162 
163 	/* save pointer to jmp instruction address */
164 	risc->jmp = rp;
165 	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
166 	return 0;
167 }
168 
169 int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
170 			 struct scatterlist *sglist, unsigned int bpl,
171 			 unsigned int lines, unsigned int lpi)
172 {
173 	u32 instructions;
174 	__le32 *rp;
175 	int rc;
176 
177 	/* estimate risc mem: worst case is one write per page border +
178 	   one write per scan line + syncs + jump (all 2 dwords).  Here
179 	   there is no padding and no sync.  First DMA region may be smaller
180 	   than PAGE_SIZE */
181 	instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
182 	instructions += 1;
183 	if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
184 		return rc;
185 
186 	/* write risc instructions */
187 	rp = risc->cpu;
188 	rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
189 
190 	/* save pointer to jmp instruction address */
191 	risc->jmp = rp;
192 	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
193 	return 0;
194 }
195 
196 int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
197 		      u32 reg, u32 mask, u32 value)
198 {
199 	__le32 *rp;
200 	int rc;
201 
202 	if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
203 		return rc;
204 
205 	/* write risc instructions */
206 	rp = risc->cpu;
207 	*(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2 | RISC_IMM);
208 	*(rp++) = cpu_to_le32(reg);
209 	*(rp++) = cpu_to_le32(value);
210 	*(rp++) = cpu_to_le32(mask);
211 	*(rp++) = cpu_to_le32(RISC_JUMP);
212 	*(rp++) = cpu_to_le32(risc->dma);
213 	return 0;
214 }
215 
216 void
217 cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
218 {
219 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
220 
221 	BUG_ON(in_interrupt());
222 	videobuf_waiton(q, &buf->vb, 0, 0);
223 	videobuf_dma_unmap(q->dev, dma);
224 	videobuf_dma_free(dma);
225 	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
226 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
227 }
228 
229 /* ------------------------------------------------------------------ */
230 /* our SRAM memory layout                                             */
231 
232 /* we are going to put all thr risc programs into host memory, so we
233  * can use the whole SDRAM for the DMA fifos.  To simplify things, we
234  * use a static memory layout.  That surely will waste memory in case
235  * we don't use all DMA channels at the same time (which will be the
236  * case most of the time).  But that still gives us enough FIFO space
237  * to be able to deal with insane long pci latencies ...
238  *
239  * FIFO space allocations:
240  *    channel  21    (y video)  - 10.0k
241  *    channel  22    (u video)  -  2.0k
242  *    channel  23    (v video)  -  2.0k
243  *    channel  24    (vbi)      -  4.0k
244  *    channels 25+26 (audio)    -  4.0k
245  *    channel  28    (mpeg)     -  4.0k
246  *    channel  27    (audio rds)-  3.0k
247  *    TOTAL                     = 29.0k
248  *
249  * Every channel has 160 bytes control data (64 bytes instruction
250  * queue and 6 CDT entries), which is close to 2k total.
251  *
252  * Address layout:
253  *    0x0000 - 0x03ff    CMDs / reserved
254  *    0x0400 - 0x0bff    instruction queues + CDs
255  *    0x0c00 -           FIFOs
256  */
257 
258 const struct sram_channel cx88_sram_channels[] = {
259 	[SRAM_CH21] = {
260 		.name       = "video y / packed",
261 		.cmds_start = 0x180040,
262 		.ctrl_start = 0x180400,
263 		.cdt        = 0x180400 + 64,
264 		.fifo_start = 0x180c00,
265 		.fifo_size  = 0x002800,
266 		.ptr1_reg   = MO_DMA21_PTR1,
267 		.ptr2_reg   = MO_DMA21_PTR2,
268 		.cnt1_reg   = MO_DMA21_CNT1,
269 		.cnt2_reg   = MO_DMA21_CNT2,
270 	},
271 	[SRAM_CH22] = {
272 		.name       = "video u",
273 		.cmds_start = 0x180080,
274 		.ctrl_start = 0x1804a0,
275 		.cdt        = 0x1804a0 + 64,
276 		.fifo_start = 0x183400,
277 		.fifo_size  = 0x000800,
278 		.ptr1_reg   = MO_DMA22_PTR1,
279 		.ptr2_reg   = MO_DMA22_PTR2,
280 		.cnt1_reg   = MO_DMA22_CNT1,
281 		.cnt2_reg   = MO_DMA22_CNT2,
282 	},
283 	[SRAM_CH23] = {
284 		.name       = "video v",
285 		.cmds_start = 0x1800c0,
286 		.ctrl_start = 0x180540,
287 		.cdt        = 0x180540 + 64,
288 		.fifo_start = 0x183c00,
289 		.fifo_size  = 0x000800,
290 		.ptr1_reg   = MO_DMA23_PTR1,
291 		.ptr2_reg   = MO_DMA23_PTR2,
292 		.cnt1_reg   = MO_DMA23_CNT1,
293 		.cnt2_reg   = MO_DMA23_CNT2,
294 	},
295 	[SRAM_CH24] = {
296 		.name       = "vbi",
297 		.cmds_start = 0x180100,
298 		.ctrl_start = 0x1805e0,
299 		.cdt        = 0x1805e0 + 64,
300 		.fifo_start = 0x184400,
301 		.fifo_size  = 0x001000,
302 		.ptr1_reg   = MO_DMA24_PTR1,
303 		.ptr2_reg   = MO_DMA24_PTR2,
304 		.cnt1_reg   = MO_DMA24_CNT1,
305 		.cnt2_reg   = MO_DMA24_CNT2,
306 	},
307 	[SRAM_CH25] = {
308 		.name       = "audio from",
309 		.cmds_start = 0x180140,
310 		.ctrl_start = 0x180680,
311 		.cdt        = 0x180680 + 64,
312 		.fifo_start = 0x185400,
313 		.fifo_size  = 0x001000,
314 		.ptr1_reg   = MO_DMA25_PTR1,
315 		.ptr2_reg   = MO_DMA25_PTR2,
316 		.cnt1_reg   = MO_DMA25_CNT1,
317 		.cnt2_reg   = MO_DMA25_CNT2,
318 	},
319 	[SRAM_CH26] = {
320 		.name       = "audio to",
321 		.cmds_start = 0x180180,
322 		.ctrl_start = 0x180720,
323 		.cdt        = 0x180680 + 64,  /* same as audio IN */
324 		.fifo_start = 0x185400,       /* same as audio IN */
325 		.fifo_size  = 0x001000,       /* same as audio IN */
326 		.ptr1_reg   = MO_DMA26_PTR1,
327 		.ptr2_reg   = MO_DMA26_PTR2,
328 		.cnt1_reg   = MO_DMA26_CNT1,
329 		.cnt2_reg   = MO_DMA26_CNT2,
330 	},
331 	[SRAM_CH28] = {
332 		.name       = "mpeg",
333 		.cmds_start = 0x180200,
334 		.ctrl_start = 0x1807C0,
335 		.cdt        = 0x1807C0 + 64,
336 		.fifo_start = 0x186400,
337 		.fifo_size  = 0x001000,
338 		.ptr1_reg   = MO_DMA28_PTR1,
339 		.ptr2_reg   = MO_DMA28_PTR2,
340 		.cnt1_reg   = MO_DMA28_CNT1,
341 		.cnt2_reg   = MO_DMA28_CNT2,
342 	},
343 	[SRAM_CH27] = {
344 		.name       = "audio rds",
345 		.cmds_start = 0x1801C0,
346 		.ctrl_start = 0x180860,
347 		.cdt        = 0x180860 + 64,
348 		.fifo_start = 0x187400,
349 		.fifo_size  = 0x000C00,
350 		.ptr1_reg   = MO_DMA27_PTR1,
351 		.ptr2_reg   = MO_DMA27_PTR2,
352 		.cnt1_reg   = MO_DMA27_CNT1,
353 		.cnt2_reg   = MO_DMA27_CNT2,
354 	},
355 };
356 
357 int cx88_sram_channel_setup(struct cx88_core *core,
358 			    const struct sram_channel *ch,
359 			    unsigned int bpl, u32 risc)
360 {
361 	unsigned int i,lines;
362 	u32 cdt;
363 
364 	bpl   = (bpl + 7) & ~7; /* alignment */
365 	cdt   = ch->cdt;
366 	lines = ch->fifo_size / bpl;
367 	if (lines > 6)
368 		lines = 6;
369 	BUG_ON(lines < 2);
370 
371 	/* write CDT */
372 	for (i = 0; i < lines; i++)
373 		cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
374 
375 	/* write CMDS */
376 	cx_write(ch->cmds_start +  0, risc);
377 	cx_write(ch->cmds_start +  4, cdt);
378 	cx_write(ch->cmds_start +  8, (lines*16) >> 3);
379 	cx_write(ch->cmds_start + 12, ch->ctrl_start);
380 	cx_write(ch->cmds_start + 16, 64 >> 2);
381 	for (i = 20; i < 64; i += 4)
382 		cx_write(ch->cmds_start + i, 0);
383 
384 	/* fill registers */
385 	cx_write(ch->ptr1_reg, ch->fifo_start);
386 	cx_write(ch->ptr2_reg, cdt);
387 	cx_write(ch->cnt1_reg, (bpl >> 3) -1);
388 	cx_write(ch->cnt2_reg, (lines*16) >> 3);
389 
390 	dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
391 	return 0;
392 }
393 
394 /* ------------------------------------------------------------------ */
395 /* debug helper code                                                  */
396 
397 static int cx88_risc_decode(u32 risc)
398 {
399 	static const char * const instr[16] = {
400 		[ RISC_SYNC    >> 28 ] = "sync",
401 		[ RISC_WRITE   >> 28 ] = "write",
402 		[ RISC_WRITEC  >> 28 ] = "writec",
403 		[ RISC_READ    >> 28 ] = "read",
404 		[ RISC_READC   >> 28 ] = "readc",
405 		[ RISC_JUMP    >> 28 ] = "jump",
406 		[ RISC_SKIP    >> 28 ] = "skip",
407 		[ RISC_WRITERM >> 28 ] = "writerm",
408 		[ RISC_WRITECM >> 28 ] = "writecm",
409 		[ RISC_WRITECR >> 28 ] = "writecr",
410 	};
411 	static int const incr[16] = {
412 		[ RISC_WRITE   >> 28 ] = 2,
413 		[ RISC_JUMP    >> 28 ] = 2,
414 		[ RISC_WRITERM >> 28 ] = 3,
415 		[ RISC_WRITECM >> 28 ] = 3,
416 		[ RISC_WRITECR >> 28 ] = 4,
417 	};
418 	static const char * const bits[] = {
419 		"12",   "13",   "14",   "resync",
420 		"cnt0", "cnt1", "18",   "19",
421 		"20",   "21",   "22",   "23",
422 		"irq1", "irq2", "eol",  "sol",
423 	};
424 	int i;
425 
426 	printk("0x%08x [ %s", risc,
427 	       instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
428 	for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
429 		if (risc & (1 << (i + 12)))
430 			printk(" %s",bits[i]);
431 	printk(" count=%d ]\n", risc & 0xfff);
432 	return incr[risc >> 28] ? incr[risc >> 28] : 1;
433 }
434 
435 
436 void cx88_sram_channel_dump(struct cx88_core *core,
437 			    const struct sram_channel *ch)
438 {
439 	static const char * const name[] = {
440 		"initial risc",
441 		"cdt base",
442 		"cdt size",
443 		"iq base",
444 		"iq size",
445 		"risc pc",
446 		"iq wr ptr",
447 		"iq rd ptr",
448 		"cdt current",
449 		"pci target",
450 		"line / byte",
451 	};
452 	u32 risc;
453 	unsigned int i,j,n;
454 
455 	printk("%s: %s - dma channel status dump\n",
456 	       core->name,ch->name);
457 	for (i = 0; i < ARRAY_SIZE(name); i++)
458 		printk("%s:   cmds: %-12s: 0x%08x\n",
459 		       core->name,name[i],
460 		       cx_read(ch->cmds_start + 4*i));
461 	for (n = 1, i = 0; i < 4; i++) {
462 		risc = cx_read(ch->cmds_start + 4 * (i+11));
463 		printk("%s:   risc%d: ", core->name, i);
464 		if (--n)
465 			printk("0x%08x [ arg #%d ]\n", risc, n);
466 		else
467 			n = cx88_risc_decode(risc);
468 	}
469 	for (i = 0; i < 16; i += n) {
470 		risc = cx_read(ch->ctrl_start + 4 * i);
471 		printk("%s:   iq %x: ", core->name, i);
472 		n = cx88_risc_decode(risc);
473 		for (j = 1; j < n; j++) {
474 			risc = cx_read(ch->ctrl_start + 4 * (i+j));
475 			printk("%s:   iq %x: 0x%08x [ arg #%d ]\n",
476 			       core->name, i+j, risc, j);
477 		}
478 	}
479 
480 	printk("%s: fifo: 0x%08x -> 0x%x\n",
481 	       core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
482 	printk("%s: ctrl: 0x%08x -> 0x%x\n",
483 	       core->name, ch->ctrl_start, ch->ctrl_start+6*16);
484 	printk("%s:   ptr1_reg: 0x%08x\n",
485 	       core->name,cx_read(ch->ptr1_reg));
486 	printk("%s:   ptr2_reg: 0x%08x\n",
487 	       core->name,cx_read(ch->ptr2_reg));
488 	printk("%s:   cnt1_reg: 0x%08x\n",
489 	       core->name,cx_read(ch->cnt1_reg));
490 	printk("%s:   cnt2_reg: 0x%08x\n",
491 	       core->name,cx_read(ch->cnt2_reg));
492 }
493 
494 static const char *cx88_pci_irqs[32] = {
495 	"vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
496 	"src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
497 	"brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
498 	"i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
499 };
500 
501 void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
502 			int len, u32 bits, u32 mask)
503 {
504 	unsigned int i;
505 
506 	printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
507 	for (i = 0; i < len; i++) {
508 		if (!(bits & (1 << i)))
509 			continue;
510 		if (strings[i])
511 			printk(" %s", strings[i]);
512 		else
513 			printk(" %d", i);
514 		if (!(mask & (1 << i)))
515 			continue;
516 		printk("*");
517 	}
518 	printk("\n");
519 }
520 
521 /* ------------------------------------------------------------------ */
522 
523 int cx88_core_irq(struct cx88_core *core, u32 status)
524 {
525 	int handled = 0;
526 
527 	if (status & PCI_INT_IR_SMPINT) {
528 		cx88_ir_irq(core);
529 		handled++;
530 	}
531 	if (!handled)
532 		cx88_print_irqbits(core->name, "irq pci",
533 				   cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
534 				   status, core->pci_irqmask);
535 	return handled;
536 }
537 
538 void cx88_wakeup(struct cx88_core *core,
539 		 struct cx88_dmaqueue *q, u32 count)
540 {
541 	struct cx88_buffer *buf;
542 	int bc;
543 
544 	for (bc = 0;; bc++) {
545 		if (list_empty(&q->active))
546 			break;
547 		buf = list_entry(q->active.next,
548 				 struct cx88_buffer, vb.queue);
549 		/* count comes from the hw and is is 16bit wide --
550 		 * this trick handles wrap-arounds correctly for
551 		 * up to 32767 buffers in flight... */
552 		if ((s16) (count - buf->count) < 0)
553 			break;
554 		v4l2_get_timestamp(&buf->vb.ts);
555 		dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
556 			count, buf->count);
557 		buf->vb.state = VIDEOBUF_DONE;
558 		list_del(&buf->vb.queue);
559 		wake_up(&buf->vb.done);
560 	}
561 	if (list_empty(&q->active)) {
562 		del_timer(&q->timeout);
563 	} else {
564 		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
565 	}
566 	if (bc != 1)
567 		dprintk(2, "%s: %d buffers handled (should be 1)\n",
568 			__func__, bc);
569 }
570 
571 void cx88_shutdown(struct cx88_core *core)
572 {
573 	/* disable RISC controller + IRQs */
574 	cx_write(MO_DEV_CNTRL2, 0);
575 
576 	/* stop dma transfers */
577 	cx_write(MO_VID_DMACNTRL, 0x0);
578 	cx_write(MO_AUD_DMACNTRL, 0x0);
579 	cx_write(MO_TS_DMACNTRL, 0x0);
580 	cx_write(MO_VIP_DMACNTRL, 0x0);
581 	cx_write(MO_GPHST_DMACNTRL, 0x0);
582 
583 	/* stop interrupts */
584 	cx_write(MO_PCI_INTMSK, 0x0);
585 	cx_write(MO_VID_INTMSK, 0x0);
586 	cx_write(MO_AUD_INTMSK, 0x0);
587 	cx_write(MO_TS_INTMSK, 0x0);
588 	cx_write(MO_VIP_INTMSK, 0x0);
589 	cx_write(MO_GPHST_INTMSK, 0x0);
590 
591 	/* stop capturing */
592 	cx_write(VID_CAPTURE_CONTROL, 0);
593 }
594 
595 int cx88_reset(struct cx88_core *core)
596 {
597 	dprintk(1,"%s\n",__func__);
598 	cx88_shutdown(core);
599 
600 	/* clear irq status */
601 	cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
602 	cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
603 	cx_write(MO_INT1_STAT,   0xFFFFFFFF); // Clear RISC int
604 
605 	/* wait a bit */
606 	msleep(100);
607 
608 	/* init sram */
609 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
610 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
611 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
612 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
613 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
614 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
615 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
616 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
617 
618 	/* misc init ... */
619 	cx_write(MO_INPUT_FORMAT, ((1 << 13) |   // agc enable
620 				   (1 << 12) |   // agc gain
621 				   (1 << 11) |   // adaptibe agc
622 				   (0 << 10) |   // chroma agc
623 				   (0 <<  9) |   // ckillen
624 				   (7)));
625 
626 	/* setup image format */
627 	cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
628 
629 	/* setup FIFO Thresholds */
630 	cx_write(MO_PDMA_STHRSH,   0x0807);
631 	cx_write(MO_PDMA_DTHRSH,   0x0807);
632 
633 	/* fixes flashing of image */
634 	cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
635 	cx_write(MO_AGC_BACK_VBI,  0x00E00555);
636 
637 	cx_write(MO_VID_INTSTAT,   0xFFFFFFFF); // Clear PIV int
638 	cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int
639 	cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int
640 
641 	/* Reset on-board parts */
642 	cx_write(MO_SRST_IO, 0);
643 	msleep(10);
644 	cx_write(MO_SRST_IO, 1);
645 
646 	return 0;
647 }
648 
649 /* ------------------------------------------------------------------ */
650 
651 static inline unsigned int norm_swidth(v4l2_std_id norm)
652 {
653 	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
654 }
655 
656 static inline unsigned int norm_hdelay(v4l2_std_id norm)
657 {
658 	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
659 }
660 
661 static inline unsigned int norm_vdelay(v4l2_std_id norm)
662 {
663 	return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
664 }
665 
666 static inline unsigned int norm_fsc8(v4l2_std_id norm)
667 {
668 	if (norm & V4L2_STD_PAL_M)
669 		return 28604892;      // 3.575611 MHz
670 
671 	if (norm & (V4L2_STD_PAL_Nc))
672 		return 28656448;      // 3.582056 MHz
673 
674 	if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
675 		return 28636360;      // 3.57954545 MHz +/- 10 Hz
676 
677 	/* SECAM have also different sub carrier for chroma,
678 	   but step_db and step_dr, at cx88_set_tvnorm already handles that.
679 
680 	   The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
681 	 */
682 
683 	return 35468950;      // 4.43361875 MHz +/- 5 Hz
684 }
685 
686 static inline unsigned int norm_htotal(v4l2_std_id norm)
687 {
688 
689 	unsigned int fsc4=norm_fsc8(norm)/2;
690 
691 	/* returns 4*FSC / vtotal / frames per seconds */
692 	return (norm & V4L2_STD_625_50) ?
693 				((fsc4+312)/625+12)/25 :
694 				((fsc4+262)/525*1001+15000)/30000;
695 }
696 
697 static inline unsigned int norm_vbipack(v4l2_std_id norm)
698 {
699 	return (norm & V4L2_STD_625_50) ? 511 : 400;
700 }
701 
702 int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
703 		   enum v4l2_field field)
704 {
705 	unsigned int swidth  = norm_swidth(core->tvnorm);
706 	unsigned int sheight = norm_maxh(core->tvnorm);
707 	u32 value;
708 
709 	dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
710 		V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
711 		V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
712 		v4l2_norm_to_name(core->tvnorm));
713 	if (!V4L2_FIELD_HAS_BOTH(field))
714 		height *= 2;
715 
716 	// recalc H delay and scale registers
717 	value = (width * norm_hdelay(core->tvnorm)) / swidth;
718 	value &= 0x3fe;
719 	cx_write(MO_HDELAY_EVEN,  value);
720 	cx_write(MO_HDELAY_ODD,   value);
721 	dprintk(1,"set_scale: hdelay  0x%04x (width %d)\n", value,swidth);
722 
723 	value = (swidth * 4096 / width) - 4096;
724 	cx_write(MO_HSCALE_EVEN,  value);
725 	cx_write(MO_HSCALE_ODD,   value);
726 	dprintk(1,"set_scale: hscale  0x%04x\n", value);
727 
728 	cx_write(MO_HACTIVE_EVEN, width);
729 	cx_write(MO_HACTIVE_ODD,  width);
730 	dprintk(1,"set_scale: hactive 0x%04x\n", width);
731 
732 	// recalc V scale Register (delay is constant)
733 	cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
734 	cx_write(MO_VDELAY_ODD,  norm_vdelay(core->tvnorm));
735 	dprintk(1,"set_scale: vdelay  0x%04x\n", norm_vdelay(core->tvnorm));
736 
737 	value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
738 	cx_write(MO_VSCALE_EVEN,  value);
739 	cx_write(MO_VSCALE_ODD,   value);
740 	dprintk(1,"set_scale: vscale  0x%04x\n", value);
741 
742 	cx_write(MO_VACTIVE_EVEN, sheight);
743 	cx_write(MO_VACTIVE_ODD,  sheight);
744 	dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
745 
746 	// setup filters
747 	value = 0;
748 	value |= (1 << 19);        // CFILT (default)
749 	if (core->tvnorm & V4L2_STD_SECAM) {
750 		value |= (1 << 15);
751 		value |= (1 << 16);
752 	}
753 	if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
754 		value |= (1 << 13) | (1 << 5);
755 	if (V4L2_FIELD_INTERLACED == field)
756 		value |= (1 << 3); // VINT (interlaced vertical scaling)
757 	if (width < 385)
758 		value |= (1 << 0); // 3-tap interpolation
759 	if (width < 193)
760 		value |= (1 << 1); // 5-tap interpolation
761 	if (nocomb)
762 		value |= (3 << 5); // disable comb filter
763 
764 	cx_andor(MO_FILTER_EVEN,  0x7ffc7f, value); /* preserve PEAKEN, PSEL */
765 	cx_andor(MO_FILTER_ODD,   0x7ffc7f, value);
766 	dprintk(1,"set_scale: filter  0x%04x\n", value);
767 
768 	return 0;
769 }
770 
771 static const u32 xtal = 28636363;
772 
773 static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
774 {
775 	static const u32 pre[] = { 0, 0, 0, 3, 2, 1 };
776 	u64 pll;
777 	u32 reg;
778 	int i;
779 
780 	if (prescale < 2)
781 		prescale = 2;
782 	if (prescale > 5)
783 		prescale = 5;
784 
785 	pll = ofreq * 8 * prescale * (u64)(1 << 20);
786 	do_div(pll,xtal);
787 	reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
788 	if (((reg >> 20) & 0x3f) < 14) {
789 		printk("%s/0: pll out of range\n",core->name);
790 		return -1;
791 	}
792 
793 	dprintk(1,"set_pll:    MO_PLL_REG       0x%08x [old=0x%08x,freq=%d]\n",
794 		reg, cx_read(MO_PLL_REG), ofreq);
795 	cx_write(MO_PLL_REG, reg);
796 	for (i = 0; i < 100; i++) {
797 		reg = cx_read(MO_DEVICE_STATUS);
798 		if (reg & (1<<2)) {
799 			dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
800 				prescale,ofreq);
801 			return 0;
802 		}
803 		dprintk(1,"pll not locked yet, waiting ...\n");
804 		msleep(10);
805 	}
806 	dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
807 	return -1;
808 }
809 
810 int cx88_start_audio_dma(struct cx88_core *core)
811 {
812 	/* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
813 	int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
814 
815 	int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
816 
817 	/* If downstream RISC is enabled, bail out; ALSA is managing DMA */
818 	if (cx_read(MO_AUD_DMACNTRL) & 0x10)
819 		return 0;
820 
821 	/* setup fifo + format */
822 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
823 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
824 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
825 				rds_bpl, 0);
826 
827 	cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
828 	cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
829 
830 	/* enable Up, Down and Audio RDS fifo */
831 	cx_write(MO_AUD_DMACNTRL, 0x0007);
832 
833 	return 0;
834 }
835 
836 int cx88_stop_audio_dma(struct cx88_core *core)
837 {
838 	/* If downstream RISC is enabled, bail out; ALSA is managing DMA */
839 	if (cx_read(MO_AUD_DMACNTRL) & 0x10)
840 		return 0;
841 
842 	/* stop dma */
843 	cx_write(MO_AUD_DMACNTRL, 0x0000);
844 
845 	return 0;
846 }
847 
848 static int set_tvaudio(struct cx88_core *core)
849 {
850 	v4l2_std_id norm = core->tvnorm;
851 
852 	if (CX88_VMUX_TELEVISION != INPUT(core->input).type &&
853 	    CX88_VMUX_CABLE != INPUT(core->input).type)
854 		return 0;
855 
856 	if (V4L2_STD_PAL_BG & norm) {
857 		core->tvaudio = WW_BG;
858 
859 	} else if (V4L2_STD_PAL_DK & norm) {
860 		core->tvaudio = WW_DK;
861 
862 	} else if (V4L2_STD_PAL_I & norm) {
863 		core->tvaudio = WW_I;
864 
865 	} else if (V4L2_STD_SECAM_L & norm) {
866 		core->tvaudio = WW_L;
867 
868 	} else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
869 		core->tvaudio = WW_BG;
870 
871 	} else if (V4L2_STD_SECAM_DK & norm) {
872 		core->tvaudio = WW_DK;
873 
874 	} else if ((V4L2_STD_NTSC_M & norm) ||
875 		   (V4L2_STD_PAL_M  & norm)) {
876 		core->tvaudio = WW_BTSC;
877 
878 	} else if (V4L2_STD_NTSC_M_JP & norm) {
879 		core->tvaudio = WW_EIAJ;
880 
881 	} else {
882 		printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
883 		       core->name, v4l2_norm_to_name(core->tvnorm));
884 		core->tvaudio = WW_NONE;
885 		return 0;
886 	}
887 
888 	cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
889 	cx88_set_tvaudio(core);
890 	/* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
891 
892 /*
893    This should be needed only on cx88-alsa. It seems that some cx88 chips have
894    bugs and does require DMA enabled for it to work.
895  */
896 	cx88_start_audio_dma(core);
897 	return 0;
898 }
899 
900 
901 
902 int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
903 {
904 	u32 fsc8;
905 	u32 adc_clock;
906 	u32 vdec_clock;
907 	u32 step_db,step_dr;
908 	u64 tmp64;
909 	u32 bdelay,agcdelay,htotal;
910 	u32 cxiformat, cxoformat;
911 
912 	core->tvnorm = norm;
913 	fsc8       = norm_fsc8(norm);
914 	adc_clock  = xtal;
915 	vdec_clock = fsc8;
916 	step_db    = fsc8;
917 	step_dr    = fsc8;
918 
919 	if (norm & V4L2_STD_NTSC_M_JP) {
920 		cxiformat = VideoFormatNTSCJapan;
921 		cxoformat = 0x181f0008;
922 	} else if (norm & V4L2_STD_NTSC_443) {
923 		cxiformat = VideoFormatNTSC443;
924 		cxoformat = 0x181f0008;
925 	} else if (norm & V4L2_STD_PAL_M) {
926 		cxiformat = VideoFormatPALM;
927 		cxoformat = 0x1c1f0008;
928 	} else if (norm & V4L2_STD_PAL_N) {
929 		cxiformat = VideoFormatPALN;
930 		cxoformat = 0x1c1f0008;
931 	} else if (norm & V4L2_STD_PAL_Nc) {
932 		cxiformat = VideoFormatPALNC;
933 		cxoformat = 0x1c1f0008;
934 	} else if (norm & V4L2_STD_PAL_60) {
935 		cxiformat = VideoFormatPAL60;
936 		cxoformat = 0x181f0008;
937 	} else if (norm & V4L2_STD_NTSC) {
938 		cxiformat = VideoFormatNTSC;
939 		cxoformat = 0x181f0008;
940 	} else if (norm & V4L2_STD_SECAM) {
941 		step_db = 4250000 * 8;
942 		step_dr = 4406250 * 8;
943 
944 		cxiformat = VideoFormatSECAM;
945 		cxoformat = 0x181f0008;
946 	} else { /* PAL */
947 		cxiformat = VideoFormatPAL;
948 		cxoformat = 0x181f0008;
949 	}
950 
951 	dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
952 		v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
953 		step_db, step_dr);
954 	set_pll(core,2,vdec_clock);
955 
956 	dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
957 		cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
958 	/* Chroma AGC must be disabled if SECAM is used, we enable it
959 	   by default on PAL and NTSC */
960 	cx_andor(MO_INPUT_FORMAT, 0x40f,
961 		 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
962 
963 	// FIXME: as-is from DScaler
964 	dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
965 		cxoformat, cx_read(MO_OUTPUT_FORMAT));
966 	cx_write(MO_OUTPUT_FORMAT, cxoformat);
967 
968 	// MO_SCONV_REG = adc clock / video dec clock * 2^17
969 	tmp64  = adc_clock * (u64)(1 << 17);
970 	do_div(tmp64, vdec_clock);
971 	dprintk(1,"set_tvnorm: MO_SCONV_REG     0x%08x [old=0x%08x]\n",
972 		(u32)tmp64, cx_read(MO_SCONV_REG));
973 	cx_write(MO_SCONV_REG, (u32)tmp64);
974 
975 	// MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
976 	tmp64  = step_db * (u64)(1 << 22);
977 	do_div(tmp64, vdec_clock);
978 	dprintk(1,"set_tvnorm: MO_SUB_STEP      0x%08x [old=0x%08x]\n",
979 		(u32)tmp64, cx_read(MO_SUB_STEP));
980 	cx_write(MO_SUB_STEP, (u32)tmp64);
981 
982 	// MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
983 	tmp64  = step_dr * (u64)(1 << 22);
984 	do_div(tmp64, vdec_clock);
985 	dprintk(1,"set_tvnorm: MO_SUB_STEP_DR   0x%08x [old=0x%08x]\n",
986 		(u32)tmp64, cx_read(MO_SUB_STEP_DR));
987 	cx_write(MO_SUB_STEP_DR, (u32)tmp64);
988 
989 	// bdelay + agcdelay
990 	bdelay   = vdec_clock * 65 / 20000000 + 21;
991 	agcdelay = vdec_clock * 68 / 20000000 + 15;
992 	dprintk(1,"set_tvnorm: MO_AGC_BURST     0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
993 		(bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
994 	cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
995 
996 	// htotal
997 	tmp64 = norm_htotal(norm) * (u64)vdec_clock;
998 	do_div(tmp64, fsc8);
999 	htotal = (u32)tmp64;
1000 	dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
1001 		htotal, cx_read(MO_HTOTAL), (u32)tmp64);
1002 	cx_andor(MO_HTOTAL, 0x07ff, htotal);
1003 
1004 	// vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
1005 	// the effective vbi offset ~244 samples, the same as the Bt8x8
1006 	cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
1007 
1008 	// this is needed as well to set all tvnorm parameter
1009 	cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
1010 
1011 	// audio
1012 	set_tvaudio(core);
1013 
1014 	// tell i2c chips
1015 	call_all(core, core, s_std, norm);
1016 
1017 	/* The chroma_agc control should be inaccessible if the video format is SECAM */
1018 	v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
1019 
1020 	// done
1021 	return 0;
1022 }
1023 
1024 /* ------------------------------------------------------------------ */
1025 
1026 struct video_device *cx88_vdev_init(struct cx88_core *core,
1027 				    struct pci_dev *pci,
1028 				    const struct video_device *template_,
1029 				    const char *type)
1030 {
1031 	struct video_device *vfd;
1032 
1033 	vfd = video_device_alloc();
1034 	if (NULL == vfd)
1035 		return NULL;
1036 	*vfd = *template_;
1037 	/*
1038 	 * The dev pointer of v4l2_device is NULL, instead we set the
1039 	 * video_device dev_parent pointer to the correct PCI bus device.
1040 	 * This driver is a rare example where there is one v4l2_device,
1041 	 * but the video nodes have different parent (PCI) devices.
1042 	 */
1043 	vfd->v4l2_dev = &core->v4l2_dev;
1044 	vfd->dev_parent = &pci->dev;
1045 	vfd->release = video_device_release;
1046 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1047 		 core->name, type, core->board.name);
1048 	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
1049 	return vfd;
1050 }
1051 
1052 struct cx88_core* cx88_core_get(struct pci_dev *pci)
1053 {
1054 	struct cx88_core *core;
1055 
1056 	mutex_lock(&devlist);
1057 	list_for_each_entry(core, &cx88_devlist, devlist) {
1058 		if (pci->bus->number != core->pci_bus)
1059 			continue;
1060 		if (PCI_SLOT(pci->devfn) != core->pci_slot)
1061 			continue;
1062 
1063 		if (0 != cx88_get_resources(core, pci)) {
1064 			mutex_unlock(&devlist);
1065 			return NULL;
1066 		}
1067 		atomic_inc(&core->refcount);
1068 		mutex_unlock(&devlist);
1069 		return core;
1070 	}
1071 
1072 	core = cx88_core_create(pci, cx88_devcount);
1073 	if (NULL != core) {
1074 		cx88_devcount++;
1075 		list_add_tail(&core->devlist, &cx88_devlist);
1076 	}
1077 
1078 	mutex_unlock(&devlist);
1079 	return core;
1080 }
1081 
1082 void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1083 {
1084 	release_mem_region(pci_resource_start(pci,0),
1085 			   pci_resource_len(pci,0));
1086 
1087 	if (!atomic_dec_and_test(&core->refcount))
1088 		return;
1089 
1090 	mutex_lock(&devlist);
1091 	cx88_ir_fini(core);
1092 	if (0 == core->i2c_rc) {
1093 		if (core->i2c_rtc)
1094 			i2c_unregister_device(core->i2c_rtc);
1095 		i2c_del_adapter(&core->i2c_adap);
1096 	}
1097 	list_del(&core->devlist);
1098 	iounmap(core->lmmio);
1099 	cx88_devcount--;
1100 	mutex_unlock(&devlist);
1101 	v4l2_ctrl_handler_free(&core->video_hdl);
1102 	v4l2_ctrl_handler_free(&core->audio_hdl);
1103 	v4l2_device_unregister(&core->v4l2_dev);
1104 	kfree(core);
1105 }
1106 
1107 /* ------------------------------------------------------------------ */
1108 
1109 EXPORT_SYMBOL(cx88_print_irqbits);
1110 
1111 EXPORT_SYMBOL(cx88_core_irq);
1112 EXPORT_SYMBOL(cx88_wakeup);
1113 EXPORT_SYMBOL(cx88_reset);
1114 EXPORT_SYMBOL(cx88_shutdown);
1115 
1116 EXPORT_SYMBOL(cx88_risc_buffer);
1117 EXPORT_SYMBOL(cx88_risc_databuffer);
1118 EXPORT_SYMBOL(cx88_risc_stopper);
1119 EXPORT_SYMBOL(cx88_free_buffer);
1120 
1121 EXPORT_SYMBOL(cx88_sram_channels);
1122 EXPORT_SYMBOL(cx88_sram_channel_setup);
1123 EXPORT_SYMBOL(cx88_sram_channel_dump);
1124 
1125 EXPORT_SYMBOL(cx88_set_tvnorm);
1126 EXPORT_SYMBOL(cx88_set_scale);
1127 
1128 EXPORT_SYMBOL(cx88_vdev_init);
1129 EXPORT_SYMBOL(cx88_core_get);
1130 EXPORT_SYMBOL(cx88_core_put);
1131 
1132 EXPORT_SYMBOL(cx88_ir_start);
1133 EXPORT_SYMBOL(cx88_ir_stop);
1134 
1135 /*
1136  * Local variables:
1137  * c-basic-offset: 8
1138  * End:
1139  * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
1140  */
1141