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