[media] cx88: drop cx88_free_buffer
[deliverable/linux.git] / drivers / media / pci / cx88 / cx88-core.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 *
3 * device driver for Conexant 2388x based TV cards
4 * driver core
5 *
6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7 *
8d87cb9f
MCC
8 * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
9 * - Multituner support
10 * - video_ioctl2 conversion
11 * - PAL/M fixes
12 *
1da177e4
LT
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>
1da177e4
LT
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>
98f30ed0 38#include <linux/videodev2.h>
1e4baed3 39#include <linux/mutex.h>
1da177e4
LT
40
41#include "cx88.h"
5e453dc7 42#include <media/v4l2-common.h>
35ea11ff 43#include <media/v4l2-ioctl.h>
1da177e4
LT
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
02615ed5
MCC
51unsigned int cx88_core_debug;
52module_param_named(core_debug, cx88_core_debug, int, 0644);
53MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
1da177e4 54
ff699e6b 55static unsigned int nicam;
1da177e4
LT
56module_param(nicam,int,0644);
57MODULE_PARM_DESC(nicam,"tv audio is nicam");
58
ff699e6b 59static unsigned int nocomb;
1da177e4
LT
60module_param(nocomb,int,0644);
61MODULE_PARM_DESC(nocomb,"disable comb filter");
62
02615ed5
MCC
63#define dprintk(level,fmt, arg...) do { \
64 if (cx88_core_debug >= level) \
65 printk(KERN_DEBUG "%s: " fmt, core->name , ## arg); \
66 } while(0)
1da177e4
LT
67
68static unsigned int cx88_devcount;
69static LIST_HEAD(cx88_devlist);
1e4baed3 70static DEFINE_MUTEX(devlist);
1da177e4 71
1da177e4
LT
72#define NO_SYNC_LINE (-1U)
73
05b27233
TP
74/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
75 generated _after_ lpi lines are transferred. */
d8eaa58b 76static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
1da177e4
LT
77 unsigned int offset, u32 sync_line,
78 unsigned int bpl, unsigned int padding,
0b6b6302 79 unsigned int lines, unsigned int lpi, bool jump)
1da177e4
LT
80{
81 struct scatterlist *sg;
05b27233 82 unsigned int line,todo,sol;
1da177e4 83
0b6b6302
HV
84 if (jump) {
85 (*rp++) = cpu_to_le32(RISC_JUMP);
86 (*rp++) = 0;
87 }
88
1da177e4
LT
89 /* sync instruction */
90 if (sync_line != NO_SYNC_LINE)
91 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
92
93 /* scan lines */
94 sg = sglist;
95 for (line = 0; line < lines; line++) {
96 while (offset && offset >= sg_dma_len(sg)) {
97 offset -= sg_dma_len(sg);
98 sg++;
99 }
05b27233
TP
100 if (lpi && line>0 && !(line % lpi))
101 sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
102 else
103 sol = RISC_SOL;
1da177e4
LT
104 if (bpl <= sg_dma_len(sg)-offset) {
105 /* fits into current chunk */
05b27233 106 *(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
4ac97914
MCC
107 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
108 offset+=bpl;
1da177e4 109 } else {
d1009bd7 110 /* scanline needs to be split */
4ac97914 111 todo = bpl;
05b27233 112 *(rp++)=cpu_to_le32(RISC_WRITE|sol|
1da177e4 113 (sg_dma_len(sg)-offset));
4ac97914
MCC
114 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
115 todo -= (sg_dma_len(sg)-offset);
116 offset = 0;
117 sg++;
118 while (todo > sg_dma_len(sg)) {
f2421ca3 119 *(rp++)=cpu_to_le32(RISC_WRITE|
1da177e4 120 sg_dma_len(sg));
f2421ca3 121 *(rp++)=cpu_to_le32(sg_dma_address(sg));
1da177e4
LT
122 todo -= sg_dma_len(sg);
123 sg++;
124 }
4ac97914 125 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
1da177e4
LT
126 *(rp++)=cpu_to_le32(sg_dma_address(sg));
127 offset += todo;
128 }
129 offset += padding;
130 }
131
132 return rp;
133}
134
135int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
136 struct scatterlist *sglist,
137 unsigned int top_offset, unsigned int bottom_offset,
138 unsigned int bpl, unsigned int padding, unsigned int lines)
139{
140 u32 instructions,fields;
d8eaa58b 141 __le32 *rp;
1da177e4
LT
142 int rc;
143
144 fields = 0;
145 if (UNSET != top_offset)
146 fields++;
147 if (UNSET != bottom_offset)
148 fields++;
149
150 /* estimate risc mem: worst case is one write per page border +
bba3ad76
DS
151 one write per scan line + syncs + jump (all 2 dwords). Padding
152 can cause next bpl to start close to a page border. First DMA
153 region may be smaller than PAGE_SIZE */
154 instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
0b6b6302 155 instructions += 4;
1da177e4
LT
156 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
157 return rc;
158
159 /* write risc instructions */
160 rp = risc->cpu;
161 if (UNSET != top_offset)
162 rp = cx88_risc_field(rp, sglist, top_offset, 0,
0b6b6302 163 bpl, padding, lines, 0, true);
1da177e4
LT
164 if (UNSET != bottom_offset)
165 rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
0b6b6302 166 bpl, padding, lines, 0, top_offset == UNSET);
1da177e4
LT
167
168 /* save pointer to jmp instruction address */
169 risc->jmp = rp;
4a287cfe 170 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
1da177e4
LT
171 return 0;
172}
173
174int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
175 struct scatterlist *sglist, unsigned int bpl,
05b27233 176 unsigned int lines, unsigned int lpi)
1da177e4
LT
177{
178 u32 instructions;
d8eaa58b 179 __le32 *rp;
1da177e4
LT
180 int rc;
181
182 /* estimate risc mem: worst case is one write per page border +
bba3ad76
DS
183 one write per scan line + syncs + jump (all 2 dwords). Here
184 there is no padding and no sync. First DMA region may be smaller
185 than PAGE_SIZE */
186 instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
0b6b6302 187 instructions += 3;
1da177e4
LT
188 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
189 return rc;
190
191 /* write risc instructions */
192 rp = risc->cpu;
0b6b6302 193 rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi, !lpi);
1da177e4
LT
194
195 /* save pointer to jmp instruction address */
196 risc->jmp = rp;
4a287cfe 197 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
1da177e4
LT
198 return 0;
199}
200
1da177e4
LT
201/* ------------------------------------------------------------------ */
202/* our SRAM memory layout */
203
204/* we are going to put all thr risc programs into host memory, so we
205 * can use the whole SDRAM for the DMA fifos. To simplify things, we
206 * use a static memory layout. That surely will waste memory in case
207 * we don't use all DMA channels at the same time (which will be the
e878cf3a 208 * case most of the time). But that still gives us enough FIFO space
1da177e4
LT
209 * to be able to deal with insane long pci latencies ...
210 *
211 * FIFO space allocations:
212 * channel 21 (y video) - 10.0k
213 * channel 22 (u video) - 2.0k
214 * channel 23 (v video) - 2.0k
215 * channel 24 (vbi) - 4.0k
b7f355d2 216 * channels 25+26 (audio) - 4.0k
1da177e4 217 * channel 28 (mpeg) - 4.0k
e878cf3a 218 * channel 27 (audio rds)- 3.0k
b7f355d2 219 * TOTAL = 29.0k
1da177e4
LT
220 *
221 * Every channel has 160 bytes control data (64 bytes instruction
222 * queue and 6 CDT entries), which is close to 2k total.
223 *
224 * Address layout:
225 * 0x0000 - 0x03ff CMDs / reserved
226 * 0x0400 - 0x0bff instruction queues + CDs
227 * 0x0c00 - FIFOs
228 */
229
d9bc8510 230const struct sram_channel cx88_sram_channels[] = {
1da177e4
LT
231 [SRAM_CH21] = {
232 .name = "video y / packed",
233 .cmds_start = 0x180040,
234 .ctrl_start = 0x180400,
4ac97914 235 .cdt = 0x180400 + 64,
1da177e4
LT
236 .fifo_start = 0x180c00,
237 .fifo_size = 0x002800,
238 .ptr1_reg = MO_DMA21_PTR1,
239 .ptr2_reg = MO_DMA21_PTR2,
240 .cnt1_reg = MO_DMA21_CNT1,
241 .cnt2_reg = MO_DMA21_CNT2,
242 },
243 [SRAM_CH22] = {
244 .name = "video u",
245 .cmds_start = 0x180080,
246 .ctrl_start = 0x1804a0,
4ac97914 247 .cdt = 0x1804a0 + 64,
1da177e4
LT
248 .fifo_start = 0x183400,
249 .fifo_size = 0x000800,
250 .ptr1_reg = MO_DMA22_PTR1,
251 .ptr2_reg = MO_DMA22_PTR2,
252 .cnt1_reg = MO_DMA22_CNT1,
253 .cnt2_reg = MO_DMA22_CNT2,
254 },
255 [SRAM_CH23] = {
256 .name = "video v",
257 .cmds_start = 0x1800c0,
258 .ctrl_start = 0x180540,
4ac97914 259 .cdt = 0x180540 + 64,
1da177e4
LT
260 .fifo_start = 0x183c00,
261 .fifo_size = 0x000800,
262 .ptr1_reg = MO_DMA23_PTR1,
263 .ptr2_reg = MO_DMA23_PTR2,
264 .cnt1_reg = MO_DMA23_CNT1,
265 .cnt2_reg = MO_DMA23_CNT2,
266 },
267 [SRAM_CH24] = {
268 .name = "vbi",
269 .cmds_start = 0x180100,
270 .ctrl_start = 0x1805e0,
4ac97914 271 .cdt = 0x1805e0 + 64,
1da177e4
LT
272 .fifo_start = 0x184400,
273 .fifo_size = 0x001000,
274 .ptr1_reg = MO_DMA24_PTR1,
275 .ptr2_reg = MO_DMA24_PTR2,
276 .cnt1_reg = MO_DMA24_CNT1,
277 .cnt2_reg = MO_DMA24_CNT2,
278 },
279 [SRAM_CH25] = {
280 .name = "audio from",
281 .cmds_start = 0x180140,
282 .ctrl_start = 0x180680,
4ac97914 283 .cdt = 0x180680 + 64,
1da177e4 284 .fifo_start = 0x185400,
b7f355d2 285 .fifo_size = 0x001000,
1da177e4
LT
286 .ptr1_reg = MO_DMA25_PTR1,
287 .ptr2_reg = MO_DMA25_PTR2,
288 .cnt1_reg = MO_DMA25_CNT1,
289 .cnt2_reg = MO_DMA25_CNT2,
290 },
291 [SRAM_CH26] = {
292 .name = "audio to",
293 .cmds_start = 0x180180,
294 .ctrl_start = 0x180720,
4ac97914 295 .cdt = 0x180680 + 64, /* same as audio IN */
1da177e4 296 .fifo_start = 0x185400, /* same as audio IN */
b7f355d2 297 .fifo_size = 0x001000, /* same as audio IN */
1da177e4
LT
298 .ptr1_reg = MO_DMA26_PTR1,
299 .ptr2_reg = MO_DMA26_PTR2,
300 .cnt1_reg = MO_DMA26_CNT1,
301 .cnt2_reg = MO_DMA26_CNT2,
302 },
303 [SRAM_CH28] = {
304 .name = "mpeg",
305 .cmds_start = 0x180200,
306 .ctrl_start = 0x1807C0,
307 .cdt = 0x1807C0 + 64,
b7f355d2 308 .fifo_start = 0x186400,
1da177e4
LT
309 .fifo_size = 0x001000,
310 .ptr1_reg = MO_DMA28_PTR1,
311 .ptr2_reg = MO_DMA28_PTR2,
312 .cnt1_reg = MO_DMA28_CNT1,
313 .cnt2_reg = MO_DMA28_CNT2,
314 },
e878cf3a
MB
315 [SRAM_CH27] = {
316 .name = "audio rds",
317 .cmds_start = 0x1801C0,
318 .ctrl_start = 0x180860,
319 .cdt = 0x180860 + 64,
320 .fifo_start = 0x187400,
321 .fifo_size = 0x000C00,
322 .ptr1_reg = MO_DMA27_PTR1,
323 .ptr2_reg = MO_DMA27_PTR2,
324 .cnt1_reg = MO_DMA27_CNT1,
325 .cnt2_reg = MO_DMA27_CNT2,
326 },
1da177e4
LT
327};
328
329int cx88_sram_channel_setup(struct cx88_core *core,
2e4e98e7 330 const struct sram_channel *ch,
1da177e4
LT
331 unsigned int bpl, u32 risc)
332{
333 unsigned int i,lines;
334 u32 cdt;
335
336 bpl = (bpl + 7) & ~7; /* alignment */
337 cdt = ch->cdt;
338 lines = ch->fifo_size / bpl;
339 if (lines > 6)
340 lines = 6;
341 BUG_ON(lines < 2);
342
343 /* write CDT */
344 for (i = 0; i < lines; i++)
345 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
346
347 /* write CMDS */
348 cx_write(ch->cmds_start + 0, risc);
349 cx_write(ch->cmds_start + 4, cdt);
350 cx_write(ch->cmds_start + 8, (lines*16) >> 3);
351 cx_write(ch->cmds_start + 12, ch->ctrl_start);
352 cx_write(ch->cmds_start + 16, 64 >> 2);
353 for (i = 20; i < 64; i += 4)
354 cx_write(ch->cmds_start + i, 0);
355
356 /* fill registers */
357 cx_write(ch->ptr1_reg, ch->fifo_start);
358 cx_write(ch->ptr2_reg, cdt);
359 cx_write(ch->cnt1_reg, (bpl >> 3) -1);
360 cx_write(ch->cnt2_reg, (lines*16) >> 3);
361
362 dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
363 return 0;
364}
365
366/* ------------------------------------------------------------------ */
367/* debug helper code */
368
f9e7a020 369static int cx88_risc_decode(u32 risc)
1da177e4 370{
2e4e98e7 371 static const char * const instr[16] = {
1da177e4
LT
372 [ RISC_SYNC >> 28 ] = "sync",
373 [ RISC_WRITE >> 28 ] = "write",
374 [ RISC_WRITEC >> 28 ] = "writec",
375 [ RISC_READ >> 28 ] = "read",
376 [ RISC_READC >> 28 ] = "readc",
377 [ RISC_JUMP >> 28 ] = "jump",
378 [ RISC_SKIP >> 28 ] = "skip",
379 [ RISC_WRITERM >> 28 ] = "writerm",
380 [ RISC_WRITECM >> 28 ] = "writecm",
381 [ RISC_WRITECR >> 28 ] = "writecr",
382 };
2e4e98e7 383 static int const incr[16] = {
1da177e4
LT
384 [ RISC_WRITE >> 28 ] = 2,
385 [ RISC_JUMP >> 28 ] = 2,
386 [ RISC_WRITERM >> 28 ] = 3,
387 [ RISC_WRITECM >> 28 ] = 3,
388 [ RISC_WRITECR >> 28 ] = 4,
389 };
2e4e98e7 390 static const char * const bits[] = {
1da177e4
LT
391 "12", "13", "14", "resync",
392 "cnt0", "cnt1", "18", "19",
393 "20", "21", "22", "23",
394 "irq1", "irq2", "eol", "sol",
395 };
396 int i;
397
398 printk("0x%08x [ %s", risc,
399 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
400 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
401 if (risc & (1 << (i + 12)))
402 printk(" %s",bits[i]);
403 printk(" count=%d ]\n", risc & 0xfff);
404 return incr[risc >> 28] ? incr[risc >> 28] : 1;
405}
406
1da177e4
LT
407
408void cx88_sram_channel_dump(struct cx88_core *core,
2e4e98e7 409 const struct sram_channel *ch)
1da177e4 410{
2e4e98e7 411 static const char * const name[] = {
1da177e4
LT
412 "initial risc",
413 "cdt base",
414 "cdt size",
415 "iq base",
416 "iq size",
417 "risc pc",
418 "iq wr ptr",
419 "iq rd ptr",
420 "cdt current",
421 "pci target",
422 "line / byte",
423 };
424 u32 risc;
425 unsigned int i,j,n;
426
427 printk("%s: %s - dma channel status dump\n",
428 core->name,ch->name);
429 for (i = 0; i < ARRAY_SIZE(name); i++)
430 printk("%s: cmds: %-12s: 0x%08x\n",
431 core->name,name[i],
432 cx_read(ch->cmds_start + 4*i));
16cf1d0c 433 for (n = 1, i = 0; i < 4; i++) {
1da177e4
LT
434 risc = cx_read(ch->cmds_start + 4 * (i+11));
435 printk("%s: risc%d: ", core->name, i);
16cf1d0c
TP
436 if (--n)
437 printk("0x%08x [ arg #%d ]\n", risc, n);
438 else
439 n = cx88_risc_decode(risc);
1da177e4
LT
440 }
441 for (i = 0; i < 16; i += n) {
442 risc = cx_read(ch->ctrl_start + 4 * i);
443 printk("%s: iq %x: ", core->name, i);
444 n = cx88_risc_decode(risc);
445 for (j = 1; j < n; j++) {
446 risc = cx_read(ch->ctrl_start + 4 * (i+j));
447 printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
448 core->name, i+j, risc, j);
449 }
450 }
451
452 printk("%s: fifo: 0x%08x -> 0x%x\n",
453 core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
454 printk("%s: ctrl: 0x%08x -> 0x%x\n",
455 core->name, ch->ctrl_start, ch->ctrl_start+6*16);
456 printk("%s: ptr1_reg: 0x%08x\n",
457 core->name,cx_read(ch->ptr1_reg));
458 printk("%s: ptr2_reg: 0x%08x\n",
459 core->name,cx_read(ch->ptr2_reg));
460 printk("%s: cnt1_reg: 0x%08x\n",
461 core->name,cx_read(ch->cnt1_reg));
462 printk("%s: cnt2_reg: 0x%08x\n",
463 core->name,cx_read(ch->cnt2_reg));
464}
465
2e4e98e7 466static const char *cx88_pci_irqs[32] = {
1da177e4
LT
467 "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
468 "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
469 "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
470 "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
471};
1da177e4 472
2e4e98e7 473void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
66623a04 474 int len, u32 bits, u32 mask)
1da177e4
LT
475{
476 unsigned int i;
477
478 printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
66623a04 479 for (i = 0; i < len; i++) {
1da177e4
LT
480 if (!(bits & (1 << i)))
481 continue;
482 if (strings[i])
483 printk(" %s", strings[i]);
484 else
485 printk(" %d", i);
486 if (!(mask & (1 << i)))
487 continue;
488 printk("*");
489 }
490 printk("\n");
491}
492
493/* ------------------------------------------------------------------ */
494
495int cx88_core_irq(struct cx88_core *core, u32 status)
496{
497 int handled = 0;
498
8ddac9ee 499 if (status & PCI_INT_IR_SMPINT) {
1da177e4
LT
500 cx88_ir_irq(core);
501 handled++;
502 }
503 if (!handled)
504 cx88_print_irqbits(core->name, "irq pci",
66623a04
MCC
505 cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
506 status, core->pci_irqmask);
1da177e4
LT
507 return handled;
508}
509
510void cx88_wakeup(struct cx88_core *core,
511 struct cx88_dmaqueue *q, u32 count)
512{
513 struct cx88_buffer *buf;
0b6b6302
HV
514
515 buf = list_entry(q->active.next,
516 struct cx88_buffer, list);
517 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
518 list_del(&buf->list);
519 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
1da177e4
LT
520}
521
522void cx88_shutdown(struct cx88_core *core)
523{
524 /* disable RISC controller + IRQs */
525 cx_write(MO_DEV_CNTRL2, 0);
526
527 /* stop dma transfers */
528 cx_write(MO_VID_DMACNTRL, 0x0);
529 cx_write(MO_AUD_DMACNTRL, 0x0);
530 cx_write(MO_TS_DMACNTRL, 0x0);
531 cx_write(MO_VIP_DMACNTRL, 0x0);
532 cx_write(MO_GPHST_DMACNTRL, 0x0);
533
534 /* stop interrupts */
535 cx_write(MO_PCI_INTMSK, 0x0);
536 cx_write(MO_VID_INTMSK, 0x0);
537 cx_write(MO_AUD_INTMSK, 0x0);
538 cx_write(MO_TS_INTMSK, 0x0);
539 cx_write(MO_VIP_INTMSK, 0x0);
540 cx_write(MO_GPHST_INTMSK, 0x0);
541
542 /* stop capturing */
543 cx_write(VID_CAPTURE_CONTROL, 0);
544}
545
546int cx88_reset(struct cx88_core *core)
547{
32d83efc 548 dprintk(1,"%s\n",__func__);
1da177e4
LT
549 cx88_shutdown(core);
550
551 /* clear irq status */
552 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
553 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
554 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
555
556 /* wait a bit */
557 msleep(100);
558
559 /* init sram */
560 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
561 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
562 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
563 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
564 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
565 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
566 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
e878cf3a 567 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
1da177e4
LT
568
569 /* misc init ... */
570 cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
571 (1 << 12) | // agc gain
572 (1 << 11) | // adaptibe agc
573 (0 << 10) | // chroma agc
574 (0 << 9) | // ckillen
575 (7)));
576
577 /* setup image format */
578 cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
579
af901ca1 580 /* setup FIFO Thresholds */
1da177e4
LT
581 cx_write(MO_PDMA_STHRSH, 0x0807);
582 cx_write(MO_PDMA_DTHRSH, 0x0807);
583
584 /* fixes flashing of image */
585 cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
586 cx_write(MO_AGC_BACK_VBI, 0x00E00555);
587
588 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
589 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
590 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
591
592 /* Reset on-board parts */
593 cx_write(MO_SRST_IO, 0);
594 msleep(10);
595 cx_write(MO_SRST_IO, 1);
596
597 return 0;
598}
599
600/* ------------------------------------------------------------------ */
601
34206439 602static inline unsigned int norm_swidth(v4l2_std_id norm)
1da177e4 603{
63ab1bdc 604 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
1da177e4
LT
605}
606
34206439 607static inline unsigned int norm_hdelay(v4l2_std_id norm)
1da177e4 608{
63ab1bdc 609 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
1da177e4
LT
610}
611
34206439 612static inline unsigned int norm_vdelay(v4l2_std_id norm)
1da177e4 613{
63ab1bdc 614 return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
1da177e4
LT
615}
616
34206439 617static inline unsigned int norm_fsc8(v4l2_std_id norm)
1da177e4 618{
63ab1bdc 619 if (norm & V4L2_STD_PAL_M)
315eb962
MCC
620 return 28604892; // 3.575611 MHz
621
63ab1bdc 622 if (norm & (V4L2_STD_PAL_Nc))
315eb962
MCC
623 return 28656448; // 3.582056 MHz
624
63ab1bdc 625 if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
315eb962 626 return 28636360; // 3.57954545 MHz +/- 10 Hz
1da177e4 627
315eb962
MCC
628 /* SECAM have also different sub carrier for chroma,
629 but step_db and step_dr, at cx88_set_tvnorm already handles that.
630
631 The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
632 */
633
634 return 35468950; // 4.43361875 MHz +/- 5 Hz
1da177e4
LT
635}
636
34206439 637static inline unsigned int norm_htotal(v4l2_std_id norm)
1da177e4 638{
59dcd948 639
315eb962 640 unsigned int fsc4=norm_fsc8(norm)/2;
59dcd948 641
315eb962 642 /* returns 4*FSC / vtotal / frames per seconds */
63ab1bdc 643 return (norm & V4L2_STD_625_50) ?
315eb962
MCC
644 ((fsc4+312)/625+12)/25 :
645 ((fsc4+262)/525*1001+15000)/30000;
1da177e4
LT
646}
647
34206439 648static inline unsigned int norm_vbipack(v4l2_std_id norm)
1da177e4 649{
63ab1bdc 650 return (norm & V4L2_STD_625_50) ? 511 : 400;
1da177e4
LT
651}
652
653int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
654 enum v4l2_field field)
655{
656 unsigned int swidth = norm_swidth(core->tvnorm);
657 unsigned int sheight = norm_maxh(core->tvnorm);
658 u32 value;
659
660 dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
661 V4L2_FIELD_HAS_TOP(field) ? "T" : "",
662 V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
63ab1bdc 663 v4l2_norm_to_name(core->tvnorm));
1da177e4
LT
664 if (!V4L2_FIELD_HAS_BOTH(field))
665 height *= 2;
666
667 // recalc H delay and scale registers
668 value = (width * norm_hdelay(core->tvnorm)) / swidth;
669 value &= 0x3fe;
670 cx_write(MO_HDELAY_EVEN, value);
671 cx_write(MO_HDELAY_ODD, value);
315eb962 672 dprintk(1,"set_scale: hdelay 0x%04x (width %d)\n", value,swidth);
1da177e4
LT
673
674 value = (swidth * 4096 / width) - 4096;
675 cx_write(MO_HSCALE_EVEN, value);
676 cx_write(MO_HSCALE_ODD, value);
677 dprintk(1,"set_scale: hscale 0x%04x\n", value);
678
679 cx_write(MO_HACTIVE_EVEN, width);
680 cx_write(MO_HACTIVE_ODD, width);
681 dprintk(1,"set_scale: hactive 0x%04x\n", width);
682
683 // recalc V scale Register (delay is constant)
684 cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
685 cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
686 dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
687
688 value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
689 cx_write(MO_VSCALE_EVEN, value);
690 cx_write(MO_VSCALE_ODD, value);
691 dprintk(1,"set_scale: vscale 0x%04x\n", value);
692
693 cx_write(MO_VACTIVE_EVEN, sheight);
694 cx_write(MO_VACTIVE_ODD, sheight);
695 dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
696
697 // setup filters
698 value = 0;
699 value |= (1 << 19); // CFILT (default)
63ab1bdc 700 if (core->tvnorm & V4L2_STD_SECAM) {
1da177e4
LT
701 value |= (1 << 15);
702 value |= (1 << 16);
703 }
6a59d64c 704 if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
1da177e4
LT
705 value |= (1 << 13) | (1 << 5);
706 if (V4L2_FIELD_INTERLACED == field)
707 value |= (1 << 3); // VINT (interlaced vertical scaling)
708 if (width < 385)
709 value |= (1 << 0); // 3-tap interpolation
710 if (width < 193)
711 value |= (1 << 1); // 5-tap interpolation
712 if (nocomb)
713 value |= (3 << 5); // disable comb filter
714
eea16e36 715 cx_andor(MO_FILTER_EVEN, 0x7ffc7f, value); /* preserve PEAKEN, PSEL */
716 cx_andor(MO_FILTER_ODD, 0x7ffc7f, value);
1da177e4
LT
717 dprintk(1,"set_scale: filter 0x%04x\n", value);
718
719 return 0;
720}
721
722static const u32 xtal = 28636363;
723
724static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
725{
2e4e98e7 726 static const u32 pre[] = { 0, 0, 0, 3, 2, 1 };
1da177e4
LT
727 u64 pll;
728 u32 reg;
729 int i;
730
731 if (prescale < 2)
732 prescale = 2;
733 if (prescale > 5)
734 prescale = 5;
735
736 pll = ofreq * 8 * prescale * (u64)(1 << 20);
737 do_div(pll,xtal);
738 reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
739 if (((reg >> 20) & 0x3f) < 14) {
740 printk("%s/0: pll out of range\n",core->name);
741 return -1;
742 }
743
744 dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
745 reg, cx_read(MO_PLL_REG), ofreq);
746 cx_write(MO_PLL_REG, reg);
747 for (i = 0; i < 100; i++) {
748 reg = cx_read(MO_DEVICE_STATUS);
749 if (reg & (1<<2)) {
750 dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
751 prescale,ofreq);
752 return 0;
753 }
754 dprintk(1,"pll not locked yet, waiting ...\n");
755 msleep(10);
756 }
757 dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
758 return -1;
759}
760
6f502b8a
MCC
761int cx88_start_audio_dma(struct cx88_core *core)
762{
17801f5f
MR
763 /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
764 int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
e738e35d 765
e878cf3a
MB
766 int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
767
e738e35d
RC
768 /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
769 if (cx_read(MO_AUD_DMACNTRL) & 0x10)
770 return 0;
771
6f502b8a 772 /* setup fifo + format */
17801f5f
MR
773 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
774 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
e878cf3a
MB
775 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
776 rds_bpl, 0);
6f502b8a 777
17801f5f 778 cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
e878cf3a 779 cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
6f502b8a 780
e878cf3a
MB
781 /* enable Up, Down and Audio RDS fifo */
782 cx_write(MO_AUD_DMACNTRL, 0x0007);
e738e35d 783
6f502b8a
MCC
784 return 0;
785}
786
787int cx88_stop_audio_dma(struct cx88_core *core)
788{
e738e35d
RC
789 /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
790 if (cx_read(MO_AUD_DMACNTRL) & 0x10)
791 return 0;
792
6f502b8a
MCC
793 /* stop dma */
794 cx_write(MO_AUD_DMACNTRL, 0x0000);
795
796 return 0;
797}
798
1da177e4
LT
799static int set_tvaudio(struct cx88_core *core)
800{
63ab1bdc 801 v4l2_std_id norm = core->tvnorm;
1da177e4 802
6e1f4df7 803 if (CX88_VMUX_TELEVISION != INPUT(core->input).type &&
804 CX88_VMUX_CABLE != INPUT(core->input).type)
1da177e4
LT
805 return 0;
806
63ab1bdc 807 if (V4L2_STD_PAL_BG & norm) {
b1706b91 808 core->tvaudio = WW_BG;
1da177e4 809
63ab1bdc 810 } else if (V4L2_STD_PAL_DK & norm) {
b1706b91 811 core->tvaudio = WW_DK;
1da177e4 812
63ab1bdc 813 } else if (V4L2_STD_PAL_I & norm) {
b1706b91 814 core->tvaudio = WW_I;
1da177e4 815
63ab1bdc 816 } else if (V4L2_STD_SECAM_L & norm) {
b1706b91 817 core->tvaudio = WW_L;
1da177e4 818
b84ca9f2
FC
819 } else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
820 core->tvaudio = WW_BG;
821
63ab1bdc 822 } else if (V4L2_STD_SECAM_DK & norm) {
b1706b91 823 core->tvaudio = WW_DK;
1da177e4 824
63ab1bdc
MCC
825 } else if ((V4L2_STD_NTSC_M & norm) ||
826 (V4L2_STD_PAL_M & norm)) {
1da177e4
LT
827 core->tvaudio = WW_BTSC;
828
63ab1bdc 829 } else if (V4L2_STD_NTSC_M_JP & norm) {
1da177e4
LT
830 core->tvaudio = WW_EIAJ;
831
832 } else {
833 printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
63ab1bdc 834 core->name, v4l2_norm_to_name(core->tvnorm));
d06b49ed 835 core->tvaudio = WW_NONE;
1da177e4
LT
836 return 0;
837 }
838
839 cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
840 cx88_set_tvaudio(core);
e52e98a7 841 /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
1da177e4 842
6f502b8a
MCC
843/*
844 This should be needed only on cx88-alsa. It seems that some cx88 chips have
845 bugs and does require DMA enabled for it to work.
846 */
847 cx88_start_audio_dma(core);
1da177e4
LT
848 return 0;
849}
850
6f502b8a
MCC
851
852
63ab1bdc 853int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
1da177e4
LT
854{
855 u32 fsc8;
856 u32 adc_clock;
857 u32 vdec_clock;
858 u32 step_db,step_dr;
859 u64 tmp64;
860 u32 bdelay,agcdelay,htotal;
8d87cb9f 861 u32 cxiformat, cxoformat;
1da177e4
LT
862
863 core->tvnorm = norm;
864 fsc8 = norm_fsc8(norm);
865 adc_clock = xtal;
866 vdec_clock = fsc8;
867 step_db = fsc8;
868 step_dr = fsc8;
869
63ab1bdc 870 if (norm & V4L2_STD_NTSC_M_JP) {
8d87cb9f
MCC
871 cxiformat = VideoFormatNTSCJapan;
872 cxoformat = 0x181f0008;
63ab1bdc 873 } else if (norm & V4L2_STD_NTSC_443) {
1427f6b6
MCC
874 cxiformat = VideoFormatNTSC443;
875 cxoformat = 0x181f0008;
63ab1bdc 876 } else if (norm & V4L2_STD_PAL_M) {
8d87cb9f
MCC
877 cxiformat = VideoFormatPALM;
878 cxoformat = 0x1c1f0008;
63ab1bdc 879 } else if (norm & V4L2_STD_PAL_N) {
8d87cb9f
MCC
880 cxiformat = VideoFormatPALN;
881 cxoformat = 0x1c1f0008;
63ab1bdc 882 } else if (norm & V4L2_STD_PAL_Nc) {
8d87cb9f
MCC
883 cxiformat = VideoFormatPALNC;
884 cxoformat = 0x1c1f0008;
63ab1bdc 885 } else if (norm & V4L2_STD_PAL_60) {
8d87cb9f
MCC
886 cxiformat = VideoFormatPAL60;
887 cxoformat = 0x181f0008;
63ab1bdc 888 } else if (norm & V4L2_STD_NTSC) {
8d87cb9f
MCC
889 cxiformat = VideoFormatNTSC;
890 cxoformat = 0x181f0008;
63ab1bdc 891 } else if (norm & V4L2_STD_SECAM) {
1da177e4
LT
892 step_db = 4250000 * 8;
893 step_dr = 4406250 * 8;
1427f6b6
MCC
894
895 cxiformat = VideoFormatSECAM;
896 cxoformat = 0x181f0008;
8d87cb9f
MCC
897 } else { /* PAL */
898 cxiformat = VideoFormatPAL;
899 cxoformat = 0x181f0008;
1da177e4
LT
900 }
901
902 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
63ab1bdc
MCC
903 v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
904 step_db, step_dr);
1da177e4
LT
905 set_pll(core,2,vdec_clock);
906
907 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
8d87cb9f 908 cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
87a17389
FD
909 /* Chroma AGC must be disabled if SECAM is used, we enable it
910 by default on PAL and NTSC */
911 cx_andor(MO_INPUT_FORMAT, 0x40f,
912 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
1da177e4 913
1da177e4
LT
914 // FIXME: as-is from DScaler
915 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
8d87cb9f
MCC
916 cxoformat, cx_read(MO_OUTPUT_FORMAT));
917 cx_write(MO_OUTPUT_FORMAT, cxoformat);
1da177e4
LT
918
919 // MO_SCONV_REG = adc clock / video dec clock * 2^17
920 tmp64 = adc_clock * (u64)(1 << 17);
921 do_div(tmp64, vdec_clock);
922 dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
923 (u32)tmp64, cx_read(MO_SCONV_REG));
924 cx_write(MO_SCONV_REG, (u32)tmp64);
925
926 // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
927 tmp64 = step_db * (u64)(1 << 22);
928 do_div(tmp64, vdec_clock);
929 dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
930 (u32)tmp64, cx_read(MO_SUB_STEP));
931 cx_write(MO_SUB_STEP, (u32)tmp64);
932
933 // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
934 tmp64 = step_dr * (u64)(1 << 22);
935 do_div(tmp64, vdec_clock);
936 dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
937 (u32)tmp64, cx_read(MO_SUB_STEP_DR));
938 cx_write(MO_SUB_STEP_DR, (u32)tmp64);
939
940 // bdelay + agcdelay
941 bdelay = vdec_clock * 65 / 20000000 + 21;
942 agcdelay = vdec_clock * 68 / 20000000 + 15;
943 dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
944 (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
945 cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
946
947 // htotal
948 tmp64 = norm_htotal(norm) * (u64)vdec_clock;
949 do_div(tmp64, fsc8);
bded70d2 950 htotal = (u32)tmp64;
1da177e4
LT
951 dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
952 htotal, cx_read(MO_HTOTAL), (u32)tmp64);
bded70d2 953 cx_andor(MO_HTOTAL, 0x07ff, htotal);
1da177e4 954
3eb73170
TP
955 // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
956 // the effective vbi offset ~244 samples, the same as the Bt8x8
957 cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
1da177e4
LT
958
959 // this is needed as well to set all tvnorm parameter
960 cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
961
962 // audio
963 set_tvaudio(core);
964
965 // tell i2c chips
8774bed9 966 call_all(core, video, s_std, norm);
1da177e4 967
8c7cb12a
HV
968 /* The chroma_agc control should be inaccessible if the video format is SECAM */
969 v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
970
1da177e4
LT
971 // done
972 return 0;
973}
974
975/* ------------------------------------------------------------------ */
976
1da177e4
LT
977struct video_device *cx88_vdev_init(struct cx88_core *core,
978 struct pci_dev *pci,
2e4e98e7 979 const struct video_device *template_,
980 const char *type)
1da177e4
LT
981{
982 struct video_device *vfd;
983
984 vfd = video_device_alloc();
985 if (NULL == vfd)
986 return NULL;
2e4e98e7 987 *vfd = *template_;
e5715cfb
HV
988 /*
989 * The dev pointer of v4l2_device is NULL, instead we set the
990 * video_device dev_parent pointer to the correct PCI bus device.
991 * This driver is a rare example where there is one v4l2_device,
992 * but the video nodes have different parent (PCI) devices.
993 */
9467fe12 994 vfd->v4l2_dev = &core->v4l2_dev;
e5715cfb 995 vfd->dev_parent = &pci->dev;
1da177e4 996 vfd->release = video_device_release;
0b6b6302 997 vfd->lock = &core->lock;
1da177e4 998 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
6a59d64c 999 core->name, type, core->board.name);
1da177e4
LT
1000 return vfd;
1001}
1002
1da177e4
LT
1003struct cx88_core* cx88_core_get(struct pci_dev *pci)
1004{
1005 struct cx88_core *core;
1da177e4 1006
1e4baed3 1007 mutex_lock(&devlist);
8bb629e2 1008 list_for_each_entry(core, &cx88_devlist, devlist) {
1da177e4
LT
1009 if (pci->bus->number != core->pci_bus)
1010 continue;
1011 if (PCI_SLOT(pci->devfn) != core->pci_slot)
1012 continue;
1013
bbc83597
TP
1014 if (0 != cx88_get_resources(core, pci)) {
1015 mutex_unlock(&devlist);
1016 return NULL;
1017 }
1da177e4 1018 atomic_inc(&core->refcount);
1e4baed3 1019 mutex_unlock(&devlist);
1da177e4
LT
1020 return core;
1021 }
b45009b0 1022
bbc83597
TP
1023 core = cx88_core_create(pci, cx88_devcount);
1024 if (NULL != core) {
1025 cx88_devcount++;
1026 list_add_tail(&core->devlist, &cx88_devlist);
1027 }
1da177e4 1028
1e4baed3 1029 mutex_unlock(&devlist);
1da177e4 1030 return core;
1da177e4
LT
1031}
1032
1033void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1034{
1035 release_mem_region(pci_resource_start(pci,0),
1036 pci_resource_len(pci,0));
1037
1038 if (!atomic_dec_and_test(&core->refcount))
1039 return;
1040
1e4baed3 1041 mutex_lock(&devlist);
1da177e4 1042 cx88_ir_fini(core);
b8341e1d
HV
1043 if (0 == core->i2c_rc) {
1044 if (core->i2c_rtc)
1045 i2c_unregister_device(core->i2c_rtc);
3269711b 1046 i2c_del_adapter(&core->i2c_adap);
b8341e1d 1047 }
1da177e4
LT
1048 list_del(&core->devlist);
1049 iounmap(core->lmmio);
1050 cx88_devcount--;
1e4baed3 1051 mutex_unlock(&devlist);
8c7cb12a
HV
1052 v4l2_ctrl_handler_free(&core->video_hdl);
1053 v4l2_ctrl_handler_free(&core->audio_hdl);
9467fe12 1054 v4l2_device_unregister(&core->v4l2_dev);
1da177e4
LT
1055 kfree(core);
1056}
1057
1058/* ------------------------------------------------------------------ */
1059
1da177e4
LT
1060EXPORT_SYMBOL(cx88_print_irqbits);
1061
1062EXPORT_SYMBOL(cx88_core_irq);
1063EXPORT_SYMBOL(cx88_wakeup);
1064EXPORT_SYMBOL(cx88_reset);
1065EXPORT_SYMBOL(cx88_shutdown);
1066
1067EXPORT_SYMBOL(cx88_risc_buffer);
1068EXPORT_SYMBOL(cx88_risc_databuffer);
1da177e4
LT
1069
1070EXPORT_SYMBOL(cx88_sram_channels);
1071EXPORT_SYMBOL(cx88_sram_channel_setup);
1072EXPORT_SYMBOL(cx88_sram_channel_dump);
1073
1074EXPORT_SYMBOL(cx88_set_tvnorm);
1075EXPORT_SYMBOL(cx88_set_scale);
1076
1077EXPORT_SYMBOL(cx88_vdev_init);
1078EXPORT_SYMBOL(cx88_core_get);
1079EXPORT_SYMBOL(cx88_core_put);
1080
13595a51
MCC
1081EXPORT_SYMBOL(cx88_ir_start);
1082EXPORT_SYMBOL(cx88_ir_stop);
1083
1da177e4
LT
1084/*
1085 * Local variables:
1086 * c-basic-offset: 8
1087 * End:
e52e98a7 1088 * 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
1da177e4 1089 */
This page took 0.858526 seconds and 5 git commands to generate.