Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/cx88/cx88-core.c
17687 views
1
/*
2
*
3
* device driver for Conexant 2388x based TV cards
4
* driver core
5
*
6
* (c) 2003 Gerd Knorr <[email protected]> [SuSE Labs]
7
*
8
* (c) 2005-2006 Mauro Carvalho Chehab <[email protected]>
9
* - Multituner support
10
* - video_ioctl2 conversion
11
* - PAL/M fixes
12
*
13
* This program is free software; you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License as published by
15
* the Free Software Foundation; either version 2 of the License, or
16
* (at your option) any later version.
17
*
18
* This program is distributed in the hope that it will be useful,
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
* GNU General Public License for more details.
22
*
23
* You should have received a copy of the GNU General Public License
24
* along with this program; if not, write to the Free Software
25
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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
45
MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
46
MODULE_AUTHOR("Gerd Knorr <[email protected]> [SuSE Labs]");
47
MODULE_LICENSE("GPL");
48
49
/* ------------------------------------------------------------------ */
50
51
static unsigned int core_debug;
52
module_param(core_debug,int,0644);
53
MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
54
55
static unsigned int nicam;
56
module_param(nicam,int,0644);
57
MODULE_PARM_DESC(nicam,"tv audio is nicam");
58
59
static unsigned int nocomb;
60
module_param(nocomb,int,0644);
61
MODULE_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
66
static unsigned int cx88_devcount;
67
static LIST_HEAD(cx88_devlist);
68
static DEFINE_MUTEX(devlist);
69
70
#define NO_SYNC_LINE (-1U)
71
72
/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
73
generated _after_ lpi lines are transferred. */
74
static __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
/* sync instruction */
83
if (sync_line != NO_SYNC_LINE)
84
*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
85
86
/* scan lines */
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
/* fits into current chunk */
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
/* scanline needs to be split */
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
128
int 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
/* estimate risc mem: worst case is one write per page border +
144
one write per scan line + syncs + jump (all 2 dwords). Padding
145
can cause next bpl to start close to a page border. First DMA
146
region may be smaller than PAGE_SIZE */
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
/* write risc instructions */
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
/* save pointer to jmp instruction address */
162
risc->jmp = rp;
163
BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
164
return 0;
165
}
166
167
int 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
/* estimate risc mem: worst case is one write per page border +
176
one write per scan line + syncs + jump (all 2 dwords). Here
177
there is no padding and no sync. First DMA region may be smaller
178
than PAGE_SIZE */
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
/* write risc instructions */
185
rp = risc->cpu;
186
rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
187
188
/* save pointer to jmp instruction address */
189
risc->jmp = rp;
190
BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
191
return 0;
192
}
193
194
int 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
/* write risc instructions */
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
214
void
215
cx88_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(q, &buf->vb, 0, 0);
221
videobuf_dma_unmap(q->dev, 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
/* our SRAM memory layout */
229
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 enough FIFO space
235
* to be able to deal with insane long pci latencies ...
236
*
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
* channel 27 (audio rds)- 3.0k
245
* TOTAL = 29.0k
246
*
247
* Every channel has 160 bytes control data (64 bytes instruction
248
* queue and 6 CDT entries), which is close to 2k total.
249
*
250
* Address layout:
251
* 0x0000 - 0x03ff CMDs / reserved
252
* 0x0400 - 0x0bff instruction queues + CDs
253
* 0x0c00 - FIFOs
254
*/
255
256
const struct sram_channel const cx88_sram_channels[] = {
257
[SRAM_CH21] = {
258
.name = "video y / packed",
259
.cmds_start = 0x180040,
260
.ctrl_start = 0x180400,
261
.cdt = 0x180400 + 64,
262
.fifo_start = 0x180c00,
263
.fifo_size = 0x002800,
264
.ptr1_reg = MO_DMA21_PTR1,
265
.ptr2_reg = MO_DMA21_PTR2,
266
.cnt1_reg = MO_DMA21_CNT1,
267
.cnt2_reg = MO_DMA21_CNT2,
268
},
269
[SRAM_CH22] = {
270
.name = "video u",
271
.cmds_start = 0x180080,
272
.ctrl_start = 0x1804a0,
273
.cdt = 0x1804a0 + 64,
274
.fifo_start = 0x183400,
275
.fifo_size = 0x000800,
276
.ptr1_reg = MO_DMA22_PTR1,
277
.ptr2_reg = MO_DMA22_PTR2,
278
.cnt1_reg = MO_DMA22_CNT1,
279
.cnt2_reg = MO_DMA22_CNT2,
280
},
281
[SRAM_CH23] = {
282
.name = "video v",
283
.cmds_start = 0x1800c0,
284
.ctrl_start = 0x180540,
285
.cdt = 0x180540 + 64,
286
.fifo_start = 0x183c00,
287
.fifo_size = 0x000800,
288
.ptr1_reg = MO_DMA23_PTR1,
289
.ptr2_reg = MO_DMA23_PTR2,
290
.cnt1_reg = MO_DMA23_CNT1,
291
.cnt2_reg = MO_DMA23_CNT2,
292
},
293
[SRAM_CH24] = {
294
.name = "vbi",
295
.cmds_start = 0x180100,
296
.ctrl_start = 0x1805e0,
297
.cdt = 0x1805e0 + 64,
298
.fifo_start = 0x184400,
299
.fifo_size = 0x001000,
300
.ptr1_reg = MO_DMA24_PTR1,
301
.ptr2_reg = MO_DMA24_PTR2,
302
.cnt1_reg = MO_DMA24_CNT1,
303
.cnt2_reg = MO_DMA24_CNT2,
304
},
305
[SRAM_CH25] = {
306
.name = "audio from",
307
.cmds_start = 0x180140,
308
.ctrl_start = 0x180680,
309
.cdt = 0x180680 + 64,
310
.fifo_start = 0x185400,
311
.fifo_size = 0x001000,
312
.ptr1_reg = MO_DMA25_PTR1,
313
.ptr2_reg = MO_DMA25_PTR2,
314
.cnt1_reg = MO_DMA25_CNT1,
315
.cnt2_reg = MO_DMA25_CNT2,
316
},
317
[SRAM_CH26] = {
318
.name = "audio to",
319
.cmds_start = 0x180180,
320
.ctrl_start = 0x180720,
321
.cdt = 0x180680 + 64, /* same as audio IN */
322
.fifo_start = 0x185400, /* same as audio IN */
323
.fifo_size = 0x001000, /* same as audio IN */
324
.ptr1_reg = MO_DMA26_PTR1,
325
.ptr2_reg = MO_DMA26_PTR2,
326
.cnt1_reg = MO_DMA26_CNT1,
327
.cnt2_reg = MO_DMA26_CNT2,
328
},
329
[SRAM_CH28] = {
330
.name = "mpeg",
331
.cmds_start = 0x180200,
332
.ctrl_start = 0x1807C0,
333
.cdt = 0x1807C0 + 64,
334
.fifo_start = 0x186400,
335
.fifo_size = 0x001000,
336
.ptr1_reg = MO_DMA28_PTR1,
337
.ptr2_reg = MO_DMA28_PTR2,
338
.cnt1_reg = MO_DMA28_CNT1,
339
.cnt2_reg = MO_DMA28_CNT2,
340
},
341
[SRAM_CH27] = {
342
.name = "audio rds",
343
.cmds_start = 0x1801C0,
344
.ctrl_start = 0x180860,
345
.cdt = 0x180860 + 64,
346
.fifo_start = 0x187400,
347
.fifo_size = 0x000C00,
348
.ptr1_reg = MO_DMA27_PTR1,
349
.ptr2_reg = MO_DMA27_PTR2,
350
.cnt1_reg = MO_DMA27_CNT1,
351
.cnt2_reg = MO_DMA27_CNT2,
352
},
353
};
354
355
int cx88_sram_channel_setup(struct cx88_core *core,
356
const struct sram_channel *ch,
357
unsigned int bpl, u32 risc)
358
{
359
unsigned int i,lines;
360
u32 cdt;
361
362
bpl = (bpl + 7) & ~7; /* alignment */
363
cdt = ch->cdt;
364
lines = ch->fifo_size / bpl;
365
if (lines > 6)
366
lines = 6;
367
BUG_ON(lines < 2);
368
369
/* write CDT */
370
for (i = 0; i < lines; i++)
371
cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
372
373
/* write CMDS */
374
cx_write(ch->cmds_start + 0, risc);
375
cx_write(ch->cmds_start + 4, cdt);
376
cx_write(ch->cmds_start + 8, (lines*16) >> 3);
377
cx_write(ch->cmds_start + 12, ch->ctrl_start);
378
cx_write(ch->cmds_start + 16, 64 >> 2);
379
for (i = 20; i < 64; i += 4)
380
cx_write(ch->cmds_start + i, 0);
381
382
/* fill registers */
383
cx_write(ch->ptr1_reg, ch->fifo_start);
384
cx_write(ch->ptr2_reg, cdt);
385
cx_write(ch->cnt1_reg, (bpl >> 3) -1);
386
cx_write(ch->cnt2_reg, (lines*16) >> 3);
387
388
dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
389
return 0;
390
}
391
392
/* ------------------------------------------------------------------ */
393
/* debug helper code */
394
395
static int cx88_risc_decode(u32 risc)
396
{
397
static const char * const instr[16] = {
398
[ RISC_SYNC >> 28 ] = "sync",
399
[ RISC_WRITE >> 28 ] = "write",
400
[ RISC_WRITEC >> 28 ] = "writec",
401
[ RISC_READ >> 28 ] = "read",
402
[ RISC_READC >> 28 ] = "readc",
403
[ RISC_JUMP >> 28 ] = "jump",
404
[ RISC_SKIP >> 28 ] = "skip",
405
[ RISC_WRITERM >> 28 ] = "writerm",
406
[ RISC_WRITECM >> 28 ] = "writecm",
407
[ RISC_WRITECR >> 28 ] = "writecr",
408
};
409
static int const incr[16] = {
410
[ RISC_WRITE >> 28 ] = 2,
411
[ RISC_JUMP >> 28 ] = 2,
412
[ RISC_WRITERM >> 28 ] = 3,
413
[ RISC_WRITECM >> 28 ] = 3,
414
[ RISC_WRITECR >> 28 ] = 4,
415
};
416
static const char * const bits[] = {
417
"12", "13", "14", "resync",
418
"cnt0", "cnt1", "18", "19",
419
"20", "21", "22", "23",
420
"irq1", "irq2", "eol", "sol",
421
};
422
int i;
423
424
printk("0x%08x [ %s", risc,
425
instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
426
for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
427
if (risc & (1 << (i + 12)))
428
printk(" %s",bits[i]);
429
printk(" count=%d ]\n", risc & 0xfff);
430
return incr[risc >> 28] ? incr[risc >> 28] : 1;
431
}
432
433
434
void cx88_sram_channel_dump(struct cx88_core *core,
435
const struct sram_channel *ch)
436
{
437
static const char * const name[] = {
438
"initial risc",
439
"cdt base",
440
"cdt size",
441
"iq base",
442
"iq size",
443
"risc pc",
444
"iq wr ptr",
445
"iq rd ptr",
446
"cdt current",
447
"pci target",
448
"line / byte",
449
};
450
u32 risc;
451
unsigned int i,j,n;
452
453
printk("%s: %s - dma channel status dump\n",
454
core->name,ch->name);
455
for (i = 0; i < ARRAY_SIZE(name); i++)
456
printk("%s: cmds: %-12s: 0x%08x\n",
457
core->name,name[i],
458
cx_read(ch->cmds_start + 4*i));
459
for (n = 1, i = 0; i < 4; i++) {
460
risc = cx_read(ch->cmds_start + 4 * (i+11));
461
printk("%s: risc%d: ", core->name, i);
462
if (--n)
463
printk("0x%08x [ arg #%d ]\n", risc, n);
464
else
465
n = cx88_risc_decode(risc);
466
}
467
for (i = 0; i < 16; i += n) {
468
risc = cx_read(ch->ctrl_start + 4 * i);
469
printk("%s: iq %x: ", core->name, i);
470
n = cx88_risc_decode(risc);
471
for (j = 1; j < n; j++) {
472
risc = cx_read(ch->ctrl_start + 4 * (i+j));
473
printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
474
core->name, i+j, risc, j);
475
}
476
}
477
478
printk("%s: fifo: 0x%08x -> 0x%x\n",
479
core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
480
printk("%s: ctrl: 0x%08x -> 0x%x\n",
481
core->name, ch->ctrl_start, ch->ctrl_start+6*16);
482
printk("%s: ptr1_reg: 0x%08x\n",
483
core->name,cx_read(ch->ptr1_reg));
484
printk("%s: ptr2_reg: 0x%08x\n",
485
core->name,cx_read(ch->ptr2_reg));
486
printk("%s: cnt1_reg: 0x%08x\n",
487
core->name,cx_read(ch->cnt1_reg));
488
printk("%s: cnt2_reg: 0x%08x\n",
489
core->name,cx_read(ch->cnt2_reg));
490
}
491
492
static const char *cx88_pci_irqs[32] = {
493
"vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
494
"src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
495
"brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
496
"i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
497
};
498
499
void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
500
int len, u32 bits, u32 mask)
501
{
502
unsigned int i;
503
504
printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
505
for (i = 0; i < len; i++) {
506
if (!(bits & (1 << i)))
507
continue;
508
if (strings[i])
509
printk(" %s", strings[i]);
510
else
511
printk(" %d", i);
512
if (!(mask & (1 << i)))
513
continue;
514
printk("*");
515
}
516
printk("\n");
517
}
518
519
/* ------------------------------------------------------------------ */
520
521
int cx88_core_irq(struct cx88_core *core, u32 status)
522
{
523
int handled = 0;
524
525
if (status & PCI_INT_IR_SMPINT) {
526
cx88_ir_irq(core);
527
handled++;
528
}
529
if (!handled)
530
cx88_print_irqbits(core->name, "irq pci",
531
cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
532
status, core->pci_irqmask);
533
return handled;
534
}
535
536
void cx88_wakeup(struct cx88_core *core,
537
struct cx88_dmaqueue *q, u32 count)
538
{
539
struct cx88_buffer *buf;
540
int bc;
541
542
for (bc = 0;; bc++) {
543
if (list_empty(&q->active))
544
break;
545
buf = list_entry(q->active.next,
546
struct cx88_buffer, vb.queue);
547
/* count comes from the hw and is is 16bit wide --
548
* this trick handles wrap-arounds correctly for
549
* up to 32767 buffers in flight... */
550
if ((s16) (count - buf->count) < 0)
551
break;
552
do_gettimeofday(&buf->vb.ts);
553
dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
554
count, buf->count);
555
buf->vb.state = VIDEOBUF_DONE;
556
list_del(&buf->vb.queue);
557
wake_up(&buf->vb.done);
558
}
559
if (list_empty(&q->active)) {
560
del_timer(&q->timeout);
561
} else {
562
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
563
}
564
if (bc != 1)
565
dprintk(2, "%s: %d buffers handled (should be 1)\n",
566
__func__, bc);
567
}
568
569
void cx88_shutdown(struct cx88_core *core)
570
{
571
/* disable RISC controller + IRQs */
572
cx_write(MO_DEV_CNTRL2, 0);
573
574
/* stop dma transfers */
575
cx_write(MO_VID_DMACNTRL, 0x0);
576
cx_write(MO_AUD_DMACNTRL, 0x0);
577
cx_write(MO_TS_DMACNTRL, 0x0);
578
cx_write(MO_VIP_DMACNTRL, 0x0);
579
cx_write(MO_GPHST_DMACNTRL, 0x0);
580
581
/* stop interrupts */
582
cx_write(MO_PCI_INTMSK, 0x0);
583
cx_write(MO_VID_INTMSK, 0x0);
584
cx_write(MO_AUD_INTMSK, 0x0);
585
cx_write(MO_TS_INTMSK, 0x0);
586
cx_write(MO_VIP_INTMSK, 0x0);
587
cx_write(MO_GPHST_INTMSK, 0x0);
588
589
/* stop capturing */
590
cx_write(VID_CAPTURE_CONTROL, 0);
591
}
592
593
int cx88_reset(struct cx88_core *core)
594
{
595
dprintk(1,"%s\n",__func__);
596
cx88_shutdown(core);
597
598
/* clear irq status */
599
cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
600
cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
601
cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
602
603
/* wait a bit */
604
msleep(100);
605
606
/* init sram */
607
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
608
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
609
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
610
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
611
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
612
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
613
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
614
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
615
616
/* misc init ... */
617
cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
618
(1 << 12) | // agc gain
619
(1 << 11) | // adaptibe agc
620
(0 << 10) | // chroma agc
621
(0 << 9) | // ckillen
622
(7)));
623
624
/* setup image format */
625
cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
626
627
/* setup FIFO Thresholds */
628
cx_write(MO_PDMA_STHRSH, 0x0807);
629
cx_write(MO_PDMA_DTHRSH, 0x0807);
630
631
/* fixes flashing of image */
632
cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
633
cx_write(MO_AGC_BACK_VBI, 0x00E00555);
634
635
cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
636
cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
637
cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
638
639
/* Reset on-board parts */
640
cx_write(MO_SRST_IO, 0);
641
msleep(10);
642
cx_write(MO_SRST_IO, 1);
643
644
return 0;
645
}
646
647
/* ------------------------------------------------------------------ */
648
649
static unsigned int inline norm_swidth(v4l2_std_id norm)
650
{
651
return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
652
}
653
654
static unsigned int inline norm_hdelay(v4l2_std_id norm)
655
{
656
return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
657
}
658
659
static unsigned int inline norm_vdelay(v4l2_std_id norm)
660
{
661
return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
662
}
663
664
static unsigned int inline norm_fsc8(v4l2_std_id norm)
665
{
666
if (norm & V4L2_STD_PAL_M)
667
return 28604892; // 3.575611 MHz
668
669
if (norm & (V4L2_STD_PAL_Nc))
670
return 28656448; // 3.582056 MHz
671
672
if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
673
return 28636360; // 3.57954545 MHz +/- 10 Hz
674
675
/* SECAM have also different sub carrier for chroma,
676
but step_db and step_dr, at cx88_set_tvnorm already handles that.
677
678
The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
679
*/
680
681
return 35468950; // 4.43361875 MHz +/- 5 Hz
682
}
683
684
static unsigned int inline norm_htotal(v4l2_std_id norm)
685
{
686
687
unsigned int fsc4=norm_fsc8(norm)/2;
688
689
/* returns 4*FSC / vtotal / frames per seconds */
690
return (norm & V4L2_STD_625_50) ?
691
((fsc4+312)/625+12)/25 :
692
((fsc4+262)/525*1001+15000)/30000;
693
}
694
695
static unsigned int inline norm_vbipack(v4l2_std_id norm)
696
{
697
return (norm & V4L2_STD_625_50) ? 511 : 400;
698
}
699
700
int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
701
enum v4l2_field field)
702
{
703
unsigned int swidth = norm_swidth(core->tvnorm);
704
unsigned int sheight = norm_maxh(core->tvnorm);
705
u32 value;
706
707
dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
708
V4L2_FIELD_HAS_TOP(field) ? "T" : "",
709
V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
710
v4l2_norm_to_name(core->tvnorm));
711
if (!V4L2_FIELD_HAS_BOTH(field))
712
height *= 2;
713
714
// recalc H delay and scale registers
715
value = (width * norm_hdelay(core->tvnorm)) / swidth;
716
value &= 0x3fe;
717
cx_write(MO_HDELAY_EVEN, value);
718
cx_write(MO_HDELAY_ODD, value);
719
dprintk(1,"set_scale: hdelay 0x%04x (width %d)\n", value,swidth);
720
721
value = (swidth * 4096 / width) - 4096;
722
cx_write(MO_HSCALE_EVEN, value);
723
cx_write(MO_HSCALE_ODD, value);
724
dprintk(1,"set_scale: hscale 0x%04x\n", value);
725
726
cx_write(MO_HACTIVE_EVEN, width);
727
cx_write(MO_HACTIVE_ODD, width);
728
dprintk(1,"set_scale: hactive 0x%04x\n", width);
729
730
// recalc V scale Register (delay is constant)
731
cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
732
cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
733
dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
734
735
value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
736
cx_write(MO_VSCALE_EVEN, value);
737
cx_write(MO_VSCALE_ODD, value);
738
dprintk(1,"set_scale: vscale 0x%04x\n", value);
739
740
cx_write(MO_VACTIVE_EVEN, sheight);
741
cx_write(MO_VACTIVE_ODD, sheight);
742
dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
743
744
// setup filters
745
value = 0;
746
value |= (1 << 19); // CFILT (default)
747
if (core->tvnorm & V4L2_STD_SECAM) {
748
value |= (1 << 15);
749
value |= (1 << 16);
750
}
751
if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
752
value |= (1 << 13) | (1 << 5);
753
if (V4L2_FIELD_INTERLACED == field)
754
value |= (1 << 3); // VINT (interlaced vertical scaling)
755
if (width < 385)
756
value |= (1 << 0); // 3-tap interpolation
757
if (width < 193)
758
value |= (1 << 1); // 5-tap interpolation
759
if (nocomb)
760
value |= (3 << 5); // disable comb filter
761
762
cx_write(MO_FILTER_EVEN, value);
763
cx_write(MO_FILTER_ODD, value);
764
dprintk(1,"set_scale: filter 0x%04x\n", value);
765
766
return 0;
767
}
768
769
static const u32 xtal = 28636363;
770
771
static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
772
{
773
static const u32 pre[] = { 0, 0, 0, 3, 2, 1 };
774
u64 pll;
775
u32 reg;
776
int i;
777
778
if (prescale < 2)
779
prescale = 2;
780
if (prescale > 5)
781
prescale = 5;
782
783
pll = ofreq * 8 * prescale * (u64)(1 << 20);
784
do_div(pll,xtal);
785
reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
786
if (((reg >> 20) & 0x3f) < 14) {
787
printk("%s/0: pll out of range\n",core->name);
788
return -1;
789
}
790
791
dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
792
reg, cx_read(MO_PLL_REG), ofreq);
793
cx_write(MO_PLL_REG, reg);
794
for (i = 0; i < 100; i++) {
795
reg = cx_read(MO_DEVICE_STATUS);
796
if (reg & (1<<2)) {
797
dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
798
prescale,ofreq);
799
return 0;
800
}
801
dprintk(1,"pll not locked yet, waiting ...\n");
802
msleep(10);
803
}
804
dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
805
return -1;
806
}
807
808
int cx88_start_audio_dma(struct cx88_core *core)
809
{
810
/* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
811
int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
812
813
int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
814
815
/* If downstream RISC is enabled, bail out; ALSA is managing DMA */
816
if (cx_read(MO_AUD_DMACNTRL) & 0x10)
817
return 0;
818
819
/* setup fifo + format */
820
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
821
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
822
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
823
rds_bpl, 0);
824
825
cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
826
cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
827
828
/* enable Up, Down and Audio RDS fifo */
829
cx_write(MO_AUD_DMACNTRL, 0x0007);
830
831
return 0;
832
}
833
834
int cx88_stop_audio_dma(struct cx88_core *core)
835
{
836
/* If downstream RISC is enabled, bail out; ALSA is managing DMA */
837
if (cx_read(MO_AUD_DMACNTRL) & 0x10)
838
return 0;
839
840
/* stop dma */
841
cx_write(MO_AUD_DMACNTRL, 0x0000);
842
843
return 0;
844
}
845
846
static int set_tvaudio(struct cx88_core *core)
847
{
848
v4l2_std_id norm = core->tvnorm;
849
850
if (CX88_VMUX_TELEVISION != INPUT(core->input).type &&
851
CX88_VMUX_CABLE != INPUT(core->input).type)
852
return 0;
853
854
if (V4L2_STD_PAL_BG & norm) {
855
core->tvaudio = WW_BG;
856
857
} else if (V4L2_STD_PAL_DK & norm) {
858
core->tvaudio = WW_DK;
859
860
} else if (V4L2_STD_PAL_I & norm) {
861
core->tvaudio = WW_I;
862
863
} else if (V4L2_STD_SECAM_L & norm) {
864
core->tvaudio = WW_L;
865
866
} else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
867
core->tvaudio = WW_BG;
868
869
} else if (V4L2_STD_SECAM_DK & norm) {
870
core->tvaudio = WW_DK;
871
872
} else if ((V4L2_STD_NTSC_M & norm) ||
873
(V4L2_STD_PAL_M & norm)) {
874
core->tvaudio = WW_BTSC;
875
876
} else if (V4L2_STD_NTSC_M_JP & norm) {
877
core->tvaudio = WW_EIAJ;
878
879
} else {
880
printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
881
core->name, v4l2_norm_to_name(core->tvnorm));
882
core->tvaudio = WW_NONE;
883
return 0;
884
}
885
886
cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
887
cx88_set_tvaudio(core);
888
/* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
889
890
/*
891
This should be needed only on cx88-alsa. It seems that some cx88 chips have
892
bugs and does require DMA enabled for it to work.
893
*/
894
cx88_start_audio_dma(core);
895
return 0;
896
}
897
898
899
900
int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
901
{
902
u32 fsc8;
903
u32 adc_clock;
904
u32 vdec_clock;
905
u32 step_db,step_dr;
906
u64 tmp64;
907
u32 bdelay,agcdelay,htotal;
908
u32 cxiformat, cxoformat;
909
910
core->tvnorm = norm;
911
fsc8 = norm_fsc8(norm);
912
adc_clock = xtal;
913
vdec_clock = fsc8;
914
step_db = fsc8;
915
step_dr = fsc8;
916
917
if (norm & V4L2_STD_NTSC_M_JP) {
918
cxiformat = VideoFormatNTSCJapan;
919
cxoformat = 0x181f0008;
920
} else if (norm & V4L2_STD_NTSC_443) {
921
cxiformat = VideoFormatNTSC443;
922
cxoformat = 0x181f0008;
923
} else if (norm & V4L2_STD_PAL_M) {
924
cxiformat = VideoFormatPALM;
925
cxoformat = 0x1c1f0008;
926
} else if (norm & V4L2_STD_PAL_N) {
927
cxiformat = VideoFormatPALN;
928
cxoformat = 0x1c1f0008;
929
} else if (norm & V4L2_STD_PAL_Nc) {
930
cxiformat = VideoFormatPALNC;
931
cxoformat = 0x1c1f0008;
932
} else if (norm & V4L2_STD_PAL_60) {
933
cxiformat = VideoFormatPAL60;
934
cxoformat = 0x181f0008;
935
} else if (norm & V4L2_STD_NTSC) {
936
cxiformat = VideoFormatNTSC;
937
cxoformat = 0x181f0008;
938
} else if (norm & V4L2_STD_SECAM) {
939
step_db = 4250000 * 8;
940
step_dr = 4406250 * 8;
941
942
cxiformat = VideoFormatSECAM;
943
cxoformat = 0x181f0008;
944
} else { /* PAL */
945
cxiformat = VideoFormatPAL;
946
cxoformat = 0x181f0008;
947
}
948
949
dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
950
v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
951
step_db, step_dr);
952
set_pll(core,2,vdec_clock);
953
954
dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
955
cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
956
/* Chroma AGC must be disabled if SECAM is used, we enable it
957
by default on PAL and NTSC */
958
cx_andor(MO_INPUT_FORMAT, 0x40f,
959
norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
960
961
// FIXME: as-is from DScaler
962
dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
963
cxoformat, cx_read(MO_OUTPUT_FORMAT));
964
cx_write(MO_OUTPUT_FORMAT, cxoformat);
965
966
// MO_SCONV_REG = adc clock / video dec clock * 2^17
967
tmp64 = adc_clock * (u64)(1 << 17);
968
do_div(tmp64, vdec_clock);
969
dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
970
(u32)tmp64, cx_read(MO_SCONV_REG));
971
cx_write(MO_SCONV_REG, (u32)tmp64);
972
973
// MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
974
tmp64 = step_db * (u64)(1 << 22);
975
do_div(tmp64, vdec_clock);
976
dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
977
(u32)tmp64, cx_read(MO_SUB_STEP));
978
cx_write(MO_SUB_STEP, (u32)tmp64);
979
980
// MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
981
tmp64 = step_dr * (u64)(1 << 22);
982
do_div(tmp64, vdec_clock);
983
dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
984
(u32)tmp64, cx_read(MO_SUB_STEP_DR));
985
cx_write(MO_SUB_STEP_DR, (u32)tmp64);
986
987
// bdelay + agcdelay
988
bdelay = vdec_clock * 65 / 20000000 + 21;
989
agcdelay = vdec_clock * 68 / 20000000 + 15;
990
dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
991
(bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
992
cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
993
994
// htotal
995
tmp64 = norm_htotal(norm) * (u64)vdec_clock;
996
do_div(tmp64, fsc8);
997
htotal = (u32)tmp64 | (HLNotchFilter4xFsc << 11);
998
dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
999
htotal, cx_read(MO_HTOTAL), (u32)tmp64);
1000
cx_write(MO_HTOTAL, htotal);
1001
1002
// vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
1003
// the effective vbi offset ~244 samples, the same as the Bt8x8
1004
cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
1005
1006
// this is needed as well to set all tvnorm parameter
1007
cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
1008
1009
// audio
1010
set_tvaudio(core);
1011
1012
// tell i2c chips
1013
call_all(core, core, s_std, norm);
1014
1015
// done
1016
return 0;
1017
}
1018
1019
/* ------------------------------------------------------------------ */
1020
1021
struct video_device *cx88_vdev_init(struct cx88_core *core,
1022
struct pci_dev *pci,
1023
const struct video_device *template_,
1024
const char *type)
1025
{
1026
struct video_device *vfd;
1027
1028
vfd = video_device_alloc();
1029
if (NULL == vfd)
1030
return NULL;
1031
*vfd = *template_;
1032
vfd->v4l2_dev = &core->v4l2_dev;
1033
vfd->parent = &pci->dev;
1034
vfd->release = video_device_release;
1035
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1036
core->name, type, core->board.name);
1037
return vfd;
1038
}
1039
1040
struct cx88_core* cx88_core_get(struct pci_dev *pci)
1041
{
1042
struct cx88_core *core;
1043
1044
mutex_lock(&devlist);
1045
list_for_each_entry(core, &cx88_devlist, devlist) {
1046
if (pci->bus->number != core->pci_bus)
1047
continue;
1048
if (PCI_SLOT(pci->devfn) != core->pci_slot)
1049
continue;
1050
1051
if (0 != cx88_get_resources(core, pci)) {
1052
mutex_unlock(&devlist);
1053
return NULL;
1054
}
1055
atomic_inc(&core->refcount);
1056
mutex_unlock(&devlist);
1057
return core;
1058
}
1059
1060
core = cx88_core_create(pci, cx88_devcount);
1061
if (NULL != core) {
1062
cx88_devcount++;
1063
list_add_tail(&core->devlist, &cx88_devlist);
1064
}
1065
1066
mutex_unlock(&devlist);
1067
return core;
1068
}
1069
1070
void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1071
{
1072
release_mem_region(pci_resource_start(pci,0),
1073
pci_resource_len(pci,0));
1074
1075
if (!atomic_dec_and_test(&core->refcount))
1076
return;
1077
1078
mutex_lock(&devlist);
1079
cx88_ir_fini(core);
1080
if (0 == core->i2c_rc) {
1081
if (core->i2c_rtc)
1082
i2c_unregister_device(core->i2c_rtc);
1083
i2c_del_adapter(&core->i2c_adap);
1084
}
1085
list_del(&core->devlist);
1086
iounmap(core->lmmio);
1087
cx88_devcount--;
1088
mutex_unlock(&devlist);
1089
v4l2_device_unregister(&core->v4l2_dev);
1090
kfree(core);
1091
}
1092
1093
/* ------------------------------------------------------------------ */
1094
1095
EXPORT_SYMBOL(cx88_print_irqbits);
1096
1097
EXPORT_SYMBOL(cx88_core_irq);
1098
EXPORT_SYMBOL(cx88_wakeup);
1099
EXPORT_SYMBOL(cx88_reset);
1100
EXPORT_SYMBOL(cx88_shutdown);
1101
1102
EXPORT_SYMBOL(cx88_risc_buffer);
1103
EXPORT_SYMBOL(cx88_risc_databuffer);
1104
EXPORT_SYMBOL(cx88_risc_stopper);
1105
EXPORT_SYMBOL(cx88_free_buffer);
1106
1107
EXPORT_SYMBOL(cx88_sram_channels);
1108
EXPORT_SYMBOL(cx88_sram_channel_setup);
1109
EXPORT_SYMBOL(cx88_sram_channel_dump);
1110
1111
EXPORT_SYMBOL(cx88_set_tvnorm);
1112
EXPORT_SYMBOL(cx88_set_scale);
1113
1114
EXPORT_SYMBOL(cx88_vdev_init);
1115
EXPORT_SYMBOL(cx88_core_get);
1116
EXPORT_SYMBOL(cx88_core_put);
1117
1118
EXPORT_SYMBOL(cx88_ir_start);
1119
EXPORT_SYMBOL(cx88_ir_stop);
1120
1121
/*
1122
* Local variables:
1123
* c-basic-offset: 8
1124
* End:
1125
* 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
1126
*/
1127
1128