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