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