[PATCH] v4l: CX88 cards update
[deliverable/linux.git] / drivers / media / video / cx88 / cx88-core.c
1 /*
2 * $Id: cx88-core.c,v 1.28 2005/06/12 04:19:19 mchehab Exp $
3 *
4 * device driver for Conexant 2388x based TV cards
5 * driver core
6 *
7 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include <linux/init.h>
25 #include <linux/list.h>
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/kernel.h>
29 #include <linux/slab.h>
30 #include <linux/kmod.h>
31 #include <linux/sound.h>
32 #include <linux/interrupt.h>
33 #include <linux/pci.h>
34 #include <linux/delay.h>
35 #include <linux/videodev.h>
36
37 #include "cx88.h"
38
39 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
40 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
41 MODULE_LICENSE("GPL");
42
43 /* ------------------------------------------------------------------ */
44
45 static unsigned int core_debug = 0;
46 module_param(core_debug,int,0644);
47 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
48
49 static unsigned int latency = UNSET;
50 module_param(latency,int,0444);
51 MODULE_PARM_DESC(latency,"pci latency timer");
52
53 static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
54 static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
55 static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
56
57 module_param_array(tuner, int, NULL, 0444);
58 module_param_array(radio, int, NULL, 0444);
59 module_param_array(card, int, NULL, 0444);
60
61 MODULE_PARM_DESC(tuner,"tuner type");
62 MODULE_PARM_DESC(radio,"radio tuner type");
63 MODULE_PARM_DESC(card,"card type");
64
65 static unsigned int nicam = 0;
66 module_param(nicam,int,0644);
67 MODULE_PARM_DESC(nicam,"tv audio is nicam");
68
69 static unsigned int nocomb = 0;
70 module_param(nocomb,int,0644);
71 MODULE_PARM_DESC(nocomb,"disable comb filter");
72
73 #define dprintk(level,fmt, arg...) if (core_debug >= level) \
74 printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
75
76 static unsigned int cx88_devcount;
77 static LIST_HEAD(cx88_devlist);
78 static DECLARE_MUTEX(devlist);
79
80 /* ------------------------------------------------------------------ */
81 /* debug help functions */
82
83 static const char *v4l1_ioctls[] = {
84 "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
85 "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
86 "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
87 "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
88 "SMICROCODE", "GVBIFMT", "SVBIFMT" };
89 #define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
90
91 static const char *v4l2_ioctls[] = {
92 "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
93 "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
94 "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
95 "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
96 "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
97 "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
98 "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
99 "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
100 "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
101 "S_MODULATOR"
102 };
103 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
104
105 void cx88_print_ioctl(char *name, unsigned int cmd)
106 {
107 char *dir;
108
109 switch (_IOC_DIR(cmd)) {
110 case _IOC_NONE: dir = "--"; break;
111 case _IOC_READ: dir = "r-"; break;
112 case _IOC_WRITE: dir = "-w"; break;
113 case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
114 default: dir = "??"; break;
115 }
116 switch (_IOC_TYPE(cmd)) {
117 case 'v':
118 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
119 name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
120 v4l1_ioctls[_IOC_NR(cmd)] : "???");
121 break;
122 case 'V':
123 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
124 name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
125 v4l2_ioctls[_IOC_NR(cmd)] : "???");
126 break;
127 default:
128 printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
129 name, cmd, dir, _IOC_NR(cmd));
130 }
131 }
132
133 /* ------------------------------------------------------------------ */
134 #define NO_SYNC_LINE (-1U)
135
136 static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
137 unsigned int offset, u32 sync_line,
138 unsigned int bpl, unsigned int padding,
139 unsigned int lines)
140 {
141 struct scatterlist *sg;
142 unsigned int line,todo;
143
144 /* sync instruction */
145 if (sync_line != NO_SYNC_LINE)
146 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
147
148 /* scan lines */
149 sg = sglist;
150 for (line = 0; line < lines; line++) {
151 while (offset && offset >= sg_dma_len(sg)) {
152 offset -= sg_dma_len(sg);
153 sg++;
154 }
155 if (bpl <= sg_dma_len(sg)-offset) {
156 /* fits into current chunk */
157 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
158 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
159 offset+=bpl;
160 } else {
161 /* scanline needs to be splitted */
162 todo = bpl;
163 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
164 (sg_dma_len(sg)-offset));
165 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
166 todo -= (sg_dma_len(sg)-offset);
167 offset = 0;
168 sg++;
169 while (todo > sg_dma_len(sg)) {
170 *(rp++)=cpu_to_le32(RISC_WRITE|
171 sg_dma_len(sg));
172 *(rp++)=cpu_to_le32(sg_dma_address(sg));
173 todo -= sg_dma_len(sg);
174 sg++;
175 }
176 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
177 *(rp++)=cpu_to_le32(sg_dma_address(sg));
178 offset += todo;
179 }
180 offset += padding;
181 }
182
183 return rp;
184 }
185
186 int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
187 struct scatterlist *sglist,
188 unsigned int top_offset, unsigned int bottom_offset,
189 unsigned int bpl, unsigned int padding, unsigned int lines)
190 {
191 u32 instructions,fields;
192 u32 *rp;
193 int rc;
194
195 fields = 0;
196 if (UNSET != top_offset)
197 fields++;
198 if (UNSET != bottom_offset)
199 fields++;
200
201 /* estimate risc mem: worst case is one write per page border +
202 one write per scan line + syncs + jump (all 2 dwords) */
203 instructions = (bpl * lines * fields) / PAGE_SIZE + lines * fields;
204 instructions += 3 + 4;
205 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
206 return rc;
207
208 /* write risc instructions */
209 rp = risc->cpu;
210 if (UNSET != top_offset)
211 rp = cx88_risc_field(rp, sglist, top_offset, 0,
212 bpl, padding, lines);
213 if (UNSET != bottom_offset)
214 rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
215 bpl, padding, lines);
216
217 /* save pointer to jmp instruction address */
218 risc->jmp = rp;
219 BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
220 return 0;
221 }
222
223 int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
224 struct scatterlist *sglist, unsigned int bpl,
225 unsigned int lines)
226 {
227 u32 instructions;
228 u32 *rp;
229 int rc;
230
231 /* estimate risc mem: worst case is one write per page border +
232 one write per scan line + syncs + jump (all 2 dwords) */
233 instructions = (bpl * lines) / PAGE_SIZE + lines;
234 instructions += 3 + 4;
235 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
236 return rc;
237
238 /* write risc instructions */
239 rp = risc->cpu;
240 rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
241
242 /* save pointer to jmp instruction address */
243 risc->jmp = rp;
244 BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
245 return 0;
246 }
247
248 int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
249 u32 reg, u32 mask, u32 value)
250 {
251 u32 *rp;
252 int rc;
253
254 if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
255 return rc;
256
257 /* write risc instructions */
258 rp = risc->cpu;
259 *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
260 *(rp++) = cpu_to_le32(reg);
261 *(rp++) = cpu_to_le32(value);
262 *(rp++) = cpu_to_le32(mask);
263 *(rp++) = cpu_to_le32(RISC_JUMP);
264 *(rp++) = cpu_to_le32(risc->dma);
265 return 0;
266 }
267
268 void
269 cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
270 {
271 if (in_interrupt())
272 BUG();
273 videobuf_waiton(&buf->vb,0,0);
274 videobuf_dma_pci_unmap(pci, &buf->vb.dma);
275 videobuf_dma_free(&buf->vb.dma);
276 btcx_riscmem_free(pci, &buf->risc);
277 buf->vb.state = STATE_NEEDS_INIT;
278 }
279
280 /* ------------------------------------------------------------------ */
281 /* our SRAM memory layout */
282
283 /* we are going to put all thr risc programs into host memory, so we
284 * can use the whole SDRAM for the DMA fifos. To simplify things, we
285 * use a static memory layout. That surely will waste memory in case
286 * we don't use all DMA channels at the same time (which will be the
287 * case most of the time). But that still gives us enougth FIFO space
288 * to be able to deal with insane long pci latencies ...
289 *
290 * FIFO space allocations:
291 * channel 21 (y video) - 10.0k
292 * channel 22 (u video) - 2.0k
293 * channel 23 (v video) - 2.0k
294 * channel 24 (vbi) - 4.0k
295 * channels 25+26 (audio) - 0.5k
296 * channel 28 (mpeg) - 4.0k
297 * TOTAL = 25.5k
298 *
299 * Every channel has 160 bytes control data (64 bytes instruction
300 * queue and 6 CDT entries), which is close to 2k total.
301 *
302 * Address layout:
303 * 0x0000 - 0x03ff CMDs / reserved
304 * 0x0400 - 0x0bff instruction queues + CDs
305 * 0x0c00 - FIFOs
306 */
307
308 struct sram_channel cx88_sram_channels[] = {
309 [SRAM_CH21] = {
310 .name = "video y / packed",
311 .cmds_start = 0x180040,
312 .ctrl_start = 0x180400,
313 .cdt = 0x180400 + 64,
314 .fifo_start = 0x180c00,
315 .fifo_size = 0x002800,
316 .ptr1_reg = MO_DMA21_PTR1,
317 .ptr2_reg = MO_DMA21_PTR2,
318 .cnt1_reg = MO_DMA21_CNT1,
319 .cnt2_reg = MO_DMA21_CNT2,
320 },
321 [SRAM_CH22] = {
322 .name = "video u",
323 .cmds_start = 0x180080,
324 .ctrl_start = 0x1804a0,
325 .cdt = 0x1804a0 + 64,
326 .fifo_start = 0x183400,
327 .fifo_size = 0x000800,
328 .ptr1_reg = MO_DMA22_PTR1,
329 .ptr2_reg = MO_DMA22_PTR2,
330 .cnt1_reg = MO_DMA22_CNT1,
331 .cnt2_reg = MO_DMA22_CNT2,
332 },
333 [SRAM_CH23] = {
334 .name = "video v",
335 .cmds_start = 0x1800c0,
336 .ctrl_start = 0x180540,
337 .cdt = 0x180540 + 64,
338 .fifo_start = 0x183c00,
339 .fifo_size = 0x000800,
340 .ptr1_reg = MO_DMA23_PTR1,
341 .ptr2_reg = MO_DMA23_PTR2,
342 .cnt1_reg = MO_DMA23_CNT1,
343 .cnt2_reg = MO_DMA23_CNT2,
344 },
345 [SRAM_CH24] = {
346 .name = "vbi",
347 .cmds_start = 0x180100,
348 .ctrl_start = 0x1805e0,
349 .cdt = 0x1805e0 + 64,
350 .fifo_start = 0x184400,
351 .fifo_size = 0x001000,
352 .ptr1_reg = MO_DMA24_PTR1,
353 .ptr2_reg = MO_DMA24_PTR2,
354 .cnt1_reg = MO_DMA24_CNT1,
355 .cnt2_reg = MO_DMA24_CNT2,
356 },
357 [SRAM_CH25] = {
358 .name = "audio from",
359 .cmds_start = 0x180140,
360 .ctrl_start = 0x180680,
361 .cdt = 0x180680 + 64,
362 .fifo_start = 0x185400,
363 .fifo_size = 0x000200,
364 .ptr1_reg = MO_DMA25_PTR1,
365 .ptr2_reg = MO_DMA25_PTR2,
366 .cnt1_reg = MO_DMA25_CNT1,
367 .cnt2_reg = MO_DMA25_CNT2,
368 },
369 [SRAM_CH26] = {
370 .name = "audio to",
371 .cmds_start = 0x180180,
372 .ctrl_start = 0x180720,
373 .cdt = 0x180680 + 64, /* same as audio IN */
374 .fifo_start = 0x185400, /* same as audio IN */
375 .fifo_size = 0x000200, /* same as audio IN */
376 .ptr1_reg = MO_DMA26_PTR1,
377 .ptr2_reg = MO_DMA26_PTR2,
378 .cnt1_reg = MO_DMA26_CNT1,
379 .cnt2_reg = MO_DMA26_CNT2,
380 },
381 [SRAM_CH28] = {
382 .name = "mpeg",
383 .cmds_start = 0x180200,
384 .ctrl_start = 0x1807C0,
385 .cdt = 0x1807C0 + 64,
386 .fifo_start = 0x185600,
387 .fifo_size = 0x001000,
388 .ptr1_reg = MO_DMA28_PTR1,
389 .ptr2_reg = MO_DMA28_PTR2,
390 .cnt1_reg = MO_DMA28_CNT1,
391 .cnt2_reg = MO_DMA28_CNT2,
392 },
393 };
394
395 int cx88_sram_channel_setup(struct cx88_core *core,
396 struct sram_channel *ch,
397 unsigned int bpl, u32 risc)
398 {
399 unsigned int i,lines;
400 u32 cdt;
401
402 bpl = (bpl + 7) & ~7; /* alignment */
403 cdt = ch->cdt;
404 lines = ch->fifo_size / bpl;
405 if (lines > 6)
406 lines = 6;
407 BUG_ON(lines < 2);
408
409 /* write CDT */
410 for (i = 0; i < lines; i++)
411 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
412
413 /* write CMDS */
414 cx_write(ch->cmds_start + 0, risc);
415 cx_write(ch->cmds_start + 4, cdt);
416 cx_write(ch->cmds_start + 8, (lines*16) >> 3);
417 cx_write(ch->cmds_start + 12, ch->ctrl_start);
418 cx_write(ch->cmds_start + 16, 64 >> 2);
419 for (i = 20; i < 64; i += 4)
420 cx_write(ch->cmds_start + i, 0);
421
422 /* fill registers */
423 cx_write(ch->ptr1_reg, ch->fifo_start);
424 cx_write(ch->ptr2_reg, cdt);
425 cx_write(ch->cnt1_reg, (bpl >> 3) -1);
426 cx_write(ch->cnt2_reg, (lines*16) >> 3);
427
428 dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
429 return 0;
430 }
431
432 /* ------------------------------------------------------------------ */
433 /* debug helper code */
434
435 int cx88_risc_decode(u32 risc)
436 {
437 static char *instr[16] = {
438 [ RISC_SYNC >> 28 ] = "sync",
439 [ RISC_WRITE >> 28 ] = "write",
440 [ RISC_WRITEC >> 28 ] = "writec",
441 [ RISC_READ >> 28 ] = "read",
442 [ RISC_READC >> 28 ] = "readc",
443 [ RISC_JUMP >> 28 ] = "jump",
444 [ RISC_SKIP >> 28 ] = "skip",
445 [ RISC_WRITERM >> 28 ] = "writerm",
446 [ RISC_WRITECM >> 28 ] = "writecm",
447 [ RISC_WRITECR >> 28 ] = "writecr",
448 };
449 static int incr[16] = {
450 [ RISC_WRITE >> 28 ] = 2,
451 [ RISC_JUMP >> 28 ] = 2,
452 [ RISC_WRITERM >> 28 ] = 3,
453 [ RISC_WRITECM >> 28 ] = 3,
454 [ RISC_WRITECR >> 28 ] = 4,
455 };
456 static char *bits[] = {
457 "12", "13", "14", "resync",
458 "cnt0", "cnt1", "18", "19",
459 "20", "21", "22", "23",
460 "irq1", "irq2", "eol", "sol",
461 };
462 int i;
463
464 printk("0x%08x [ %s", risc,
465 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
466 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
467 if (risc & (1 << (i + 12)))
468 printk(" %s",bits[i]);
469 printk(" count=%d ]\n", risc & 0xfff);
470 return incr[risc >> 28] ? incr[risc >> 28] : 1;
471 }
472
473 #if 0 /* currently unused, but useful for debugging */
474 void cx88_risc_disasm(struct cx88_core *core,
475 struct btcx_riscmem *risc)
476 {
477 unsigned int i,j,n;
478
479 printk("%s: risc disasm: %p [dma=0x%08lx]\n",
480 core->name, risc->cpu, (unsigned long)risc->dma);
481 for (i = 0; i < (risc->size >> 2); i += n) {
482 printk("%s: %04d: ", core->name, i);
483 n = cx88_risc_decode(risc->cpu[i]);
484 for (j = 1; j < n; j++)
485 printk("%s: %04d: 0x%08x [ arg #%d ]\n",
486 core->name, i+j, risc->cpu[i+j], j);
487 if (risc->cpu[i] == RISC_JUMP)
488 break;
489 }
490 }
491 #endif
492
493 void cx88_sram_channel_dump(struct cx88_core *core,
494 struct sram_channel *ch)
495 {
496 static char *name[] = {
497 "initial risc",
498 "cdt base",
499 "cdt size",
500 "iq base",
501 "iq size",
502 "risc pc",
503 "iq wr ptr",
504 "iq rd ptr",
505 "cdt current",
506 "pci target",
507 "line / byte",
508 };
509 u32 risc;
510 unsigned int i,j,n;
511
512 printk("%s: %s - dma channel status dump\n",
513 core->name,ch->name);
514 for (i = 0; i < ARRAY_SIZE(name); i++)
515 printk("%s: cmds: %-12s: 0x%08x\n",
516 core->name,name[i],
517 cx_read(ch->cmds_start + 4*i));
518 for (i = 0; i < 4; i++) {
519 risc = cx_read(ch->cmds_start + 4 * (i+11));
520 printk("%s: risc%d: ", core->name, i);
521 cx88_risc_decode(risc);
522 }
523 for (i = 0; i < 16; i += n) {
524 risc = cx_read(ch->ctrl_start + 4 * i);
525 printk("%s: iq %x: ", core->name, i);
526 n = cx88_risc_decode(risc);
527 for (j = 1; j < n; j++) {
528 risc = cx_read(ch->ctrl_start + 4 * (i+j));
529 printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
530 core->name, i+j, risc, j);
531 }
532 }
533
534 printk("%s: fifo: 0x%08x -> 0x%x\n",
535 core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
536 printk("%s: ctrl: 0x%08x -> 0x%x\n",
537 core->name, ch->ctrl_start, ch->ctrl_start+6*16);
538 printk("%s: ptr1_reg: 0x%08x\n",
539 core->name,cx_read(ch->ptr1_reg));
540 printk("%s: ptr2_reg: 0x%08x\n",
541 core->name,cx_read(ch->ptr2_reg));
542 printk("%s: cnt1_reg: 0x%08x\n",
543 core->name,cx_read(ch->cnt1_reg));
544 printk("%s: cnt2_reg: 0x%08x\n",
545 core->name,cx_read(ch->cnt2_reg));
546 }
547
548 static char *cx88_pci_irqs[32] = {
549 "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
550 "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
551 "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
552 "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
553 };
554 char *cx88_vid_irqs[32] = {
555 "y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
556 "y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
557 "y_oflow", "u_oflow", "v_oflow", "vbi_oflow",
558 "y_sync", "u_sync", "v_sync", "vbi_sync",
559 "opc_err", "par_err", "rip_err", "pci_abort",
560 };
561 char *cx88_mpeg_irqs[32] = {
562 "ts_risci1", NULL, NULL, NULL,
563 "ts_risci2", NULL, NULL, NULL,
564 "ts_oflow", NULL, NULL, NULL,
565 "ts_sync", NULL, NULL, NULL,
566 "opc_err", "par_err", "rip_err", "pci_abort",
567 "ts_err?",
568 };
569
570 void cx88_print_irqbits(char *name, char *tag, char **strings,
571 u32 bits, u32 mask)
572 {
573 unsigned int i;
574
575 printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
576 for (i = 0; i < 32; i++) {
577 if (!(bits & (1 << i)))
578 continue;
579 if (strings[i])
580 printk(" %s", strings[i]);
581 else
582 printk(" %d", i);
583 if (!(mask & (1 << i)))
584 continue;
585 printk("*");
586 }
587 printk("\n");
588 }
589
590 /* ------------------------------------------------------------------ */
591
592 int cx88_core_irq(struct cx88_core *core, u32 status)
593 {
594 int handled = 0;
595
596 if (status & (1<<18)) {
597 cx88_ir_irq(core);
598 handled++;
599 }
600 if (!handled)
601 cx88_print_irqbits(core->name, "irq pci",
602 cx88_pci_irqs, status,
603 core->pci_irqmask);
604 return handled;
605 }
606
607 void cx88_wakeup(struct cx88_core *core,
608 struct cx88_dmaqueue *q, u32 count)
609 {
610 struct cx88_buffer *buf;
611 int bc;
612
613 for (bc = 0;; bc++) {
614 if (list_empty(&q->active))
615 break;
616 buf = list_entry(q->active.next,
617 struct cx88_buffer, vb.queue);
618 #if 0
619 if (buf->count > count)
620 break;
621 #else
622 /* count comes from the hw and is is 16bit wide --
623 * this trick handles wrap-arounds correctly for
624 * up to 32767 buffers in flight... */
625 if ((s16) (count - buf->count) < 0)
626 break;
627 #endif
628 do_gettimeofday(&buf->vb.ts);
629 dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
630 count, buf->count);
631 buf->vb.state = STATE_DONE;
632 list_del(&buf->vb.queue);
633 wake_up(&buf->vb.done);
634 }
635 if (list_empty(&q->active)) {
636 del_timer(&q->timeout);
637 } else {
638 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
639 }
640 if (bc != 1)
641 printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
642 }
643
644 void cx88_shutdown(struct cx88_core *core)
645 {
646 /* disable RISC controller + IRQs */
647 cx_write(MO_DEV_CNTRL2, 0);
648
649 /* stop dma transfers */
650 cx_write(MO_VID_DMACNTRL, 0x0);
651 cx_write(MO_AUD_DMACNTRL, 0x0);
652 cx_write(MO_TS_DMACNTRL, 0x0);
653 cx_write(MO_VIP_DMACNTRL, 0x0);
654 cx_write(MO_GPHST_DMACNTRL, 0x0);
655
656 /* stop interrupts */
657 cx_write(MO_PCI_INTMSK, 0x0);
658 cx_write(MO_VID_INTMSK, 0x0);
659 cx_write(MO_AUD_INTMSK, 0x0);
660 cx_write(MO_TS_INTMSK, 0x0);
661 cx_write(MO_VIP_INTMSK, 0x0);
662 cx_write(MO_GPHST_INTMSK, 0x0);
663
664 /* stop capturing */
665 cx_write(VID_CAPTURE_CONTROL, 0);
666 }
667
668 int cx88_reset(struct cx88_core *core)
669 {
670 dprintk(1,"%s\n",__FUNCTION__);
671 cx88_shutdown(core);
672
673 /* clear irq status */
674 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
675 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
676 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
677
678 /* wait a bit */
679 msleep(100);
680
681 /* init sram */
682 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
683 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
684 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
685 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
686 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
687 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
688 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
689
690 /* misc init ... */
691 cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
692 (1 << 12) | // agc gain
693 (1 << 11) | // adaptibe agc
694 (0 << 10) | // chroma agc
695 (0 << 9) | // ckillen
696 (7)));
697
698 /* setup image format */
699 cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
700
701 /* setup FIFO Threshholds */
702 cx_write(MO_PDMA_STHRSH, 0x0807);
703 cx_write(MO_PDMA_DTHRSH, 0x0807);
704
705 /* fixes flashing of image */
706 cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
707 cx_write(MO_AGC_BACK_VBI, 0x00E00555);
708
709 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
710 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
711 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
712
713 /* Reset on-board parts */
714 cx_write(MO_SRST_IO, 0);
715 msleep(10);
716 cx_write(MO_SRST_IO, 1);
717
718 return 0;
719 }
720
721 /* ------------------------------------------------------------------ */
722
723 static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
724 {
725 return (norm->id & V4L2_STD_625_50) ? 922 : 754;
726 }
727
728 static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
729 {
730 return (norm->id & V4L2_STD_625_50) ? 186 : 135;
731 }
732
733 static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
734 {
735 return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18;
736 }
737
738 static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
739 {
740 static const unsigned int ntsc = 28636360;
741 static const unsigned int pal = 35468950;
742 static const unsigned int palm = 28604892;
743
744 if (norm->id & V4L2_STD_PAL_M)
745 return palm;
746
747 return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
748 }
749
750 static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
751 {
752 return (norm->id & V4L2_STD_625_50)
753 ? HLNotchFilter135PAL
754 : HLNotchFilter135NTSC;
755 }
756
757 static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
758 {
759 /* Should always be Line Draw Time / (4*FSC) */
760
761 if (norm->id & V4L2_STD_PAL_M)
762 return 909;
763
764 return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
765 }
766
767 static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
768 {
769 return (norm->id & V4L2_STD_625_50) ? 511 : 288;
770 }
771
772 int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
773 enum v4l2_field field)
774 {
775 unsigned int swidth = norm_swidth(core->tvnorm);
776 unsigned int sheight = norm_maxh(core->tvnorm);
777 u32 value;
778
779 dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
780 V4L2_FIELD_HAS_TOP(field) ? "T" : "",
781 V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
782 core->tvnorm->name);
783 if (!V4L2_FIELD_HAS_BOTH(field))
784 height *= 2;
785
786 // recalc H delay and scale registers
787 value = (width * norm_hdelay(core->tvnorm)) / swidth;
788 value &= 0x3fe;
789 cx_write(MO_HDELAY_EVEN, value);
790 cx_write(MO_HDELAY_ODD, value);
791 dprintk(1,"set_scale: hdelay 0x%04x\n", value);
792
793 value = (swidth * 4096 / width) - 4096;
794 cx_write(MO_HSCALE_EVEN, value);
795 cx_write(MO_HSCALE_ODD, value);
796 dprintk(1,"set_scale: hscale 0x%04x\n", value);
797
798 cx_write(MO_HACTIVE_EVEN, width);
799 cx_write(MO_HACTIVE_ODD, width);
800 dprintk(1,"set_scale: hactive 0x%04x\n", width);
801
802 // recalc V scale Register (delay is constant)
803 cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
804 cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
805 dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
806
807 value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
808 cx_write(MO_VSCALE_EVEN, value);
809 cx_write(MO_VSCALE_ODD, value);
810 dprintk(1,"set_scale: vscale 0x%04x\n", value);
811
812 cx_write(MO_VACTIVE_EVEN, sheight);
813 cx_write(MO_VACTIVE_ODD, sheight);
814 dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
815
816 // setup filters
817 value = 0;
818 value |= (1 << 19); // CFILT (default)
819 if (core->tvnorm->id & V4L2_STD_SECAM) {
820 value |= (1 << 15);
821 value |= (1 << 16);
822 }
823 if (INPUT(core->input)->type == CX88_VMUX_SVIDEO)
824 value |= (1 << 13) | (1 << 5);
825 if (V4L2_FIELD_INTERLACED == field)
826 value |= (1 << 3); // VINT (interlaced vertical scaling)
827 if (width < 385)
828 value |= (1 << 0); // 3-tap interpolation
829 if (width < 193)
830 value |= (1 << 1); // 5-tap interpolation
831 if (nocomb)
832 value |= (3 << 5); // disable comb filter
833
834 cx_write(MO_FILTER_EVEN, value);
835 cx_write(MO_FILTER_ODD, value);
836 dprintk(1,"set_scale: filter 0x%04x\n", value);
837
838 return 0;
839 }
840
841 static const u32 xtal = 28636363;
842
843 static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
844 {
845 static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
846 u64 pll;
847 u32 reg;
848 int i;
849
850 if (prescale < 2)
851 prescale = 2;
852 if (prescale > 5)
853 prescale = 5;
854
855 pll = ofreq * 8 * prescale * (u64)(1 << 20);
856 do_div(pll,xtal);
857 reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
858 if (((reg >> 20) & 0x3f) < 14) {
859 printk("%s/0: pll out of range\n",core->name);
860 return -1;
861 }
862
863 dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
864 reg, cx_read(MO_PLL_REG), ofreq);
865 cx_write(MO_PLL_REG, reg);
866 for (i = 0; i < 100; i++) {
867 reg = cx_read(MO_DEVICE_STATUS);
868 if (reg & (1<<2)) {
869 dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
870 prescale,ofreq);
871 return 0;
872 }
873 dprintk(1,"pll not locked yet, waiting ...\n");
874 msleep(10);
875 }
876 dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
877 return -1;
878 }
879
880 static int set_tvaudio(struct cx88_core *core)
881 {
882 struct cx88_tvnorm *norm = core->tvnorm;
883
884 if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
885 return 0;
886
887 if (V4L2_STD_PAL_BG & norm->id) {
888 core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_BG;
889
890 } else if (V4L2_STD_PAL_DK & norm->id) {
891 core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_DK;
892
893 } else if (V4L2_STD_PAL_I & norm->id) {
894 core->tvaudio = WW_NICAM_I;
895
896 } else if (V4L2_STD_SECAM_L & norm->id) {
897 core->tvaudio = WW_SYSTEM_L_AM;
898
899 } else if (V4L2_STD_SECAM_DK & norm->id) {
900 core->tvaudio = WW_A2_DK;
901
902 } else if ((V4L2_STD_NTSC_M & norm->id) ||
903 (V4L2_STD_PAL_M & norm->id)) {
904 core->tvaudio = WW_BTSC;
905
906 } else if (V4L2_STD_NTSC_M_JP & norm->id) {
907 core->tvaudio = WW_EIAJ;
908
909 } else {
910 printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
911 core->name, norm->name);
912 core->tvaudio = 0;
913 return 0;
914 }
915
916 cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
917 cx88_set_tvaudio(core);
918 // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
919
920 cx_write(MO_AUDD_LNGTH, 128); /* fifo size */
921 cx_write(MO_AUDR_LNGTH, 128); /* fifo size */
922 cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */
923 return 0;
924 }
925
926 int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
927 {
928 u32 fsc8;
929 u32 adc_clock;
930 u32 vdec_clock;
931 u32 step_db,step_dr;
932 u64 tmp64;
933 u32 bdelay,agcdelay,htotal;
934
935 core->tvnorm = norm;
936 fsc8 = norm_fsc8(norm);
937 adc_clock = xtal;
938 vdec_clock = fsc8;
939 step_db = fsc8;
940 step_dr = fsc8;
941
942 if (norm->id & V4L2_STD_SECAM) {
943 step_db = 4250000 * 8;
944 step_dr = 4406250 * 8;
945 }
946
947 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
948 norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr);
949 set_pll(core,2,vdec_clock);
950
951 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
952 norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
953 cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat);
954
955 #if 1
956 // FIXME: as-is from DScaler
957 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
958 norm->cxoformat, cx_read(MO_OUTPUT_FORMAT));
959 cx_write(MO_OUTPUT_FORMAT, norm->cxoformat);
960 #endif
961
962 // MO_SCONV_REG = adc clock / video dec clock * 2^17
963 tmp64 = adc_clock * (u64)(1 << 17);
964 do_div(tmp64, vdec_clock);
965 dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
966 (u32)tmp64, cx_read(MO_SCONV_REG));
967 cx_write(MO_SCONV_REG, (u32)tmp64);
968
969 // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
970 tmp64 = step_db * (u64)(1 << 22);
971 do_div(tmp64, vdec_clock);
972 dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
973 (u32)tmp64, cx_read(MO_SUB_STEP));
974 cx_write(MO_SUB_STEP, (u32)tmp64);
975
976 // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
977 tmp64 = step_dr * (u64)(1 << 22);
978 do_div(tmp64, vdec_clock);
979 dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
980 (u32)tmp64, cx_read(MO_SUB_STEP_DR));
981 cx_write(MO_SUB_STEP_DR, (u32)tmp64);
982
983 // bdelay + agcdelay
984 bdelay = vdec_clock * 65 / 20000000 + 21;
985 agcdelay = vdec_clock * 68 / 20000000 + 15;
986 dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
987 (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
988 cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
989
990 // htotal
991 tmp64 = norm_htotal(norm) * (u64)vdec_clock;
992 do_div(tmp64, fsc8);
993 htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11);
994 dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
995 htotal, cx_read(MO_HTOTAL), (u32)tmp64);
996 cx_write(MO_HTOTAL, htotal);
997
998 // vbi stuff
999 cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */
1000 norm_vbipack(norm)));
1001
1002 // this is needed as well to set all tvnorm parameter
1003 cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
1004
1005 // audio
1006 set_tvaudio(core);
1007
1008 // tell i2c chips
1009 #ifdef V4L2_I2C_CLIENTS
1010 cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);
1011 #else
1012 {
1013 struct video_channel c;
1014 memset(&c,0,sizeof(c));
1015 c.channel = core->input;
1016 c.norm = VIDEO_MODE_PAL;
1017 if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP)))
1018 c.norm = VIDEO_MODE_NTSC;
1019 if (norm->id & V4L2_STD_SECAM)
1020 c.norm = VIDEO_MODE_SECAM;
1021 cx88_call_i2c_clients(core,VIDIOCSCHAN,&c);
1022 }
1023 #endif
1024
1025 // done
1026 return 0;
1027 }
1028
1029 /* ------------------------------------------------------------------ */
1030
1031 static int cx88_pci_quirks(char *name, struct pci_dev *pci)
1032 {
1033 unsigned int lat = UNSET;
1034 u8 ctrl = 0;
1035 u8 value;
1036
1037 /* check pci quirks */
1038 if (pci_pci_problems & PCIPCI_TRITON) {
1039 printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
1040 name);
1041 ctrl |= CX88X_EN_TBFX;
1042 }
1043 if (pci_pci_problems & PCIPCI_NATOMA) {
1044 printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
1045 name);
1046 ctrl |= CX88X_EN_TBFX;
1047 }
1048 if (pci_pci_problems & PCIPCI_VIAETBF) {
1049 printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
1050 name);
1051 ctrl |= CX88X_EN_TBFX;
1052 }
1053 if (pci_pci_problems & PCIPCI_VSFX) {
1054 printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
1055 name);
1056 ctrl |= CX88X_EN_VSFX;
1057 }
1058 #ifdef PCIPCI_ALIMAGIK
1059 if (pci_pci_problems & PCIPCI_ALIMAGIK) {
1060 printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
1061 name);
1062 lat = 0x0A;
1063 }
1064 #endif
1065
1066 /* check insmod options */
1067 if (UNSET != latency)
1068 lat = latency;
1069
1070 /* apply stuff */
1071 if (ctrl) {
1072 pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
1073 value |= ctrl;
1074 pci_write_config_byte(pci, CX88X_DEVCTRL, value);
1075 }
1076 if (UNSET != lat) {
1077 printk(KERN_INFO "%s: setting pci latency timer to %d\n",
1078 name, latency);
1079 pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
1080 }
1081 return 0;
1082 }
1083
1084 /* ------------------------------------------------------------------ */
1085
1086 struct video_device *cx88_vdev_init(struct cx88_core *core,
1087 struct pci_dev *pci,
1088 struct video_device *template,
1089 char *type)
1090 {
1091 struct video_device *vfd;
1092
1093 vfd = video_device_alloc();
1094 if (NULL == vfd)
1095 return NULL;
1096 *vfd = *template;
1097 vfd->minor = -1;
1098 vfd->dev = &pci->dev;
1099 vfd->release = video_device_release;
1100 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1101 core->name, type, cx88_boards[core->board].name);
1102 return vfd;
1103 }
1104
1105 static int get_ressources(struct cx88_core *core, struct pci_dev *pci)
1106 {
1107 if (request_mem_region(pci_resource_start(pci,0),
1108 pci_resource_len(pci,0),
1109 core->name))
1110 return 0;
1111 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",
1112 core->name,pci_resource_start(pci,0));
1113 return -EBUSY;
1114 }
1115
1116 struct cx88_core* cx88_core_get(struct pci_dev *pci)
1117 {
1118 struct cx88_core *core;
1119 struct list_head *item;
1120 int i;
1121
1122 down(&devlist);
1123 list_for_each(item,&cx88_devlist) {
1124 core = list_entry(item, struct cx88_core, devlist);
1125 if (pci->bus->number != core->pci_bus)
1126 continue;
1127 if (PCI_SLOT(pci->devfn) != core->pci_slot)
1128 continue;
1129
1130 if (0 != get_ressources(core,pci))
1131 goto fail_unlock;
1132 atomic_inc(&core->refcount);
1133 up(&devlist);
1134 return core;
1135 }
1136 core = kmalloc(sizeof(*core),GFP_KERNEL);
1137 if (NULL == core)
1138 goto fail_unlock;
1139
1140 memset(core,0,sizeof(*core));
1141 atomic_inc(&core->refcount);
1142 core->pci_bus = pci->bus->number;
1143 core->pci_slot = PCI_SLOT(pci->devfn);
1144 core->pci_irqmask = 0x00fc00;
1145
1146 core->nr = cx88_devcount++;
1147 sprintf(core->name,"cx88[%d]",core->nr);
1148 if (0 != get_ressources(core,pci)) {
1149 cx88_devcount--;
1150 goto fail_free;
1151 }
1152 list_add_tail(&core->devlist,&cx88_devlist);
1153
1154 /* PCI stuff */
1155 cx88_pci_quirks(core->name, pci);
1156 core->lmmio = ioremap(pci_resource_start(pci,0),
1157 pci_resource_len(pci,0));
1158 core->bmmio = (u8 __iomem *)core->lmmio;
1159
1160 /* board config */
1161 core->board = UNSET;
1162 if (card[core->nr] < cx88_bcount)
1163 core->board = card[core->nr];
1164 for (i = 0; UNSET == core->board && i < cx88_idcount; i++)
1165 if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
1166 pci->subsystem_device == cx88_subids[i].subdevice)
1167 core->board = cx88_subids[i].card;
1168 if (UNSET == core->board) {
1169 core->board = CX88_BOARD_UNKNOWN;
1170 cx88_card_list(core,pci);
1171 }
1172 printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
1173 core->name,pci->subsystem_vendor,
1174 pci->subsystem_device,cx88_boards[core->board].name,
1175 core->board, card[core->nr] == core->board ?
1176 "insmod option" : "autodetected");
1177
1178 core->tuner_type = tuner[core->nr];
1179 core->radio_type = radio[core->nr];
1180 if (UNSET == core->tuner_type)
1181 core->tuner_type = cx88_boards[core->board].tuner_type;
1182 if (UNSET == core->radio_type)
1183 core->radio_type = cx88_boards[core->board].radio_type;
1184 if (!core->tuner_addr)
1185 core->tuner_addr = cx88_boards[core->board].tuner_addr;
1186 if (!core->radio_addr)
1187 core->radio_addr = cx88_boards[core->board].radio_addr;
1188
1189 printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
1190 core->tuner_type, core->tuner_addr<<1,
1191 core->radio_type, core->radio_addr<<1);
1192
1193 core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
1194
1195 /* init hardware */
1196 cx88_reset(core);
1197 cx88_i2c_init(core,pci);
1198 cx88_card_setup(core);
1199 cx88_ir_init(core,pci);
1200
1201 up(&devlist);
1202 return core;
1203
1204 fail_free:
1205 kfree(core);
1206 fail_unlock:
1207 up(&devlist);
1208 return NULL;
1209 }
1210
1211 void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1212 {
1213 release_mem_region(pci_resource_start(pci,0),
1214 pci_resource_len(pci,0));
1215
1216 if (!atomic_dec_and_test(&core->refcount))
1217 return;
1218
1219 down(&devlist);
1220 cx88_ir_fini(core);
1221 if (0 == core->i2c_rc)
1222 i2c_bit_del_bus(&core->i2c_adap);
1223 list_del(&core->devlist);
1224 iounmap(core->lmmio);
1225 cx88_devcount--;
1226 up(&devlist);
1227 kfree(core);
1228 }
1229
1230 /* ------------------------------------------------------------------ */
1231
1232 EXPORT_SYMBOL(cx88_print_ioctl);
1233 EXPORT_SYMBOL(cx88_vid_irqs);
1234 EXPORT_SYMBOL(cx88_mpeg_irqs);
1235 EXPORT_SYMBOL(cx88_print_irqbits);
1236
1237 EXPORT_SYMBOL(cx88_core_irq);
1238 EXPORT_SYMBOL(cx88_wakeup);
1239 EXPORT_SYMBOL(cx88_reset);
1240 EXPORT_SYMBOL(cx88_shutdown);
1241
1242 EXPORT_SYMBOL(cx88_risc_buffer);
1243 EXPORT_SYMBOL(cx88_risc_databuffer);
1244 EXPORT_SYMBOL(cx88_risc_stopper);
1245 EXPORT_SYMBOL(cx88_free_buffer);
1246
1247 EXPORT_SYMBOL(cx88_sram_channels);
1248 EXPORT_SYMBOL(cx88_sram_channel_setup);
1249 EXPORT_SYMBOL(cx88_sram_channel_dump);
1250
1251 EXPORT_SYMBOL(cx88_set_tvnorm);
1252 EXPORT_SYMBOL(cx88_set_scale);
1253
1254 EXPORT_SYMBOL(cx88_vdev_init);
1255 EXPORT_SYMBOL(cx88_core_get);
1256 EXPORT_SYMBOL(cx88_core_put);
1257
1258 /*
1259 * Local variables:
1260 * c-basic-offset: 8
1261 * End:
1262 */
This page took 0.090655 seconds and 6 git commands to generate.