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. */
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)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
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)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
cx88_risc_databuffer(struct pci_dev * pci,struct btcx_riscmem * risc,struct scatterlist * sglist,unsigned int bpl,unsigned int lines,unsigned int lpi)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
cx88_risc_stopper(struct pci_dev * pci,struct btcx_riscmem * risc,u32 reg,u32 mask,u32 value)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
cx88_free_buffer(struct videobuf_queue * q,struct cx88_buffer * buf)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
cx88_sram_channel_setup(struct cx88_core * core,const struct sram_channel * ch,unsigned int bpl,u32 risc)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
cx88_risc_decode(u32 risc)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
cx88_sram_channel_dump(struct cx88_core * core,const struct sram_channel * ch)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
cx88_print_irqbits(const char * name,const char * tag,const char * strings[],int len,u32 bits,u32 mask)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
cx88_core_irq(struct cx88_core * core,u32 status)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
cx88_wakeup(struct cx88_core * core,struct cx88_dmaqueue * q,u32 count)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
cx88_shutdown(struct cx88_core * core)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
cx88_reset(struct cx88_core * core)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
norm_swidth(v4l2_std_id norm)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
norm_hdelay(v4l2_std_id norm)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
norm_vdelay(v4l2_std_id norm)661 static inline unsigned int norm_vdelay(v4l2_std_id norm)
662 {
663 return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
664 }
665
norm_fsc8(v4l2_std_id norm)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
norm_htotal(v4l2_std_id norm)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
norm_vbipack(v4l2_std_id norm)697 static inline unsigned int norm_vbipack(v4l2_std_id norm)
698 {
699 return (norm & V4L2_STD_625_50) ? 511 : 400;
700 }
701
cx88_set_scale(struct cx88_core * core,unsigned int width,unsigned int height,enum v4l2_field field)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
set_pll(struct cx88_core * core,int prescale,u32 ofreq)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
cx88_start_audio_dma(struct cx88_core * core)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
cx88_stop_audio_dma(struct cx88_core * core)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
set_tvaudio(struct cx88_core * core)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
cx88_set_tvnorm(struct cx88_core * core,v4l2_std_id norm)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
cx88_vdev_init(struct cx88_core * core,struct pci_dev * pci,const struct video_device * template_,const char * type)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 vfd->v4l2_dev = &core->v4l2_dev;
1038 vfd->release = video_device_release;
1039 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1040 core->name, type, core->board.name);
1041 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
1042 return vfd;
1043 }
1044
cx88_core_get(struct pci_dev * pci)1045 struct cx88_core* cx88_core_get(struct pci_dev *pci)
1046 {
1047 struct cx88_core *core;
1048
1049 mutex_lock(&devlist);
1050 list_for_each_entry(core, &cx88_devlist, devlist) {
1051 if (pci->bus->number != core->pci_bus)
1052 continue;
1053 if (PCI_SLOT(pci->devfn) != core->pci_slot)
1054 continue;
1055
1056 if (0 != cx88_get_resources(core, pci)) {
1057 mutex_unlock(&devlist);
1058 return NULL;
1059 }
1060 atomic_inc(&core->refcount);
1061 mutex_unlock(&devlist);
1062 return core;
1063 }
1064
1065 core = cx88_core_create(pci, cx88_devcount);
1066 if (NULL != core) {
1067 cx88_devcount++;
1068 list_add_tail(&core->devlist, &cx88_devlist);
1069 }
1070
1071 mutex_unlock(&devlist);
1072 return core;
1073 }
1074
cx88_core_put(struct cx88_core * core,struct pci_dev * pci)1075 void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1076 {
1077 release_mem_region(pci_resource_start(pci,0),
1078 pci_resource_len(pci,0));
1079
1080 if (!atomic_dec_and_test(&core->refcount))
1081 return;
1082
1083 mutex_lock(&devlist);
1084 cx88_ir_fini(core);
1085 if (0 == core->i2c_rc) {
1086 if (core->i2c_rtc)
1087 i2c_unregister_device(core->i2c_rtc);
1088 i2c_del_adapter(&core->i2c_adap);
1089 }
1090 list_del(&core->devlist);
1091 iounmap(core->lmmio);
1092 cx88_devcount--;
1093 mutex_unlock(&devlist);
1094 v4l2_ctrl_handler_free(&core->video_hdl);
1095 v4l2_ctrl_handler_free(&core->audio_hdl);
1096 v4l2_device_unregister(&core->v4l2_dev);
1097 kfree(core);
1098 }
1099
1100 /* ------------------------------------------------------------------ */
1101
1102 EXPORT_SYMBOL(cx88_print_irqbits);
1103
1104 EXPORT_SYMBOL(cx88_core_irq);
1105 EXPORT_SYMBOL(cx88_wakeup);
1106 EXPORT_SYMBOL(cx88_reset);
1107 EXPORT_SYMBOL(cx88_shutdown);
1108
1109 EXPORT_SYMBOL(cx88_risc_buffer);
1110 EXPORT_SYMBOL(cx88_risc_databuffer);
1111 EXPORT_SYMBOL(cx88_risc_stopper);
1112 EXPORT_SYMBOL(cx88_free_buffer);
1113
1114 EXPORT_SYMBOL(cx88_sram_channels);
1115 EXPORT_SYMBOL(cx88_sram_channel_setup);
1116 EXPORT_SYMBOL(cx88_sram_channel_dump);
1117
1118 EXPORT_SYMBOL(cx88_set_tvnorm);
1119 EXPORT_SYMBOL(cx88_set_scale);
1120
1121 EXPORT_SYMBOL(cx88_vdev_init);
1122 EXPORT_SYMBOL(cx88_core_get);
1123 EXPORT_SYMBOL(cx88_core_put);
1124
1125 EXPORT_SYMBOL(cx88_ir_start);
1126 EXPORT_SYMBOL(cx88_ir_stop);
1127
1128 /*
1129 * Local variables:
1130 * c-basic-offset: 8
1131 * End:
1132 * 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
1133 */
1134