1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <linux/init.h>
29#include <linux/list.h>
30#include <linux/module.h>
31#include <linux/kernel.h>
32#include <linux/slab.h>
33#include <linux/kmod.h>
34#include <linux/sound.h>
35#include <linux/interrupt.h>
36#include <linux/pci.h>
37#include <linux/delay.h>
38#include <linux/videodev2.h>
39#include <linux/mutex.h>
40
41#include "cx88.h"
42#include <media/v4l2-common.h>
43#include <media/v4l2-ioctl.h>
44
45MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
46MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
47MODULE_LICENSE("GPL");
48
49
50
51static unsigned int core_debug;
52module_param(core_debug,int,0644);
53MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
54
55static unsigned int nicam;
56module_param(nicam,int,0644);
57MODULE_PARM_DESC(nicam,"tv audio is nicam");
58
59static unsigned int nocomb;
60module_param(nocomb,int,0644);
61MODULE_PARM_DESC(nocomb,"disable comb filter");
62
63#define dprintk(level,fmt, arg...) if (core_debug >= level) \
64 printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
65
66static unsigned int cx88_devcount;
67static LIST_HEAD(cx88_devlist);
68static DEFINE_MUTEX(devlist);
69
70#define NO_SYNC_LINE (-1U)
71
72
73
74static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
75 unsigned int offset, u32 sync_line,
76 unsigned int bpl, unsigned int padding,
77 unsigned int lines, unsigned int lpi)
78{
79 struct scatterlist *sg;
80 unsigned int line,todo,sol;
81
82
83 if (sync_line != NO_SYNC_LINE)
84 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
85
86
87 sg = sglist;
88 for (line = 0; line < lines; line++) {
89 while (offset && offset >= sg_dma_len(sg)) {
90 offset -= sg_dma_len(sg);
91 sg++;
92 }
93 if (lpi && line>0 && !(line % lpi))
94 sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
95 else
96 sol = RISC_SOL;
97 if (bpl <= sg_dma_len(sg)-offset) {
98
99 *(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
100 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
101 offset+=bpl;
102 } else {
103
104 todo = bpl;
105 *(rp++)=cpu_to_le32(RISC_WRITE|sol|
106 (sg_dma_len(sg)-offset));
107 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
108 todo -= (sg_dma_len(sg)-offset);
109 offset = 0;
110 sg++;
111 while (todo > sg_dma_len(sg)) {
112 *(rp++)=cpu_to_le32(RISC_WRITE|
113 sg_dma_len(sg));
114 *(rp++)=cpu_to_le32(sg_dma_address(sg));
115 todo -= sg_dma_len(sg);
116 sg++;
117 }
118 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
119 *(rp++)=cpu_to_le32(sg_dma_address(sg));
120 offset += todo;
121 }
122 offset += padding;
123 }
124
125 return rp;
126}
127
128int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
129 struct scatterlist *sglist,
130 unsigned int top_offset, unsigned int bottom_offset,
131 unsigned int bpl, unsigned int padding, unsigned int lines)
132{
133 u32 instructions,fields;
134 __le32 *rp;
135 int rc;
136
137 fields = 0;
138 if (UNSET != top_offset)
139 fields++;
140 if (UNSET != bottom_offset)
141 fields++;
142
143
144
145
146
147 instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
148 instructions += 2;
149 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
150 return rc;
151
152
153 rp = risc->cpu;
154 if (UNSET != top_offset)
155 rp = cx88_risc_field(rp, sglist, top_offset, 0,
156 bpl, padding, lines, 0);
157 if (UNSET != bottom_offset)
158 rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
159 bpl, padding, lines, 0);
160
161
162 risc->jmp = rp;
163 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
164 return 0;
165}
166
167int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
168 struct scatterlist *sglist, unsigned int bpl,
169 unsigned int lines, unsigned int lpi)
170{
171 u32 instructions;
172 __le32 *rp;
173 int rc;
174
175
176
177
178
179 instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
180 instructions += 1;
181 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
182 return rc;
183
184
185 rp = risc->cpu;
186 rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
187
188
189 risc->jmp = rp;
190 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
191 return 0;
192}
193
194int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
195 u32 reg, u32 mask, u32 value)
196{
197 __le32 *rp;
198 int rc;
199
200 if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
201 return rc;
202
203
204 rp = risc->cpu;
205 *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
206 *(rp++) = cpu_to_le32(reg);
207 *(rp++) = cpu_to_le32(value);
208 *(rp++) = cpu_to_le32(mask);
209 *(rp++) = cpu_to_le32(RISC_JUMP);
210 *(rp++) = cpu_to_le32(risc->dma);
211 return 0;
212}
213
214void
215cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
216{
217 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
218
219 BUG_ON(in_interrupt());
220 videobuf_waiton(&buf->vb,0,0);
221 videobuf_dma_unmap(q, dma);
222 videobuf_dma_free(dma);
223 btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
224 buf->vb.state = VIDEOBUF_NEEDS_INIT;
225}
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255struct 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,
267 },
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,
279 },
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,
291 },
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,
303 },
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,
315 },
316 [SRAM_CH26] = {
317 .name = "audio to",
318 .cmds_start = 0x180180,
319 .ctrl_start = 0x180720,
320 .cdt = 0x180680 + 64,
321 .fifo_start = 0x185400,
322 .fifo_size = 0x001000,
323 .ptr1_reg = MO_DMA26_PTR1,
324 .ptr2_reg = MO_DMA26_PTR2,
325 .cnt1_reg = MO_DMA26_CNT1,
326 .cnt2_reg = MO_DMA26_CNT2,
327 },
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,
339 },
340};
341
342int cx88_sram_channel_setup(struct cx88_core *core,
343 struct sram_channel *ch,
344 unsigned int bpl, u32 risc)
345{
346 unsigned int i,lines;
347 u32 cdt;
348
349 bpl = (bpl + 7) & ~7;
350 cdt = ch->cdt;
351 lines = ch->fifo_size / bpl;
352 if (lines > 6)
353 lines = 6;
354 BUG_ON(lines < 2);
355
356
357 for (i = 0; i < lines; i++)
358 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
359
360
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);
368
369
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);
374
375 dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
376 return 0;
377}
378
379
380
381
382static int cx88_risc_decode(u32 risc)
383{
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",
395 };
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,
402 };
403 static char *bits[] = {
404 "12", "13", "14", "resync",
405 "cnt0", "cnt1", "18", "19",
406 "20", "21", "22", "23",
407 "irq1", "irq2", "eol", "sol",
408 };
409 int i;
410
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;
418}
419
420
421void cx88_sram_channel_dump(struct cx88_core *core,
422 struct sram_channel *ch)
423{
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",
436 };
437 u32 risc;
438 unsigned int i,j,n;
439
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 (n = 1, i = 0; i < 4; i++) {
447 risc = cx_read(ch->cmds_start + 4 * (i+11));
448 printk("%s: risc%d: ", core->name, i);
449 if (--n)
450 printk("0x%08x [ arg #%d ]\n", risc, n);
451 else
452 n = cx88_risc_decode(risc);
453 }
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);
462 }
463 }
464
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));
477}
478
479static 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"
484};
485
486void cx88_print_irqbits(char *name, char *tag, char **strings,
487 int len, u32 bits, u32 mask)
488{
489 unsigned int i;
490
491 printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
492 for (i = 0; i < len; 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("*");
502 }
503 printk("\n");
504}
505
506
507
508int cx88_core_irq(struct cx88_core *core, u32 status)
509{
510 int handled = 0;
511
512 if (status & PCI_INT_IR_SMPINT) {
513 cx88_ir_irq(core);
514 handled++;
515 }
516 if (!handled)
517 cx88_print_irqbits(core->name, "irq pci",
518 cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
519 status, core->pci_irqmask);
520 return handled;
521}
522
523void cx88_wakeup(struct cx88_core *core,
524 struct cx88_dmaqueue *q, u32 count)
525{
526 struct cx88_buffer *buf;
527 int bc;
528
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
535
536
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 = VIDEOBUF_DONE;
543 list_del(&buf->vb.queue);
544 wake_up(&buf->vb.done);
545 }
546 if (list_empty(&q->active)) {
547 del_timer(&q->timeout);
548 } else {
549 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
550 }
551 if (bc != 1)
552 printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
553}
554
555void cx88_shutdown(struct cx88_core *core)
556{
557
558 cx_write(MO_DEV_CNTRL2, 0);
559
560
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);
566
567
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);
574
575
576 cx_write(VID_CAPTURE_CONTROL, 0);
577}
578
579int cx88_reset(struct cx88_core *core)
580{
581 dprintk(1,"%s\n",__func__);
582 cx88_shutdown(core);
583
584
585 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF);
586 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF);
587 cx_write(MO_INT1_STAT, 0xFFFFFFFF);
588
589
590 msleep(100);
591
592
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);
600
601
602 cx_write(MO_INPUT_FORMAT, ((1 << 13) |
603 (1 << 12) |
604 (1 << 11) |
605 (0 << 10) |
606 (0 << 9) |
607 (7)));
608
609
610 cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
611
612
613 cx_write(MO_PDMA_STHRSH, 0x0807);
614 cx_write(MO_PDMA_DTHRSH, 0x0807);
615
616
617 cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
618 cx_write(MO_AGC_BACK_VBI, 0x00E00555);
619
620 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF);
621 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF);
622 cx_write(MO_INT1_STAT, 0xFFFFFFFF);
623
624
625 cx_write(MO_SRST_IO, 0);
626 msleep(10);
627 cx_write(MO_SRST_IO, 1);
628
629 return 0;
630}
631
632
633
634static unsigned int inline norm_swidth(v4l2_std_id norm)
635{
636 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
637}
638
639static unsigned int inline norm_hdelay(v4l2_std_id norm)
640{
641 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
642}
643
644static unsigned int inline norm_vdelay(v4l2_std_id norm)
645{
646 return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
647}
648
649static unsigned int inline norm_fsc8(v4l2_std_id norm)
650{
651 if (norm & V4L2_STD_PAL_M)
652 return 28604892;
653
654 if (norm & (V4L2_STD_PAL_Nc))
655 return 28656448;
656
657 if (norm & V4L2_STD_NTSC)
658 return 28636360;
659
660
661
662
663
664
665
666 return 35468950;
667}
668
669static unsigned int inline norm_htotal(v4l2_std_id norm)
670{
671
672 unsigned int fsc4=norm_fsc8(norm)/2;
673
674
675 return (norm & V4L2_STD_625_50) ?
676 ((fsc4+312)/625+12)/25 :
677 ((fsc4+262)/525*1001+15000)/30000;
678}
679
680static unsigned int inline norm_vbipack(v4l2_std_id norm)
681{
682 return (norm & V4L2_STD_625_50) ? 511 : 400;
683}
684
685int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
686 enum v4l2_field field)
687{
688 unsigned int swidth = norm_swidth(core->tvnorm);
689 unsigned int sheight = norm_maxh(core->tvnorm);
690 u32 value;
691
692 dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
693 V4L2_FIELD_HAS_TOP(field) ? "T" : "",
694 V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
695 v4l2_norm_to_name(core->tvnorm));
696 if (!V4L2_FIELD_HAS_BOTH(field))
697 height *= 2;
698
699
700 value = (width * norm_hdelay(core->tvnorm)) / swidth;
701 value &= 0x3fe;
702 cx_write(MO_HDELAY_EVEN, value);
703 cx_write(MO_HDELAY_ODD, value);
704 dprintk(1,"set_scale: hdelay 0x%04x (width %d)\n", value,swidth);
705
706 value = (swidth * 4096 / width) - 4096;
707 cx_write(MO_HSCALE_EVEN, value);
708 cx_write(MO_HSCALE_ODD, value);
709 dprintk(1,"set_scale: hscale 0x%04x\n", value);
710
711 cx_write(MO_HACTIVE_EVEN, width);
712 cx_write(MO_HACTIVE_ODD, width);
713 dprintk(1,"set_scale: hactive 0x%04x\n", width);
714
715
716 cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
717 cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
718 dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
719
720 value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
721 cx_write(MO_VSCALE_EVEN, value);
722 cx_write(MO_VSCALE_ODD, value);
723 dprintk(1,"set_scale: vscale 0x%04x\n", value);
724
725 cx_write(MO_VACTIVE_EVEN, sheight);
726 cx_write(MO_VACTIVE_ODD, sheight);
727 dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
728
729
730 value = 0;
731 value |= (1 << 19);
732 if (core->tvnorm & V4L2_STD_SECAM) {
733 value |= (1 << 15);
734 value |= (1 << 16);
735 }
736 if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
737 value |= (1 << 13) | (1 << 5);
738 if (V4L2_FIELD_INTERLACED == field)
739 value |= (1 << 3);
740 if (width < 385)
741 value |= (1 << 0);
742 if (width < 193)
743 value |= (1 << 1);
744 if (nocomb)
745 value |= (3 << 5);
746
747 cx_write(MO_FILTER_EVEN, value);
748 cx_write(MO_FILTER_ODD, value);
749 dprintk(1,"set_scale: filter 0x%04x\n", value);
750
751 return 0;
752}
753
754static const u32 xtal = 28636363;
755
756static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
757{
758 static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
759 u64 pll;
760 u32 reg;
761 int i;
762
763 if (prescale < 2)
764 prescale = 2;
765 if (prescale > 5)
766 prescale = 5;
767
768 pll = ofreq * 8 * prescale * (u64)(1 << 20);
769 do_div(pll,xtal);
770 reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
771 if (((reg >> 20) & 0x3f) < 14) {
772 printk("%s/0: pll out of range\n",core->name);
773 return -1;
774 }
775
776 dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
777 reg, cx_read(MO_PLL_REG), ofreq);
778 cx_write(MO_PLL_REG, reg);
779 for (i = 0; i < 100; i++) {
780 reg = cx_read(MO_DEVICE_STATUS);
781 if (reg & (1<<2)) {
782 dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
783 prescale,ofreq);
784 return 0;
785 }
786 dprintk(1,"pll not locked yet, waiting ...\n");
787 msleep(10);
788 }
789 dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
790 return -1;
791}
792
793int cx88_start_audio_dma(struct cx88_core *core)
794{
795
796 int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
797
798
799 if (cx_read(MO_AUD_DMACNTRL) & 0x10)
800 return 0;
801
802
803 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
804 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
805
806 cx_write(MO_AUDD_LNGTH, bpl);
807 cx_write(MO_AUDR_LNGTH, bpl);
808
809
810 cx_write(MO_AUD_DMACNTRL, 0x0003);
811
812 return 0;
813}
814
815int cx88_stop_audio_dma(struct cx88_core *core)
816{
817
818 if (cx_read(MO_AUD_DMACNTRL) & 0x10)
819 return 0;
820
821
822 cx_write(MO_AUD_DMACNTRL, 0x0000);
823
824 return 0;
825}
826
827static int set_tvaudio(struct cx88_core *core)
828{
829 v4l2_std_id norm = core->tvnorm;
830
831 if (CX88_VMUX_TELEVISION != INPUT(core->input).type)
832 return 0;
833
834 if (V4L2_STD_PAL_BG & norm) {
835 core->tvaudio = WW_BG;
836
837 } else if (V4L2_STD_PAL_DK & norm) {
838 core->tvaudio = WW_DK;
839
840 } else if (V4L2_STD_PAL_I & norm) {
841 core->tvaudio = WW_I;
842
843 } else if (V4L2_STD_SECAM_L & norm) {
844 core->tvaudio = WW_L;
845
846 } else if (V4L2_STD_SECAM_DK & norm) {
847 core->tvaudio = WW_DK;
848
849 } else if ((V4L2_STD_NTSC_M & norm) ||
850 (V4L2_STD_PAL_M & norm)) {
851 core->tvaudio = WW_BTSC;
852
853 } else if (V4L2_STD_NTSC_M_JP & norm) {
854 core->tvaudio = WW_EIAJ;
855
856 } else {
857 printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
858 core->name, v4l2_norm_to_name(core->tvnorm));
859 core->tvaudio = 0;
860 return 0;
861 }
862
863 cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
864 cx88_set_tvaudio(core);
865
866
867
868
869
870
871 cx88_start_audio_dma(core);
872 return 0;
873}
874
875
876
877int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
878{
879 u32 fsc8;
880 u32 adc_clock;
881 u32 vdec_clock;
882 u32 step_db,step_dr;
883 u64 tmp64;
884 u32 bdelay,agcdelay,htotal;
885 u32 cxiformat, cxoformat;
886
887 core->tvnorm = norm;
888 fsc8 = norm_fsc8(norm);
889 adc_clock = xtal;
890 vdec_clock = fsc8;
891 step_db = fsc8;
892 step_dr = fsc8;
893
894 if (norm & V4L2_STD_NTSC_M_JP) {
895 cxiformat = VideoFormatNTSCJapan;
896 cxoformat = 0x181f0008;
897 } else if (norm & V4L2_STD_NTSC_443) {
898 cxiformat = VideoFormatNTSC443;
899 cxoformat = 0x181f0008;
900 } else if (norm & V4L2_STD_PAL_M) {
901 cxiformat = VideoFormatPALM;
902 cxoformat = 0x1c1f0008;
903 } else if (norm & V4L2_STD_PAL_N) {
904 cxiformat = VideoFormatPALN;
905 cxoformat = 0x1c1f0008;
906 } else if (norm & V4L2_STD_PAL_Nc) {
907 cxiformat = VideoFormatPALNC;
908 cxoformat = 0x1c1f0008;
909 } else if (norm & V4L2_STD_PAL_60) {
910 cxiformat = VideoFormatPAL60;
911 cxoformat = 0x181f0008;
912 } else if (norm & V4L2_STD_NTSC) {
913 cxiformat = VideoFormatNTSC;
914 cxoformat = 0x181f0008;
915 } else if (norm & V4L2_STD_SECAM) {
916 step_db = 4250000 * 8;
917 step_dr = 4406250 * 8;
918
919 cxiformat = VideoFormatSECAM;
920 cxoformat = 0x181f0008;
921 } else {
922 cxiformat = VideoFormatPAL;
923 cxoformat = 0x181f0008;
924 }
925
926 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
927 v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
928 step_db, step_dr);
929 set_pll(core,2,vdec_clock);
930
931 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
932 cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
933
934
935 cx_andor(MO_INPUT_FORMAT, 0x40f,
936 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
937
938
939 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
940 cxoformat, cx_read(MO_OUTPUT_FORMAT));
941 cx_write(MO_OUTPUT_FORMAT, cxoformat);
942
943
944 tmp64 = adc_clock * (u64)(1 << 17);
945 do_div(tmp64, vdec_clock);
946 dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
947 (u32)tmp64, cx_read(MO_SCONV_REG));
948 cx_write(MO_SCONV_REG, (u32)tmp64);
949
950
951 tmp64 = step_db * (u64)(1 << 22);
952 do_div(tmp64, vdec_clock);
953 dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
954 (u32)tmp64, cx_read(MO_SUB_STEP));
955 cx_write(MO_SUB_STEP, (u32)tmp64);
956
957
958 tmp64 = step_dr * (u64)(1 << 22);
959 do_div(tmp64, vdec_clock);
960 dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
961 (u32)tmp64, cx_read(MO_SUB_STEP_DR));
962 cx_write(MO_SUB_STEP_DR, (u32)tmp64);
963
964
965 bdelay = vdec_clock * 65 / 20000000 + 21;
966 agcdelay = vdec_clock * 68 / 20000000 + 15;
967 dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
968 (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
969 cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
970
971
972 tmp64 = norm_htotal(norm) * (u64)vdec_clock;
973 do_div(tmp64, fsc8);
974 htotal = (u32)tmp64 | (HLNotchFilter4xFsc << 11);
975 dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
976 htotal, cx_read(MO_HTOTAL), (u32)tmp64);
977 cx_write(MO_HTOTAL, htotal);
978
979
980
981 cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
982
983
984 cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
985
986
987 set_tvaudio(core);
988
989
990 cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm);
991
992
993 return 0;
994}
995
996
997
998struct video_device *cx88_vdev_init(struct cx88_core *core,
999 struct pci_dev *pci,
1000 struct video_device *template,
1001 char *type)
1002{
1003 struct video_device *vfd;
1004
1005 vfd = video_device_alloc();
1006 if (NULL == vfd)
1007 return NULL;
1008 *vfd = *template;
1009 vfd->minor = -1;
1010 vfd->parent = &pci->dev;
1011 vfd->release = video_device_release;
1012 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1013 core->name, type, core->board.name);
1014 return vfd;
1015}
1016
1017struct cx88_core* cx88_core_get(struct pci_dev *pci)
1018{
1019 struct cx88_core *core;
1020
1021 mutex_lock(&devlist);
1022 list_for_each_entry(core, &cx88_devlist, devlist) {
1023 if (pci->bus->number != core->pci_bus)
1024 continue;
1025 if (PCI_SLOT(pci->devfn) != core->pci_slot)
1026 continue;
1027
1028 if (0 != cx88_get_resources(core, pci)) {
1029 mutex_unlock(&devlist);
1030 return NULL;
1031 }
1032 atomic_inc(&core->refcount);
1033 mutex_unlock(&devlist);
1034 return core;
1035 }
1036
1037 core = cx88_core_create(pci, cx88_devcount);
1038 if (NULL != core) {
1039 cx88_devcount++;
1040 list_add_tail(&core->devlist, &cx88_devlist);
1041 }
1042
1043 mutex_unlock(&devlist);
1044 return core;
1045}
1046
1047void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1048{
1049 release_mem_region(pci_resource_start(pci,0),
1050 pci_resource_len(pci,0));
1051
1052 if (!atomic_dec_and_test(&core->refcount))
1053 return;
1054
1055 mutex_lock(&devlist);
1056 cx88_ir_fini(core);
1057 if (0 == core->i2c_rc)
1058 i2c_del_adapter(&core->i2c_adap);
1059 list_del(&core->devlist);
1060 iounmap(core->lmmio);
1061 cx88_devcount--;
1062 mutex_unlock(&devlist);
1063 kfree(core);
1064}
1065
1066
1067
1068EXPORT_SYMBOL(cx88_print_irqbits);
1069
1070EXPORT_SYMBOL(cx88_core_irq);
1071EXPORT_SYMBOL(cx88_wakeup);
1072EXPORT_SYMBOL(cx88_reset);
1073EXPORT_SYMBOL(cx88_shutdown);
1074
1075EXPORT_SYMBOL(cx88_risc_buffer);
1076EXPORT_SYMBOL(cx88_risc_databuffer);
1077EXPORT_SYMBOL(cx88_risc_stopper);
1078EXPORT_SYMBOL(cx88_free_buffer);
1079
1080EXPORT_SYMBOL(cx88_sram_channels);
1081EXPORT_SYMBOL(cx88_sram_channel_setup);
1082EXPORT_SYMBOL(cx88_sram_channel_dump);
1083
1084EXPORT_SYMBOL(cx88_set_tvnorm);
1085EXPORT_SYMBOL(cx88_set_scale);
1086
1087EXPORT_SYMBOL(cx88_vdev_init);
1088EXPORT_SYMBOL(cx88_core_get);
1089EXPORT_SYMBOL(cx88_core_put);
1090
1091EXPORT_SYMBOL(cx88_ir_start);
1092EXPORT_SYMBOL(cx88_ir_stop);
1093
1094
1095
1096
1097
1098
1099
1100