V4L/DVB (3394): Bttv: correct bttv_risc_packed buffer size
[linux-2.6/linux-loongson.git] / drivers / media / video / cx88 / cx88-core.c
blob25be3a976d09462254ccb956c36ea437c6992df3
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) */
150 instructions = (bpl * lines * fields) / PAGE_SIZE + lines * fields;
151 instructions += 3 + 4;
152 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
153 return rc;
155 /* write risc instructions */
156 rp = risc->cpu;
157 if (UNSET != top_offset)
158 rp = cx88_risc_field(rp, sglist, top_offset, 0,
159 bpl, padding, lines);
160 if (UNSET != bottom_offset)
161 rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
162 bpl, padding, lines);
164 /* save pointer to jmp instruction address */
165 risc->jmp = rp;
166 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
167 return 0;
170 int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
171 struct scatterlist *sglist, unsigned int bpl,
172 unsigned int lines)
174 u32 instructions;
175 u32 *rp;
176 int rc;
178 /* estimate risc mem: worst case is one write per page border +
179 one write per scan line + syncs + jump (all 2 dwords) */
180 instructions = (bpl * lines) / PAGE_SIZE + lines;
181 instructions += 3 + 4;
182 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
183 return rc;
185 /* write risc instructions */
186 rp = risc->cpu;
187 rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
189 /* save pointer to jmp instruction address */
190 risc->jmp = rp;
191 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
192 return 0;
195 int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
196 u32 reg, u32 mask, u32 value)
198 u32 *rp;
199 int rc;
201 if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
202 return rc;
204 /* write risc instructions */
205 rp = risc->cpu;
206 *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
207 *(rp++) = cpu_to_le32(reg);
208 *(rp++) = cpu_to_le32(value);
209 *(rp++) = cpu_to_le32(mask);
210 *(rp++) = cpu_to_le32(RISC_JUMP);
211 *(rp++) = cpu_to_le32(risc->dma);
212 return 0;
215 void
216 cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
218 if (in_interrupt())
219 BUG();
220 videobuf_waiton(&buf->vb,0,0);
221 videobuf_dma_pci_unmap(pci, &buf->vb.dma);
222 videobuf_dma_free(&buf->vb.dma);
223 btcx_riscmem_free(pci, &buf->risc);
224 buf->vb.state = STATE_NEEDS_INIT;
227 /* ------------------------------------------------------------------ */
228 /* our SRAM memory layout */
230 /* we are going to put all thr risc programs into host memory, so we
231 * can use the whole SDRAM for the DMA fifos. To simplify things, we
232 * use a static memory layout. That surely will waste memory in case
233 * we don't use all DMA channels at the same time (which will be the
234 * case most of the time). But that still gives us enougth FIFO space
235 * to be able to deal with insane long pci latencies ...
237 * FIFO space allocations:
238 * channel 21 (y video) - 10.0k
239 * channel 22 (u video) - 2.0k
240 * channel 23 (v video) - 2.0k
241 * channel 24 (vbi) - 4.0k
242 * channels 25+26 (audio) - 4.0k
243 * channel 28 (mpeg) - 4.0k
244 * TOTAL = 29.0k
246 * Every channel has 160 bytes control data (64 bytes instruction
247 * queue and 6 CDT entries), which is close to 2k total.
249 * Address layout:
250 * 0x0000 - 0x03ff CMDs / reserved
251 * 0x0400 - 0x0bff instruction queues + CDs
252 * 0x0c00 - FIFOs
255 struct sram_channel cx88_sram_channels[] = {
256 [SRAM_CH21] = {
257 .name = "video y / packed",
258 .cmds_start = 0x180040,
259 .ctrl_start = 0x180400,
260 .cdt = 0x180400 + 64,
261 .fifo_start = 0x180c00,
262 .fifo_size = 0x002800,
263 .ptr1_reg = MO_DMA21_PTR1,
264 .ptr2_reg = MO_DMA21_PTR2,
265 .cnt1_reg = MO_DMA21_CNT1,
266 .cnt2_reg = MO_DMA21_CNT2,
268 [SRAM_CH22] = {
269 .name = "video u",
270 .cmds_start = 0x180080,
271 .ctrl_start = 0x1804a0,
272 .cdt = 0x1804a0 + 64,
273 .fifo_start = 0x183400,
274 .fifo_size = 0x000800,
275 .ptr1_reg = MO_DMA22_PTR1,
276 .ptr2_reg = MO_DMA22_PTR2,
277 .cnt1_reg = MO_DMA22_CNT1,
278 .cnt2_reg = MO_DMA22_CNT2,
280 [SRAM_CH23] = {
281 .name = "video v",
282 .cmds_start = 0x1800c0,
283 .ctrl_start = 0x180540,
284 .cdt = 0x180540 + 64,
285 .fifo_start = 0x183c00,
286 .fifo_size = 0x000800,
287 .ptr1_reg = MO_DMA23_PTR1,
288 .ptr2_reg = MO_DMA23_PTR2,
289 .cnt1_reg = MO_DMA23_CNT1,
290 .cnt2_reg = MO_DMA23_CNT2,
292 [SRAM_CH24] = {
293 .name = "vbi",
294 .cmds_start = 0x180100,
295 .ctrl_start = 0x1805e0,
296 .cdt = 0x1805e0 + 64,
297 .fifo_start = 0x184400,
298 .fifo_size = 0x001000,
299 .ptr1_reg = MO_DMA24_PTR1,
300 .ptr2_reg = MO_DMA24_PTR2,
301 .cnt1_reg = MO_DMA24_CNT1,
302 .cnt2_reg = MO_DMA24_CNT2,
304 [SRAM_CH25] = {
305 .name = "audio from",
306 .cmds_start = 0x180140,
307 .ctrl_start = 0x180680,
308 .cdt = 0x180680 + 64,
309 .fifo_start = 0x185400,
310 .fifo_size = 0x001000,
311 .ptr1_reg = MO_DMA25_PTR1,
312 .ptr2_reg = MO_DMA25_PTR2,
313 .cnt1_reg = MO_DMA25_CNT1,
314 .cnt2_reg = MO_DMA25_CNT2,
316 [SRAM_CH26] = {
317 .name = "audio to",
318 .cmds_start = 0x180180,
319 .ctrl_start = 0x180720,
320 .cdt = 0x180680 + 64, /* same as audio IN */
321 .fifo_start = 0x185400, /* same as audio IN */
322 .fifo_size = 0x001000, /* same as audio IN */
323 .ptr1_reg = MO_DMA26_PTR1,
324 .ptr2_reg = MO_DMA26_PTR2,
325 .cnt1_reg = MO_DMA26_CNT1,
326 .cnt2_reg = MO_DMA26_CNT2,
328 [SRAM_CH28] = {
329 .name = "mpeg",
330 .cmds_start = 0x180200,
331 .ctrl_start = 0x1807C0,
332 .cdt = 0x1807C0 + 64,
333 .fifo_start = 0x186400,
334 .fifo_size = 0x001000,
335 .ptr1_reg = MO_DMA28_PTR1,
336 .ptr2_reg = MO_DMA28_PTR2,
337 .cnt1_reg = MO_DMA28_CNT1,
338 .cnt2_reg = MO_DMA28_CNT2,
342 int cx88_sram_channel_setup(struct cx88_core *core,
343 struct sram_channel *ch,
344 unsigned int bpl, u32 risc)
346 unsigned int i,lines;
347 u32 cdt;
349 bpl = (bpl + 7) & ~7; /* alignment */
350 cdt = ch->cdt;
351 lines = ch->fifo_size / bpl;
352 if (lines > 6)
353 lines = 6;
354 BUG_ON(lines < 2);
356 /* write CDT */
357 for (i = 0; i < lines; i++)
358 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
360 /* write CMDS */
361 cx_write(ch->cmds_start + 0, risc);
362 cx_write(ch->cmds_start + 4, cdt);
363 cx_write(ch->cmds_start + 8, (lines*16) >> 3);
364 cx_write(ch->cmds_start + 12, ch->ctrl_start);
365 cx_write(ch->cmds_start + 16, 64 >> 2);
366 for (i = 20; i < 64; i += 4)
367 cx_write(ch->cmds_start + i, 0);
369 /* fill registers */
370 cx_write(ch->ptr1_reg, ch->fifo_start);
371 cx_write(ch->ptr2_reg, cdt);
372 cx_write(ch->cnt1_reg, (bpl >> 3) -1);
373 cx_write(ch->cnt2_reg, (lines*16) >> 3);
375 dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
376 return 0;
379 /* ------------------------------------------------------------------ */
380 /* debug helper code */
382 static int cx88_risc_decode(u32 risc)
384 static char *instr[16] = {
385 [ RISC_SYNC >> 28 ] = "sync",
386 [ RISC_WRITE >> 28 ] = "write",
387 [ RISC_WRITEC >> 28 ] = "writec",
388 [ RISC_READ >> 28 ] = "read",
389 [ RISC_READC >> 28 ] = "readc",
390 [ RISC_JUMP >> 28 ] = "jump",
391 [ RISC_SKIP >> 28 ] = "skip",
392 [ RISC_WRITERM >> 28 ] = "writerm",
393 [ RISC_WRITECM >> 28 ] = "writecm",
394 [ RISC_WRITECR >> 28 ] = "writecr",
396 static int incr[16] = {
397 [ RISC_WRITE >> 28 ] = 2,
398 [ RISC_JUMP >> 28 ] = 2,
399 [ RISC_WRITERM >> 28 ] = 3,
400 [ RISC_WRITECM >> 28 ] = 3,
401 [ RISC_WRITECR >> 28 ] = 4,
403 static char *bits[] = {
404 "12", "13", "14", "resync",
405 "cnt0", "cnt1", "18", "19",
406 "20", "21", "22", "23",
407 "irq1", "irq2", "eol", "sol",
409 int i;
411 printk("0x%08x [ %s", risc,
412 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
413 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
414 if (risc & (1 << (i + 12)))
415 printk(" %s",bits[i]);
416 printk(" count=%d ]\n", risc & 0xfff);
417 return incr[risc >> 28] ? incr[risc >> 28] : 1;
421 void cx88_sram_channel_dump(struct cx88_core *core,
422 struct sram_channel *ch)
424 static char *name[] = {
425 "initial risc",
426 "cdt base",
427 "cdt size",
428 "iq base",
429 "iq size",
430 "risc pc",
431 "iq wr ptr",
432 "iq rd ptr",
433 "cdt current",
434 "pci target",
435 "line / byte",
437 u32 risc;
438 unsigned int i,j,n;
440 printk("%s: %s - dma channel status dump\n",
441 core->name,ch->name);
442 for (i = 0; i < ARRAY_SIZE(name); i++)
443 printk("%s: cmds: %-12s: 0x%08x\n",
444 core->name,name[i],
445 cx_read(ch->cmds_start + 4*i));
446 for (i = 0; i < 4; i++) {
447 risc = cx_read(ch->cmds_start + 4 * (i+11));
448 printk("%s: risc%d: ", core->name, i);
449 cx88_risc_decode(risc);
451 for (i = 0; i < 16; i += n) {
452 risc = cx_read(ch->ctrl_start + 4 * i);
453 printk("%s: iq %x: ", core->name, i);
454 n = cx88_risc_decode(risc);
455 for (j = 1; j < n; j++) {
456 risc = cx_read(ch->ctrl_start + 4 * (i+j));
457 printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
458 core->name, i+j, risc, j);
462 printk("%s: fifo: 0x%08x -> 0x%x\n",
463 core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
464 printk("%s: ctrl: 0x%08x -> 0x%x\n",
465 core->name, ch->ctrl_start, ch->ctrl_start+6*16);
466 printk("%s: ptr1_reg: 0x%08x\n",
467 core->name,cx_read(ch->ptr1_reg));
468 printk("%s: ptr2_reg: 0x%08x\n",
469 core->name,cx_read(ch->ptr2_reg));
470 printk("%s: cnt1_reg: 0x%08x\n",
471 core->name,cx_read(ch->cnt1_reg));
472 printk("%s: cnt2_reg: 0x%08x\n",
473 core->name,cx_read(ch->cnt2_reg));
476 static char *cx88_pci_irqs[32] = {
477 "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
478 "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
479 "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
480 "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
483 void cx88_print_irqbits(char *name, char *tag, char **strings,
484 u32 bits, u32 mask)
486 unsigned int i;
488 printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
489 for (i = 0; i < 32; i++) {
490 if (!(bits & (1 << i)))
491 continue;
492 if (strings[i])
493 printk(" %s", strings[i]);
494 else
495 printk(" %d", i);
496 if (!(mask & (1 << i)))
497 continue;
498 printk("*");
500 printk("\n");
503 /* ------------------------------------------------------------------ */
505 int cx88_core_irq(struct cx88_core *core, u32 status)
507 int handled = 0;
509 if (status & (1<<18)) {
510 cx88_ir_irq(core);
511 handled++;
513 if (!handled)
514 cx88_print_irqbits(core->name, "irq pci",
515 cx88_pci_irqs, status,
516 core->pci_irqmask);
517 return handled;
520 void cx88_wakeup(struct cx88_core *core,
521 struct cx88_dmaqueue *q, u32 count)
523 struct cx88_buffer *buf;
524 int bc;
526 for (bc = 0;; bc++) {
527 if (list_empty(&q->active))
528 break;
529 buf = list_entry(q->active.next,
530 struct cx88_buffer, vb.queue);
531 /* count comes from the hw and is is 16bit wide --
532 * this trick handles wrap-arounds correctly for
533 * up to 32767 buffers in flight... */
534 if ((s16) (count - buf->count) < 0)
535 break;
536 do_gettimeofday(&buf->vb.ts);
537 dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
538 count, buf->count);
539 buf->vb.state = STATE_DONE;
540 list_del(&buf->vb.queue);
541 wake_up(&buf->vb.done);
543 if (list_empty(&q->active)) {
544 del_timer(&q->timeout);
545 } else {
546 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
548 if (bc != 1)
549 printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
552 void cx88_shutdown(struct cx88_core *core)
554 /* disable RISC controller + IRQs */
555 cx_write(MO_DEV_CNTRL2, 0);
557 /* stop dma transfers */
558 cx_write(MO_VID_DMACNTRL, 0x0);
559 cx_write(MO_AUD_DMACNTRL, 0x0);
560 cx_write(MO_TS_DMACNTRL, 0x0);
561 cx_write(MO_VIP_DMACNTRL, 0x0);
562 cx_write(MO_GPHST_DMACNTRL, 0x0);
564 /* stop interrupts */
565 cx_write(MO_PCI_INTMSK, 0x0);
566 cx_write(MO_VID_INTMSK, 0x0);
567 cx_write(MO_AUD_INTMSK, 0x0);
568 cx_write(MO_TS_INTMSK, 0x0);
569 cx_write(MO_VIP_INTMSK, 0x0);
570 cx_write(MO_GPHST_INTMSK, 0x0);
572 /* stop capturing */
573 cx_write(VID_CAPTURE_CONTROL, 0);
576 int cx88_reset(struct cx88_core *core)
578 dprintk(1,"%s\n",__FUNCTION__);
579 cx88_shutdown(core);
581 /* clear irq status */
582 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
583 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
584 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
586 /* wait a bit */
587 msleep(100);
589 /* init sram */
590 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
591 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
592 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
593 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
594 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
595 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
596 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
598 /* misc init ... */
599 cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
600 (1 << 12) | // agc gain
601 (1 << 11) | // adaptibe agc
602 (0 << 10) | // chroma agc
603 (0 << 9) | // ckillen
604 (7)));
606 /* setup image format */
607 cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
609 /* setup FIFO Threshholds */
610 cx_write(MO_PDMA_STHRSH, 0x0807);
611 cx_write(MO_PDMA_DTHRSH, 0x0807);
613 /* fixes flashing of image */
614 cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
615 cx_write(MO_AGC_BACK_VBI, 0x00E00555);
617 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
618 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
619 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
621 /* Reset on-board parts */
622 cx_write(MO_SRST_IO, 0);
623 msleep(10);
624 cx_write(MO_SRST_IO, 1);
626 return 0;
629 /* ------------------------------------------------------------------ */
631 static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
633 return (norm->id & V4L2_STD_625_50) ? 922 : 754;
636 static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
638 return (norm->id & V4L2_STD_625_50) ? 186 : 135;
641 static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
643 return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18;
646 static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
648 static const unsigned int ntsc = 28636360;
649 static const unsigned int pal = 35468950;
650 static const unsigned int palm = 28604892;
652 if (norm->id & V4L2_STD_PAL_M)
653 return palm;
655 return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
658 static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
660 return (norm->id & V4L2_STD_625_50)
661 ? HLNotchFilter135PAL
662 : HLNotchFilter135NTSC;
665 static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
667 /* Should always be Line Draw Time / (4*FSC) */
669 if (norm->id & V4L2_STD_PAL_M)
670 return 909;
672 return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
675 static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
677 return (norm->id & V4L2_STD_625_50) ? 511 : 288;
680 int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
681 enum v4l2_field field)
683 unsigned int swidth = norm_swidth(core->tvnorm);
684 unsigned int sheight = norm_maxh(core->tvnorm);
685 u32 value;
687 dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
688 V4L2_FIELD_HAS_TOP(field) ? "T" : "",
689 V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
690 core->tvnorm->name);
691 if (!V4L2_FIELD_HAS_BOTH(field))
692 height *= 2;
694 // recalc H delay and scale registers
695 value = (width * norm_hdelay(core->tvnorm)) / swidth;
696 value &= 0x3fe;
697 cx_write(MO_HDELAY_EVEN, value);
698 cx_write(MO_HDELAY_ODD, value);
699 dprintk(1,"set_scale: hdelay 0x%04x\n", value);
701 value = (swidth * 4096 / width) - 4096;
702 cx_write(MO_HSCALE_EVEN, value);
703 cx_write(MO_HSCALE_ODD, value);
704 dprintk(1,"set_scale: hscale 0x%04x\n", value);
706 cx_write(MO_HACTIVE_EVEN, width);
707 cx_write(MO_HACTIVE_ODD, width);
708 dprintk(1,"set_scale: hactive 0x%04x\n", width);
710 // recalc V scale Register (delay is constant)
711 cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
712 cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
713 dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
715 value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
716 cx_write(MO_VSCALE_EVEN, value);
717 cx_write(MO_VSCALE_ODD, value);
718 dprintk(1,"set_scale: vscale 0x%04x\n", value);
720 cx_write(MO_VACTIVE_EVEN, sheight);
721 cx_write(MO_VACTIVE_ODD, sheight);
722 dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
724 // setup filters
725 value = 0;
726 value |= (1 << 19); // CFILT (default)
727 if (core->tvnorm->id & V4L2_STD_SECAM) {
728 value |= (1 << 15);
729 value |= (1 << 16);
731 if (INPUT(core->input)->type == CX88_VMUX_SVIDEO)
732 value |= (1 << 13) | (1 << 5);
733 if (V4L2_FIELD_INTERLACED == field)
734 value |= (1 << 3); // VINT (interlaced vertical scaling)
735 if (width < 385)
736 value |= (1 << 0); // 3-tap interpolation
737 if (width < 193)
738 value |= (1 << 1); // 5-tap interpolation
739 if (nocomb)
740 value |= (3 << 5); // disable comb filter
742 cx_write(MO_FILTER_EVEN, value);
743 cx_write(MO_FILTER_ODD, value);
744 dprintk(1,"set_scale: filter 0x%04x\n", value);
746 return 0;
749 static const u32 xtal = 28636363;
751 static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
753 static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
754 u64 pll;
755 u32 reg;
756 int i;
758 if (prescale < 2)
759 prescale = 2;
760 if (prescale > 5)
761 prescale = 5;
763 pll = ofreq * 8 * prescale * (u64)(1 << 20);
764 do_div(pll,xtal);
765 reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
766 if (((reg >> 20) & 0x3f) < 14) {
767 printk("%s/0: pll out of range\n",core->name);
768 return -1;
771 dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
772 reg, cx_read(MO_PLL_REG), ofreq);
773 cx_write(MO_PLL_REG, reg);
774 for (i = 0; i < 100; i++) {
775 reg = cx_read(MO_DEVICE_STATUS);
776 if (reg & (1<<2)) {
777 dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
778 prescale,ofreq);
779 return 0;
781 dprintk(1,"pll not locked yet, waiting ...\n");
782 msleep(10);
784 dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
785 return -1;
788 int cx88_start_audio_dma(struct cx88_core *core)
790 /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
791 int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
792 /* setup fifo + format */
793 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
794 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
796 cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
797 cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */
799 /* start dma */
800 cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
801 return 0;
804 int cx88_stop_audio_dma(struct cx88_core *core)
806 /* stop dma */
807 cx_write(MO_AUD_DMACNTRL, 0x0000);
809 return 0;
812 static int set_tvaudio(struct cx88_core *core)
814 struct cx88_tvnorm *norm = core->tvnorm;
816 if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
817 return 0;
819 if (V4L2_STD_PAL_BG & norm->id) {
820 core->tvaudio = WW_BG;
822 } else if (V4L2_STD_PAL_DK & norm->id) {
823 core->tvaudio = WW_DK;
825 } else if (V4L2_STD_PAL_I & norm->id) {
826 core->tvaudio = WW_I;
828 } else if (V4L2_STD_SECAM_L & norm->id) {
829 core->tvaudio = WW_L;
831 } else if (V4L2_STD_SECAM_DK & norm->id) {
832 core->tvaudio = WW_DK;
834 } else if ((V4L2_STD_NTSC_M & norm->id) ||
835 (V4L2_STD_PAL_M & norm->id)) {
836 core->tvaudio = WW_BTSC;
838 } else if (V4L2_STD_NTSC_M_JP & norm->id) {
839 core->tvaudio = WW_EIAJ;
841 } else {
842 printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
843 core->name, norm->name);
844 core->tvaudio = 0;
845 return 0;
848 cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
849 cx88_set_tvaudio(core);
850 /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
853 This should be needed only on cx88-alsa. It seems that some cx88 chips have
854 bugs and does require DMA enabled for it to work.
856 cx88_start_audio_dma(core);
857 return 0;
862 int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
864 u32 fsc8;
865 u32 adc_clock;
866 u32 vdec_clock;
867 u32 step_db,step_dr;
868 u64 tmp64;
869 u32 bdelay,agcdelay,htotal;
871 core->tvnorm = norm;
872 fsc8 = norm_fsc8(norm);
873 adc_clock = xtal;
874 vdec_clock = fsc8;
875 step_db = fsc8;
876 step_dr = fsc8;
878 if (norm->id & V4L2_STD_SECAM) {
879 step_db = 4250000 * 8;
880 step_dr = 4406250 * 8;
883 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
884 norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr);
885 set_pll(core,2,vdec_clock);
887 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
888 norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
889 cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat);
891 // FIXME: as-is from DScaler
892 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
893 norm->cxoformat, cx_read(MO_OUTPUT_FORMAT));
894 cx_write(MO_OUTPUT_FORMAT, norm->cxoformat);
896 // MO_SCONV_REG = adc clock / video dec clock * 2^17
897 tmp64 = adc_clock * (u64)(1 << 17);
898 do_div(tmp64, vdec_clock);
899 dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
900 (u32)tmp64, cx_read(MO_SCONV_REG));
901 cx_write(MO_SCONV_REG, (u32)tmp64);
903 // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
904 tmp64 = step_db * (u64)(1 << 22);
905 do_div(tmp64, vdec_clock);
906 dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
907 (u32)tmp64, cx_read(MO_SUB_STEP));
908 cx_write(MO_SUB_STEP, (u32)tmp64);
910 // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
911 tmp64 = step_dr * (u64)(1 << 22);
912 do_div(tmp64, vdec_clock);
913 dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
914 (u32)tmp64, cx_read(MO_SUB_STEP_DR));
915 cx_write(MO_SUB_STEP_DR, (u32)tmp64);
917 // bdelay + agcdelay
918 bdelay = vdec_clock * 65 / 20000000 + 21;
919 agcdelay = vdec_clock * 68 / 20000000 + 15;
920 dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
921 (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
922 cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
924 // htotal
925 tmp64 = norm_htotal(norm) * (u64)vdec_clock;
926 do_div(tmp64, fsc8);
927 htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11);
928 dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
929 htotal, cx_read(MO_HTOTAL), (u32)tmp64);
930 cx_write(MO_HTOTAL, htotal);
932 // vbi stuff
933 cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */
934 norm_vbipack(norm)));
936 // this is needed as well to set all tvnorm parameter
937 cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
939 // audio
940 set_tvaudio(core);
942 // tell i2c chips
943 cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);
945 // done
946 return 0;
949 /* ------------------------------------------------------------------ */
951 static int cx88_pci_quirks(char *name, struct pci_dev *pci)
953 unsigned int lat = UNSET;
954 u8 ctrl = 0;
955 u8 value;
957 /* check pci quirks */
958 if (pci_pci_problems & PCIPCI_TRITON) {
959 printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
960 name);
961 ctrl |= CX88X_EN_TBFX;
963 if (pci_pci_problems & PCIPCI_NATOMA) {
964 printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
965 name);
966 ctrl |= CX88X_EN_TBFX;
968 if (pci_pci_problems & PCIPCI_VIAETBF) {
969 printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
970 name);
971 ctrl |= CX88X_EN_TBFX;
973 if (pci_pci_problems & PCIPCI_VSFX) {
974 printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
975 name);
976 ctrl |= CX88X_EN_VSFX;
978 #ifdef PCIPCI_ALIMAGIK
979 if (pci_pci_problems & PCIPCI_ALIMAGIK) {
980 printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
981 name);
982 lat = 0x0A;
984 #endif
986 /* check insmod options */
987 if (UNSET != latency)
988 lat = latency;
990 /* apply stuff */
991 if (ctrl) {
992 pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
993 value |= ctrl;
994 pci_write_config_byte(pci, CX88X_DEVCTRL, value);
996 if (UNSET != lat) {
997 printk(KERN_INFO "%s: setting pci latency timer to %d\n",
998 name, latency);
999 pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
1001 return 0;
1004 /* ------------------------------------------------------------------ */
1006 struct video_device *cx88_vdev_init(struct cx88_core *core,
1007 struct pci_dev *pci,
1008 struct video_device *template,
1009 char *type)
1011 struct video_device *vfd;
1013 vfd = video_device_alloc();
1014 if (NULL == vfd)
1015 return NULL;
1016 *vfd = *template;
1017 vfd->minor = -1;
1018 vfd->dev = &pci->dev;
1019 vfd->release = video_device_release;
1020 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1021 core->name, type, cx88_boards[core->board].name);
1022 return vfd;
1025 static int get_ressources(struct cx88_core *core, struct pci_dev *pci)
1027 if (request_mem_region(pci_resource_start(pci,0),
1028 pci_resource_len(pci,0),
1029 core->name))
1030 return 0;
1031 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",
1032 core->name,pci_resource_start(pci,0));
1033 return -EBUSY;
1036 struct cx88_core* cx88_core_get(struct pci_dev *pci)
1038 struct cx88_core *core;
1039 struct list_head *item;
1040 int i;
1042 mutex_lock(&devlist);
1043 list_for_each(item,&cx88_devlist) {
1044 core = list_entry(item, struct cx88_core, devlist);
1045 if (pci->bus->number != core->pci_bus)
1046 continue;
1047 if (PCI_SLOT(pci->devfn) != core->pci_slot)
1048 continue;
1050 if (0 != get_ressources(core,pci))
1051 goto fail_unlock;
1052 atomic_inc(&core->refcount);
1053 mutex_unlock(&devlist);
1054 return core;
1056 core = kzalloc(sizeof(*core),GFP_KERNEL);
1057 if (NULL == core)
1058 goto fail_unlock;
1060 atomic_inc(&core->refcount);
1061 core->pci_bus = pci->bus->number;
1062 core->pci_slot = PCI_SLOT(pci->devfn);
1063 core->pci_irqmask = 0x00fc00;
1064 mutex_init(&core->lock);
1066 core->nr = cx88_devcount++;
1067 sprintf(core->name,"cx88[%d]",core->nr);
1068 if (0 != get_ressources(core,pci)) {
1069 printk(KERN_ERR "CORE %s No more PCI ressources for "
1070 "subsystem: %04x:%04x, board: %s\n",
1071 core->name,pci->subsystem_vendor,
1072 pci->subsystem_device,
1073 cx88_boards[core->board].name);
1075 cx88_devcount--;
1076 goto fail_free;
1078 list_add_tail(&core->devlist,&cx88_devlist);
1080 /* PCI stuff */
1081 cx88_pci_quirks(core->name, pci);
1082 core->lmmio = ioremap(pci_resource_start(pci,0),
1083 pci_resource_len(pci,0));
1084 core->bmmio = (u8 __iomem *)core->lmmio;
1086 /* board config */
1087 core->board = UNSET;
1088 if (card[core->nr] < cx88_bcount)
1089 core->board = card[core->nr];
1090 for (i = 0; UNSET == core->board && i < cx88_idcount; i++)
1091 if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
1092 pci->subsystem_device == cx88_subids[i].subdevice)
1093 core->board = cx88_subids[i].card;
1094 if (UNSET == core->board) {
1095 core->board = CX88_BOARD_UNKNOWN;
1096 cx88_card_list(core,pci);
1098 printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
1099 core->name,pci->subsystem_vendor,
1100 pci->subsystem_device,cx88_boards[core->board].name,
1101 core->board, card[core->nr] == core->board ?
1102 "insmod option" : "autodetected");
1104 core->tuner_type = tuner[core->nr];
1105 core->radio_type = radio[core->nr];
1106 if (UNSET == core->tuner_type)
1107 core->tuner_type = cx88_boards[core->board].tuner_type;
1108 if (UNSET == core->radio_type)
1109 core->radio_type = cx88_boards[core->board].radio_type;
1110 if (!core->tuner_addr)
1111 core->tuner_addr = cx88_boards[core->board].tuner_addr;
1112 if (!core->radio_addr)
1113 core->radio_addr = cx88_boards[core->board].radio_addr;
1115 printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
1116 core->tuner_type, core->tuner_addr<<1,
1117 core->radio_type, core->radio_addr<<1);
1119 core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
1121 /* init hardware */
1122 cx88_reset(core);
1123 cx88_i2c_init(core,pci);
1124 cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
1125 cx88_card_setup(core);
1126 cx88_ir_init(core,pci);
1128 mutex_unlock(&devlist);
1129 return core;
1131 fail_free:
1132 kfree(core);
1133 fail_unlock:
1134 mutex_unlock(&devlist);
1135 return NULL;
1138 void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1140 release_mem_region(pci_resource_start(pci,0),
1141 pci_resource_len(pci,0));
1143 if (!atomic_dec_and_test(&core->refcount))
1144 return;
1146 mutex_lock(&devlist);
1147 cx88_ir_fini(core);
1148 if (0 == core->i2c_rc)
1149 i2c_bit_del_bus(&core->i2c_adap);
1150 list_del(&core->devlist);
1151 iounmap(core->lmmio);
1152 cx88_devcount--;
1153 mutex_unlock(&devlist);
1154 kfree(core);
1157 /* ------------------------------------------------------------------ */
1159 EXPORT_SYMBOL(cx88_print_irqbits);
1161 EXPORT_SYMBOL(cx88_core_irq);
1162 EXPORT_SYMBOL(cx88_wakeup);
1163 EXPORT_SYMBOL(cx88_reset);
1164 EXPORT_SYMBOL(cx88_shutdown);
1166 EXPORT_SYMBOL(cx88_risc_buffer);
1167 EXPORT_SYMBOL(cx88_risc_databuffer);
1168 EXPORT_SYMBOL(cx88_risc_stopper);
1169 EXPORT_SYMBOL(cx88_free_buffer);
1171 EXPORT_SYMBOL(cx88_sram_channels);
1172 EXPORT_SYMBOL(cx88_sram_channel_setup);
1173 EXPORT_SYMBOL(cx88_sram_channel_dump);
1175 EXPORT_SYMBOL(cx88_set_tvnorm);
1176 EXPORT_SYMBOL(cx88_set_scale);
1178 EXPORT_SYMBOL(cx88_vdev_init);
1179 EXPORT_SYMBOL(cx88_core_get);
1180 EXPORT_SYMBOL(cx88_core_put);
1181 EXPORT_SYMBOL(cx88_start_audio_dma);
1182 EXPORT_SYMBOL(cx88_stop_audio_dma);
1185 * Local variables:
1186 * c-basic-offset: 8
1187 * End:
1188 * 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