V4L/DVB (4213): Cx88: cleanups
[linux-2.6/sactl.git] / drivers / media / video / cx88 / cx88-core.c
blob26f4c0fb8c36cab989a9f2ab7a8269f9e6f6f11c
1 /*
3 * device driver for Conexant 2388x based TV cards
4 * driver core
6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <linux/init.h>
24 #include <linux/list.h>
25 #include <linux/module.h>
26 #include <linux/moduleparam.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/videodev2.h>
35 #include <linux/mutex.h>
37 #include "cx88.h"
38 #include <media/v4l2-common.h>
40 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
41 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
42 MODULE_LICENSE("GPL");
44 /* ------------------------------------------------------------------ */
46 static unsigned int core_debug = 0;
47 module_param(core_debug,int,0644);
48 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
50 static unsigned int latency = UNSET;
51 module_param(latency,int,0444);
52 MODULE_PARM_DESC(latency,"pci latency timer");
54 static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
55 static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
56 static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
58 module_param_array(tuner, int, NULL, 0444);
59 module_param_array(radio, int, NULL, 0444);
60 module_param_array(card, int, NULL, 0444);
62 MODULE_PARM_DESC(tuner,"tuner type");
63 MODULE_PARM_DESC(radio,"radio tuner type");
64 MODULE_PARM_DESC(card,"card type");
66 static unsigned int nicam = 0;
67 module_param(nicam,int,0644);
68 MODULE_PARM_DESC(nicam,"tv audio is nicam");
70 static unsigned int nocomb = 0;
71 module_param(nocomb,int,0644);
72 MODULE_PARM_DESC(nocomb,"disable comb filter");
74 #define dprintk(level,fmt, arg...) if (core_debug >= level) \
75 printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
77 static unsigned int cx88_devcount;
78 static LIST_HEAD(cx88_devlist);
79 static DEFINE_MUTEX(devlist);
81 #define NO_SYNC_LINE (-1U)
83 static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
84 unsigned int offset, u32 sync_line,
85 unsigned int bpl, unsigned int padding,
86 unsigned int lines)
88 struct scatterlist *sg;
89 unsigned int line,todo;
91 /* sync instruction */
92 if (sync_line != NO_SYNC_LINE)
93 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
95 /* scan lines */
96 sg = sglist;
97 for (line = 0; line < lines; line++) {
98 while (offset && offset >= sg_dma_len(sg)) {
99 offset -= sg_dma_len(sg);
100 sg++;
102 if (bpl <= sg_dma_len(sg)-offset) {
103 /* fits into current chunk */
104 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
105 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
106 offset+=bpl;
107 } else {
108 /* scanline needs to be splitted */
109 todo = bpl;
110 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
111 (sg_dma_len(sg)-offset));
112 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
113 todo -= (sg_dma_len(sg)-offset);
114 offset = 0;
115 sg++;
116 while (todo > sg_dma_len(sg)) {
117 *(rp++)=cpu_to_le32(RISC_WRITE|
118 sg_dma_len(sg));
119 *(rp++)=cpu_to_le32(sg_dma_address(sg));
120 todo -= sg_dma_len(sg);
121 sg++;
123 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
124 *(rp++)=cpu_to_le32(sg_dma_address(sg));
125 offset += todo;
127 offset += padding;
130 return rp;
133 int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
134 struct scatterlist *sglist,
135 unsigned int top_offset, unsigned int bottom_offset,
136 unsigned int bpl, unsigned int padding, unsigned int lines)
138 u32 instructions,fields;
139 u32 *rp;
140 int rc;
142 fields = 0;
143 if (UNSET != top_offset)
144 fields++;
145 if (UNSET != bottom_offset)
146 fields++;
148 /* estimate risc mem: worst case is one write per page border +
149 one write per scan line + syncs + jump (all 2 dwords). Padding
150 can cause next bpl to start close to a page border. First DMA
151 region may be smaller than PAGE_SIZE */
152 instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
153 instructions += 2;
154 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
155 return rc;
157 /* write risc instructions */
158 rp = risc->cpu;
159 if (UNSET != top_offset)
160 rp = cx88_risc_field(rp, sglist, top_offset, 0,
161 bpl, padding, lines);
162 if (UNSET != bottom_offset)
163 rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
164 bpl, padding, lines);
166 /* save pointer to jmp instruction address */
167 risc->jmp = rp;
168 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
169 return 0;
172 int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
173 struct scatterlist *sglist, unsigned int bpl,
174 unsigned int lines)
176 u32 instructions;
177 u32 *rp;
178 int rc;
180 /* estimate risc mem: worst case is one write per page border +
181 one write per scan line + syncs + jump (all 2 dwords). Here
182 there is no padding and no sync. First DMA region may be smaller
183 than PAGE_SIZE */
184 instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
185 instructions += 1;
186 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
187 return rc;
189 /* write risc instructions */
190 rp = risc->cpu;
191 rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
193 /* save pointer to jmp instruction address */
194 risc->jmp = rp;
195 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
196 return 0;
199 int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
200 u32 reg, u32 mask, u32 value)
202 u32 *rp;
203 int rc;
205 if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
206 return rc;
208 /* write risc instructions */
209 rp = risc->cpu;
210 *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
211 *(rp++) = cpu_to_le32(reg);
212 *(rp++) = cpu_to_le32(value);
213 *(rp++) = cpu_to_le32(mask);
214 *(rp++) = cpu_to_le32(RISC_JUMP);
215 *(rp++) = cpu_to_le32(risc->dma);
216 return 0;
219 void
220 cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
222 BUG_ON(in_interrupt());
223 videobuf_waiton(&buf->vb,0,0);
224 videobuf_dma_unmap(q, &buf->vb.dma);
225 videobuf_dma_free(&buf->vb.dma);
226 btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
227 buf->vb.state = STATE_NEEDS_INIT;
230 /* ------------------------------------------------------------------ */
231 /* our SRAM memory layout */
233 /* we are going to put all thr risc programs into host memory, so we
234 * can use the whole SDRAM for the DMA fifos. To simplify things, we
235 * use a static memory layout. That surely will waste memory in case
236 * we don't use all DMA channels at the same time (which will be the
237 * case most of the time). But that still gives us enougth FIFO space
238 * to be able to deal with insane long pci latencies ...
240 * FIFO space allocations:
241 * channel 21 (y video) - 10.0k
242 * channel 22 (u video) - 2.0k
243 * channel 23 (v video) - 2.0k
244 * channel 24 (vbi) - 4.0k
245 * channels 25+26 (audio) - 4.0k
246 * channel 28 (mpeg) - 4.0k
247 * TOTAL = 29.0k
249 * Every channel has 160 bytes control data (64 bytes instruction
250 * queue and 6 CDT entries), which is close to 2k total.
252 * Address layout:
253 * 0x0000 - 0x03ff CMDs / reserved
254 * 0x0400 - 0x0bff instruction queues + CDs
255 * 0x0c00 - FIFOs
258 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,
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,
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,
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,
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,
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,
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,
345 int cx88_sram_channel_setup(struct cx88_core *core,
346 struct sram_channel *ch,
347 unsigned int bpl, u32 risc)
349 unsigned int i,lines;
350 u32 cdt;
352 bpl = (bpl + 7) & ~7; /* alignment */
353 cdt = ch->cdt;
354 lines = ch->fifo_size / bpl;
355 if (lines > 6)
356 lines = 6;
357 BUG_ON(lines < 2);
359 /* write CDT */
360 for (i = 0; i < lines; i++)
361 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
363 /* write CMDS */
364 cx_write(ch->cmds_start + 0, risc);
365 cx_write(ch->cmds_start + 4, cdt);
366 cx_write(ch->cmds_start + 8, (lines*16) >> 3);
367 cx_write(ch->cmds_start + 12, ch->ctrl_start);
368 cx_write(ch->cmds_start + 16, 64 >> 2);
369 for (i = 20; i < 64; i += 4)
370 cx_write(ch->cmds_start + i, 0);
372 /* fill registers */
373 cx_write(ch->ptr1_reg, ch->fifo_start);
374 cx_write(ch->ptr2_reg, cdt);
375 cx_write(ch->cnt1_reg, (bpl >> 3) -1);
376 cx_write(ch->cnt2_reg, (lines*16) >> 3);
378 dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
379 return 0;
382 /* ------------------------------------------------------------------ */
383 /* debug helper code */
385 static int cx88_risc_decode(u32 risc)
387 static char *instr[16] = {
388 [ RISC_SYNC >> 28 ] = "sync",
389 [ RISC_WRITE >> 28 ] = "write",
390 [ RISC_WRITEC >> 28 ] = "writec",
391 [ RISC_READ >> 28 ] = "read",
392 [ RISC_READC >> 28 ] = "readc",
393 [ RISC_JUMP >> 28 ] = "jump",
394 [ RISC_SKIP >> 28 ] = "skip",
395 [ RISC_WRITERM >> 28 ] = "writerm",
396 [ RISC_WRITECM >> 28 ] = "writecm",
397 [ RISC_WRITECR >> 28 ] = "writecr",
399 static int incr[16] = {
400 [ RISC_WRITE >> 28 ] = 2,
401 [ RISC_JUMP >> 28 ] = 2,
402 [ RISC_WRITERM >> 28 ] = 3,
403 [ RISC_WRITECM >> 28 ] = 3,
404 [ RISC_WRITECR >> 28 ] = 4,
406 static char *bits[] = {
407 "12", "13", "14", "resync",
408 "cnt0", "cnt1", "18", "19",
409 "20", "21", "22", "23",
410 "irq1", "irq2", "eol", "sol",
412 int i;
414 printk("0x%08x [ %s", risc,
415 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
416 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
417 if (risc & (1 << (i + 12)))
418 printk(" %s",bits[i]);
419 printk(" count=%d ]\n", risc & 0xfff);
420 return incr[risc >> 28] ? incr[risc >> 28] : 1;
424 void cx88_sram_channel_dump(struct cx88_core *core,
425 struct sram_channel *ch)
427 static char *name[] = {
428 "initial risc",
429 "cdt base",
430 "cdt size",
431 "iq base",
432 "iq size",
433 "risc pc",
434 "iq wr ptr",
435 "iq rd ptr",
436 "cdt current",
437 "pci target",
438 "line / byte",
440 u32 risc;
441 unsigned int i,j,n;
443 printk("%s: %s - dma channel status dump\n",
444 core->name,ch->name);
445 for (i = 0; i < ARRAY_SIZE(name); i++)
446 printk("%s: cmds: %-12s: 0x%08x\n",
447 core->name,name[i],
448 cx_read(ch->cmds_start + 4*i));
449 for (i = 0; i < 4; i++) {
450 risc = cx_read(ch->cmds_start + 4 * (i+11));
451 printk("%s: risc%d: ", core->name, i);
452 cx88_risc_decode(risc);
454 for (i = 0; i < 16; i += n) {
455 risc = cx_read(ch->ctrl_start + 4 * i);
456 printk("%s: iq %x: ", core->name, i);
457 n = cx88_risc_decode(risc);
458 for (j = 1; j < n; j++) {
459 risc = cx_read(ch->ctrl_start + 4 * (i+j));
460 printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
461 core->name, i+j, risc, j);
465 printk("%s: fifo: 0x%08x -> 0x%x\n",
466 core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
467 printk("%s: ctrl: 0x%08x -> 0x%x\n",
468 core->name, ch->ctrl_start, ch->ctrl_start+6*16);
469 printk("%s: ptr1_reg: 0x%08x\n",
470 core->name,cx_read(ch->ptr1_reg));
471 printk("%s: ptr2_reg: 0x%08x\n",
472 core->name,cx_read(ch->ptr2_reg));
473 printk("%s: cnt1_reg: 0x%08x\n",
474 core->name,cx_read(ch->cnt1_reg));
475 printk("%s: cnt2_reg: 0x%08x\n",
476 core->name,cx_read(ch->cnt2_reg));
479 static char *cx88_pci_irqs[32] = {
480 "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
481 "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
482 "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
483 "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
486 void cx88_print_irqbits(char *name, char *tag, char **strings,
487 u32 bits, u32 mask)
489 unsigned int i;
491 printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
492 for (i = 0; i < 32; i++) {
493 if (!(bits & (1 << i)))
494 continue;
495 if (strings[i])
496 printk(" %s", strings[i]);
497 else
498 printk(" %d", i);
499 if (!(mask & (1 << i)))
500 continue;
501 printk("*");
503 printk("\n");
506 /* ------------------------------------------------------------------ */
508 int cx88_core_irq(struct cx88_core *core, u32 status)
510 int handled = 0;
512 if (status & (1<<18)) {
513 cx88_ir_irq(core);
514 handled++;
516 if (!handled)
517 cx88_print_irqbits(core->name, "irq pci",
518 cx88_pci_irqs, status,
519 core->pci_irqmask);
520 return handled;
523 void cx88_wakeup(struct cx88_core *core,
524 struct cx88_dmaqueue *q, u32 count)
526 struct cx88_buffer *buf;
527 int bc;
529 for (bc = 0;; bc++) {
530 if (list_empty(&q->active))
531 break;
532 buf = list_entry(q->active.next,
533 struct cx88_buffer, vb.queue);
534 /* count comes from the hw and is is 16bit wide --
535 * this trick handles wrap-arounds correctly for
536 * up to 32767 buffers in flight... */
537 if ((s16) (count - buf->count) < 0)
538 break;
539 do_gettimeofday(&buf->vb.ts);
540 dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
541 count, buf->count);
542 buf->vb.state = STATE_DONE;
543 list_del(&buf->vb.queue);
544 wake_up(&buf->vb.done);
546 if (list_empty(&q->active)) {
547 del_timer(&q->timeout);
548 } else {
549 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
551 if (bc != 1)
552 printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
555 void cx88_shutdown(struct cx88_core *core)
557 /* disable RISC controller + IRQs */
558 cx_write(MO_DEV_CNTRL2, 0);
560 /* stop dma transfers */
561 cx_write(MO_VID_DMACNTRL, 0x0);
562 cx_write(MO_AUD_DMACNTRL, 0x0);
563 cx_write(MO_TS_DMACNTRL, 0x0);
564 cx_write(MO_VIP_DMACNTRL, 0x0);
565 cx_write(MO_GPHST_DMACNTRL, 0x0);
567 /* stop interrupts */
568 cx_write(MO_PCI_INTMSK, 0x0);
569 cx_write(MO_VID_INTMSK, 0x0);
570 cx_write(MO_AUD_INTMSK, 0x0);
571 cx_write(MO_TS_INTMSK, 0x0);
572 cx_write(MO_VIP_INTMSK, 0x0);
573 cx_write(MO_GPHST_INTMSK, 0x0);
575 /* stop capturing */
576 cx_write(VID_CAPTURE_CONTROL, 0);
579 int cx88_reset(struct cx88_core *core)
581 dprintk(1,"%s\n",__FUNCTION__);
582 cx88_shutdown(core);
584 /* clear irq status */
585 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
586 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
587 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
589 /* wait a bit */
590 msleep(100);
592 /* init sram */
593 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
594 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
595 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
596 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
597 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
598 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
599 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
601 /* misc init ... */
602 cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
603 (1 << 12) | // agc gain
604 (1 << 11) | // adaptibe agc
605 (0 << 10) | // chroma agc
606 (0 << 9) | // ckillen
607 (7)));
609 /* setup image format */
610 cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
612 /* setup FIFO Threshholds */
613 cx_write(MO_PDMA_STHRSH, 0x0807);
614 cx_write(MO_PDMA_DTHRSH, 0x0807);
616 /* fixes flashing of image */
617 cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
618 cx_write(MO_AGC_BACK_VBI, 0x00E00555);
620 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
621 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
622 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
624 /* Reset on-board parts */
625 cx_write(MO_SRST_IO, 0);
626 msleep(10);
627 cx_write(MO_SRST_IO, 1);
629 return 0;
632 /* ------------------------------------------------------------------ */
634 static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
636 return (norm->id & V4L2_STD_625_50) ? 922 : 754;
639 static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
641 return (norm->id & V4L2_STD_625_50) ? 186 : 135;
644 static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
646 return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18;
649 static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
651 static const unsigned int ntsc = 28636360;
652 static const unsigned int pal = 35468950;
653 static const unsigned int palm = 28604892;
655 if (norm->id & V4L2_STD_PAL_M)
656 return palm;
658 return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
661 static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
663 return (norm->id & V4L2_STD_625_50)
664 ? HLNotchFilter135PAL
665 : HLNotchFilter135NTSC;
668 static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
670 /* Should always be Line Draw Time / (4*FSC) */
672 if (norm->id & V4L2_STD_PAL_M)
673 return 909;
675 return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
678 static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
680 return (norm->id & V4L2_STD_625_50) ? 511 : 400;
683 int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
684 enum v4l2_field field)
686 unsigned int swidth = norm_swidth(core->tvnorm);
687 unsigned int sheight = norm_maxh(core->tvnorm);
688 u32 value;
690 dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
691 V4L2_FIELD_HAS_TOP(field) ? "T" : "",
692 V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
693 core->tvnorm->name);
694 if (!V4L2_FIELD_HAS_BOTH(field))
695 height *= 2;
697 // recalc H delay and scale registers
698 value = (width * norm_hdelay(core->tvnorm)) / swidth;
699 value &= 0x3fe;
700 cx_write(MO_HDELAY_EVEN, value);
701 cx_write(MO_HDELAY_ODD, value);
702 dprintk(1,"set_scale: hdelay 0x%04x\n", value);
704 value = (swidth * 4096 / width) - 4096;
705 cx_write(MO_HSCALE_EVEN, value);
706 cx_write(MO_HSCALE_ODD, value);
707 dprintk(1,"set_scale: hscale 0x%04x\n", value);
709 cx_write(MO_HACTIVE_EVEN, width);
710 cx_write(MO_HACTIVE_ODD, width);
711 dprintk(1,"set_scale: hactive 0x%04x\n", width);
713 // recalc V scale Register (delay is constant)
714 cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
715 cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
716 dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
718 value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
719 cx_write(MO_VSCALE_EVEN, value);
720 cx_write(MO_VSCALE_ODD, value);
721 dprintk(1,"set_scale: vscale 0x%04x\n", value);
723 cx_write(MO_VACTIVE_EVEN, sheight);
724 cx_write(MO_VACTIVE_ODD, sheight);
725 dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
727 // setup filters
728 value = 0;
729 value |= (1 << 19); // CFILT (default)
730 if (core->tvnorm->id & V4L2_STD_SECAM) {
731 value |= (1 << 15);
732 value |= (1 << 16);
734 if (INPUT(core->input)->type == CX88_VMUX_SVIDEO)
735 value |= (1 << 13) | (1 << 5);
736 if (V4L2_FIELD_INTERLACED == field)
737 value |= (1 << 3); // VINT (interlaced vertical scaling)
738 if (width < 385)
739 value |= (1 << 0); // 3-tap interpolation
740 if (width < 193)
741 value |= (1 << 1); // 5-tap interpolation
742 if (nocomb)
743 value |= (3 << 5); // disable comb filter
745 cx_write(MO_FILTER_EVEN, value);
746 cx_write(MO_FILTER_ODD, value);
747 dprintk(1,"set_scale: filter 0x%04x\n", value);
749 return 0;
752 static const u32 xtal = 28636363;
754 static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
756 static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
757 u64 pll;
758 u32 reg;
759 int i;
761 if (prescale < 2)
762 prescale = 2;
763 if (prescale > 5)
764 prescale = 5;
766 pll = ofreq * 8 * prescale * (u64)(1 << 20);
767 do_div(pll,xtal);
768 reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
769 if (((reg >> 20) & 0x3f) < 14) {
770 printk("%s/0: pll out of range\n",core->name);
771 return -1;
774 dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
775 reg, cx_read(MO_PLL_REG), ofreq);
776 cx_write(MO_PLL_REG, reg);
777 for (i = 0; i < 100; i++) {
778 reg = cx_read(MO_DEVICE_STATUS);
779 if (reg & (1<<2)) {
780 dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
781 prescale,ofreq);
782 return 0;
784 dprintk(1,"pll not locked yet, waiting ...\n");
785 msleep(10);
787 dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
788 return -1;
791 int cx88_start_audio_dma(struct cx88_core *core)
793 /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
794 int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
795 /* setup fifo + format */
796 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
797 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
799 cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
800 cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */
802 /* start dma */
803 cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
804 return 0;
807 int cx88_stop_audio_dma(struct cx88_core *core)
809 /* stop dma */
810 cx_write(MO_AUD_DMACNTRL, 0x0000);
812 return 0;
815 static int set_tvaudio(struct cx88_core *core)
817 struct cx88_tvnorm *norm = core->tvnorm;
819 if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
820 return 0;
822 if (V4L2_STD_PAL_BG & norm->id) {
823 core->tvaudio = WW_BG;
825 } else if (V4L2_STD_PAL_DK & norm->id) {
826 core->tvaudio = WW_DK;
828 } else if (V4L2_STD_PAL_I & norm->id) {
829 core->tvaudio = WW_I;
831 } else if (V4L2_STD_SECAM_L & norm->id) {
832 core->tvaudio = WW_L;
834 } else if (V4L2_STD_SECAM_DK & norm->id) {
835 core->tvaudio = WW_DK;
837 } else if ((V4L2_STD_NTSC_M & norm->id) ||
838 (V4L2_STD_PAL_M & norm->id)) {
839 core->tvaudio = WW_BTSC;
841 } else if (V4L2_STD_NTSC_M_JP & norm->id) {
842 core->tvaudio = WW_EIAJ;
844 } else {
845 printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
846 core->name, norm->name);
847 core->tvaudio = 0;
848 return 0;
851 cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
852 cx88_set_tvaudio(core);
853 /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
856 This should be needed only on cx88-alsa. It seems that some cx88 chips have
857 bugs and does require DMA enabled for it to work.
859 cx88_start_audio_dma(core);
860 return 0;
865 int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
867 u32 fsc8;
868 u32 adc_clock;
869 u32 vdec_clock;
870 u32 step_db,step_dr;
871 u64 tmp64;
872 u32 bdelay,agcdelay,htotal;
874 core->tvnorm = norm;
875 fsc8 = norm_fsc8(norm);
876 adc_clock = xtal;
877 vdec_clock = fsc8;
878 step_db = fsc8;
879 step_dr = fsc8;
881 if (norm->id & V4L2_STD_SECAM) {
882 step_db = 4250000 * 8;
883 step_dr = 4406250 * 8;
886 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
887 norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr);
888 set_pll(core,2,vdec_clock);
890 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
891 norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
892 cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat);
894 // FIXME: as-is from DScaler
895 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
896 norm->cxoformat, cx_read(MO_OUTPUT_FORMAT));
897 cx_write(MO_OUTPUT_FORMAT, norm->cxoformat);
899 // MO_SCONV_REG = adc clock / video dec clock * 2^17
900 tmp64 = adc_clock * (u64)(1 << 17);
901 do_div(tmp64, vdec_clock);
902 dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
903 (u32)tmp64, cx_read(MO_SCONV_REG));
904 cx_write(MO_SCONV_REG, (u32)tmp64);
906 // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
907 tmp64 = step_db * (u64)(1 << 22);
908 do_div(tmp64, vdec_clock);
909 dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
910 (u32)tmp64, cx_read(MO_SUB_STEP));
911 cx_write(MO_SUB_STEP, (u32)tmp64);
913 // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
914 tmp64 = step_dr * (u64)(1 << 22);
915 do_div(tmp64, vdec_clock);
916 dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
917 (u32)tmp64, cx_read(MO_SUB_STEP_DR));
918 cx_write(MO_SUB_STEP_DR, (u32)tmp64);
920 // bdelay + agcdelay
921 bdelay = vdec_clock * 65 / 20000000 + 21;
922 agcdelay = vdec_clock * 68 / 20000000 + 15;
923 dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
924 (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
925 cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
927 // htotal
928 tmp64 = norm_htotal(norm) * (u64)vdec_clock;
929 do_div(tmp64, fsc8);
930 htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11);
931 dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
932 htotal, cx_read(MO_HTOTAL), (u32)tmp64);
933 cx_write(MO_HTOTAL, htotal);
935 // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
936 // the effective vbi offset ~244 samples, the same as the Bt8x8
937 cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
939 // this is needed as well to set all tvnorm parameter
940 cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
942 // audio
943 set_tvaudio(core);
945 // tell i2c chips
946 cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);
948 // done
949 return 0;
952 /* ------------------------------------------------------------------ */
954 static int cx88_pci_quirks(char *name, struct pci_dev *pci)
956 unsigned int lat = UNSET;
957 u8 ctrl = 0;
958 u8 value;
960 /* check pci quirks */
961 if (pci_pci_problems & PCIPCI_TRITON) {
962 printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
963 name);
964 ctrl |= CX88X_EN_TBFX;
966 if (pci_pci_problems & PCIPCI_NATOMA) {
967 printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
968 name);
969 ctrl |= CX88X_EN_TBFX;
971 if (pci_pci_problems & PCIPCI_VIAETBF) {
972 printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
973 name);
974 ctrl |= CX88X_EN_TBFX;
976 if (pci_pci_problems & PCIPCI_VSFX) {
977 printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
978 name);
979 ctrl |= CX88X_EN_VSFX;
981 #ifdef PCIPCI_ALIMAGIK
982 if (pci_pci_problems & PCIPCI_ALIMAGIK) {
983 printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
984 name);
985 lat = 0x0A;
987 #endif
989 /* check insmod options */
990 if (UNSET != latency)
991 lat = latency;
993 /* apply stuff */
994 if (ctrl) {
995 pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
996 value |= ctrl;
997 pci_write_config_byte(pci, CX88X_DEVCTRL, value);
999 if (UNSET != lat) {
1000 printk(KERN_INFO "%s: setting pci latency timer to %d\n",
1001 name, latency);
1002 pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
1004 return 0;
1007 /* ------------------------------------------------------------------ */
1009 struct video_device *cx88_vdev_init(struct cx88_core *core,
1010 struct pci_dev *pci,
1011 struct video_device *template,
1012 char *type)
1014 struct video_device *vfd;
1016 vfd = video_device_alloc();
1017 if (NULL == vfd)
1018 return NULL;
1019 *vfd = *template;
1020 vfd->minor = -1;
1021 vfd->dev = &pci->dev;
1022 vfd->release = video_device_release;
1023 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1024 core->name, type, cx88_boards[core->board].name);
1025 return vfd;
1028 static int get_ressources(struct cx88_core *core, struct pci_dev *pci)
1030 if (request_mem_region(pci_resource_start(pci,0),
1031 pci_resource_len(pci,0),
1032 core->name))
1033 return 0;
1034 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",
1035 core->name,pci_resource_start(pci,0));
1036 return -EBUSY;
1039 struct cx88_core* cx88_core_get(struct pci_dev *pci)
1041 struct cx88_core *core;
1042 struct list_head *item;
1043 int i;
1045 mutex_lock(&devlist);
1046 list_for_each(item,&cx88_devlist) {
1047 core = list_entry(item, struct cx88_core, devlist);
1048 if (pci->bus->number != core->pci_bus)
1049 continue;
1050 if (PCI_SLOT(pci->devfn) != core->pci_slot)
1051 continue;
1053 if (0 != get_ressources(core,pci))
1054 goto fail_unlock;
1055 atomic_inc(&core->refcount);
1056 mutex_unlock(&devlist);
1057 return core;
1059 core = kzalloc(sizeof(*core),GFP_KERNEL);
1060 if (NULL == core)
1061 goto fail_unlock;
1063 atomic_inc(&core->refcount);
1064 core->pci_bus = pci->bus->number;
1065 core->pci_slot = PCI_SLOT(pci->devfn);
1066 core->pci_irqmask = 0x00fc00;
1067 mutex_init(&core->lock);
1069 core->nr = cx88_devcount++;
1070 sprintf(core->name,"cx88[%d]",core->nr);
1071 if (0 != get_ressources(core,pci)) {
1072 printk(KERN_ERR "CORE %s No more PCI ressources for "
1073 "subsystem: %04x:%04x, board: %s\n",
1074 core->name,pci->subsystem_vendor,
1075 pci->subsystem_device,
1076 cx88_boards[core->board].name);
1078 cx88_devcount--;
1079 goto fail_free;
1081 list_add_tail(&core->devlist,&cx88_devlist);
1083 /* PCI stuff */
1084 cx88_pci_quirks(core->name, pci);
1085 core->lmmio = ioremap(pci_resource_start(pci,0),
1086 pci_resource_len(pci,0));
1087 core->bmmio = (u8 __iomem *)core->lmmio;
1089 /* board config */
1090 core->board = UNSET;
1091 if (card[core->nr] < cx88_bcount)
1092 core->board = card[core->nr];
1093 for (i = 0; UNSET == core->board && i < cx88_idcount; i++)
1094 if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
1095 pci->subsystem_device == cx88_subids[i].subdevice)
1096 core->board = cx88_subids[i].card;
1097 if (UNSET == core->board) {
1098 core->board = CX88_BOARD_UNKNOWN;
1099 cx88_card_list(core,pci);
1101 printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
1102 core->name,pci->subsystem_vendor,
1103 pci->subsystem_device,cx88_boards[core->board].name,
1104 core->board, card[core->nr] == core->board ?
1105 "insmod option" : "autodetected");
1107 core->tuner_type = tuner[core->nr];
1108 core->radio_type = radio[core->nr];
1109 if (UNSET == core->tuner_type)
1110 core->tuner_type = cx88_boards[core->board].tuner_type;
1111 if (UNSET == core->radio_type)
1112 core->radio_type = cx88_boards[core->board].radio_type;
1113 if (!core->tuner_addr)
1114 core->tuner_addr = cx88_boards[core->board].tuner_addr;
1115 if (!core->radio_addr)
1116 core->radio_addr = cx88_boards[core->board].radio_addr;
1118 printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
1119 core->tuner_type, core->tuner_addr<<1,
1120 core->radio_type, core->radio_addr<<1);
1122 core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
1124 /* init hardware */
1125 cx88_reset(core);
1126 cx88_i2c_init(core,pci);
1127 cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
1128 cx88_card_setup(core);
1129 cx88_ir_init(core,pci);
1131 mutex_unlock(&devlist);
1132 return core;
1134 fail_free:
1135 kfree(core);
1136 fail_unlock:
1137 mutex_unlock(&devlist);
1138 return NULL;
1141 void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1143 release_mem_region(pci_resource_start(pci,0),
1144 pci_resource_len(pci,0));
1146 if (!atomic_dec_and_test(&core->refcount))
1147 return;
1149 mutex_lock(&devlist);
1150 cx88_ir_fini(core);
1151 if (0 == core->i2c_rc)
1152 i2c_bit_del_bus(&core->i2c_adap);
1153 list_del(&core->devlist);
1154 iounmap(core->lmmio);
1155 cx88_devcount--;
1156 mutex_unlock(&devlist);
1157 kfree(core);
1160 /* ------------------------------------------------------------------ */
1162 EXPORT_SYMBOL(cx88_print_irqbits);
1164 EXPORT_SYMBOL(cx88_core_irq);
1165 EXPORT_SYMBOL(cx88_wakeup);
1166 EXPORT_SYMBOL(cx88_reset);
1167 EXPORT_SYMBOL(cx88_shutdown);
1169 EXPORT_SYMBOL(cx88_risc_buffer);
1170 EXPORT_SYMBOL(cx88_risc_databuffer);
1171 EXPORT_SYMBOL(cx88_risc_stopper);
1172 EXPORT_SYMBOL(cx88_free_buffer);
1174 EXPORT_SYMBOL(cx88_sram_channels);
1175 EXPORT_SYMBOL(cx88_sram_channel_setup);
1176 EXPORT_SYMBOL(cx88_sram_channel_dump);
1178 EXPORT_SYMBOL(cx88_set_tvnorm);
1179 EXPORT_SYMBOL(cx88_set_scale);
1181 EXPORT_SYMBOL(cx88_vdev_init);
1182 EXPORT_SYMBOL(cx88_core_get);
1183 EXPORT_SYMBOL(cx88_core_put);
1186 * Local variables:
1187 * c-basic-offset: 8
1188 * End:
1189 * 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