[PATCH] v4l: 800: whitespace cleanups
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / media / video / 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 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/init.h>
24#include <linux/list.h>
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/kernel.h>
28#include <linux/slab.h>
29#include <linux/kmod.h>
30#include <linux/sound.h>
31#include <linux/interrupt.h>
32#include <linux/pci.h>
33#include <linux/delay.h>
98f30ed0 34#include <linux/videodev2.h>
1da177e4
LT
35
36#include "cx88.h"
37
38MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
39MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
40MODULE_LICENSE("GPL");
41
42/* ------------------------------------------------------------------ */
43
44static unsigned int core_debug = 0;
45module_param(core_debug,int,0644);
46MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
47
48static unsigned int latency = UNSET;
49module_param(latency,int,0444);
50MODULE_PARM_DESC(latency,"pci latency timer");
51
52static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
b45009b0 53static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
1da177e4
LT
54static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
55
56module_param_array(tuner, int, NULL, 0444);
b45009b0 57module_param_array(radio, int, NULL, 0444);
1da177e4
LT
58module_param_array(card, int, NULL, 0444);
59
60MODULE_PARM_DESC(tuner,"tuner type");
b45009b0 61MODULE_PARM_DESC(radio,"radio tuner type");
1da177e4
LT
62MODULE_PARM_DESC(card,"card type");
63
64static unsigned int nicam = 0;
65module_param(nicam,int,0644);
66MODULE_PARM_DESC(nicam,"tv audio is nicam");
67
68static unsigned int nocomb = 0;
69module_param(nocomb,int,0644);
70MODULE_PARM_DESC(nocomb,"disable comb filter");
71
72#define dprintk(level,fmt, arg...) if (core_debug >= level) \
73 printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
74
75static unsigned int cx88_devcount;
76static LIST_HEAD(cx88_devlist);
77static DECLARE_MUTEX(devlist);
78
79/* ------------------------------------------------------------------ */
80/* debug help functions */
81
82static const char *v4l1_ioctls[] = {
83 "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
84 "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
85 "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
86 "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
87 "SMICROCODE", "GVBIFMT", "SVBIFMT" };
88#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
89
90static const char *v4l2_ioctls[] = {
91 "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
92 "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
93 "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
94 "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
95 "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
96 "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
97 "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
98 "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
99 "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
100 "S_MODULATOR"
101};
102#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
103
104void cx88_print_ioctl(char *name, unsigned int cmd)
105{
106 char *dir;
107
108 switch (_IOC_DIR(cmd)) {
109 case _IOC_NONE: dir = "--"; break;
110 case _IOC_READ: dir = "r-"; break;
111 case _IOC_WRITE: dir = "-w"; break;
112 case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
113 default: dir = "??"; break;
114 }
115 switch (_IOC_TYPE(cmd)) {
116 case 'v':
117 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
118 name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
119 v4l1_ioctls[_IOC_NR(cmd)] : "???");
120 break;
121 case 'V':
122 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
123 name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
124 v4l2_ioctls[_IOC_NR(cmd)] : "???");
125 break;
126 default:
127 printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
128 name, cmd, dir, _IOC_NR(cmd));
129 }
130}
131
132/* ------------------------------------------------------------------ */
133#define NO_SYNC_LINE (-1U)
134
135static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
136 unsigned int offset, u32 sync_line,
137 unsigned int bpl, unsigned int padding,
138 unsigned int lines)
139{
140 struct scatterlist *sg;
141 unsigned int line,todo;
142
143 /* sync instruction */
144 if (sync_line != NO_SYNC_LINE)
145 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
146
147 /* scan lines */
148 sg = sglist;
149 for (line = 0; line < lines; line++) {
150 while (offset && offset >= sg_dma_len(sg)) {
151 offset -= sg_dma_len(sg);
152 sg++;
153 }
154 if (bpl <= sg_dma_len(sg)-offset) {
155 /* fits into current chunk */
4ac97914
MCC
156 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
157 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
158 offset+=bpl;
1da177e4
LT
159 } else {
160 /* scanline needs to be splitted */
4ac97914
MCC
161 todo = bpl;
162 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
1da177e4 163 (sg_dma_len(sg)-offset));
4ac97914
MCC
164 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
165 todo -= (sg_dma_len(sg)-offset);
166 offset = 0;
167 sg++;
168 while (todo > sg_dma_len(sg)) {
169 *(rp++)=cpu_to_le32(RISC_WRITE|
1da177e4 170 sg_dma_len(sg));
4ac97914 171 *(rp++)=cpu_to_le32(sg_dma_address(sg));
1da177e4
LT
172 todo -= sg_dma_len(sg);
173 sg++;
174 }
4ac97914 175 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
1da177e4
LT
176 *(rp++)=cpu_to_le32(sg_dma_address(sg));
177 offset += todo;
178 }
179 offset += padding;
180 }
181
182 return rp;
183}
184
185int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
186 struct scatterlist *sglist,
187 unsigned int top_offset, unsigned int bottom_offset,
188 unsigned int bpl, unsigned int padding, unsigned int lines)
189{
190 u32 instructions,fields;
191 u32 *rp;
192 int rc;
193
194 fields = 0;
195 if (UNSET != top_offset)
196 fields++;
197 if (UNSET != bottom_offset)
198 fields++;
199
200 /* estimate risc mem: worst case is one write per page border +
201 one write per scan line + syncs + jump (all 2 dwords) */
202 instructions = (bpl * lines * fields) / PAGE_SIZE + lines * fields;
203 instructions += 3 + 4;
204 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
205 return rc;
206
207 /* write risc instructions */
208 rp = risc->cpu;
209 if (UNSET != top_offset)
210 rp = cx88_risc_field(rp, sglist, top_offset, 0,
211 bpl, padding, lines);
212 if (UNSET != bottom_offset)
213 rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
214 bpl, padding, lines);
215
216 /* save pointer to jmp instruction address */
217 risc->jmp = rp;
218 BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
219 return 0;
220}
221
222int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
223 struct scatterlist *sglist, unsigned int bpl,
224 unsigned int lines)
225{
226 u32 instructions;
227 u32 *rp;
228 int rc;
229
230 /* estimate risc mem: worst case is one write per page border +
231 one write per scan line + syncs + jump (all 2 dwords) */
232 instructions = (bpl * lines) / PAGE_SIZE + lines;
233 instructions += 3 + 4;
234 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
235 return rc;
236
237 /* write risc instructions */
238 rp = risc->cpu;
239 rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
240
241 /* save pointer to jmp instruction address */
242 risc->jmp = rp;
243 BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
244 return 0;
245}
246
247int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
248 u32 reg, u32 mask, u32 value)
249{
250 u32 *rp;
251 int rc;
252
253 if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
254 return rc;
255
256 /* write risc instructions */
257 rp = risc->cpu;
258 *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
259 *(rp++) = cpu_to_le32(reg);
260 *(rp++) = cpu_to_le32(value);
261 *(rp++) = cpu_to_le32(mask);
262 *(rp++) = cpu_to_le32(RISC_JUMP);
263 *(rp++) = cpu_to_le32(risc->dma);
264 return 0;
265}
266
267void
268cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
269{
270 if (in_interrupt())
271 BUG();
272 videobuf_waiton(&buf->vb,0,0);
273 videobuf_dma_pci_unmap(pci, &buf->vb.dma);
274 videobuf_dma_free(&buf->vb.dma);
275 btcx_riscmem_free(pci, &buf->risc);
276 buf->vb.state = STATE_NEEDS_INIT;
277}
278
279/* ------------------------------------------------------------------ */
280/* our SRAM memory layout */
281
282/* we are going to put all thr risc programs into host memory, so we
283 * can use the whole SDRAM for the DMA fifos. To simplify things, we
284 * use a static memory layout. That surely will waste memory in case
285 * we don't use all DMA channels at the same time (which will be the
286 * case most of the time). But that still gives us enougth FIFO space
287 * to be able to deal with insane long pci latencies ...
288 *
289 * FIFO space allocations:
290 * channel 21 (y video) - 10.0k
291 * channel 22 (u video) - 2.0k
292 * channel 23 (v video) - 2.0k
293 * channel 24 (vbi) - 4.0k
294 * channels 25+26 (audio) - 0.5k
295 * channel 28 (mpeg) - 4.0k
296 * TOTAL = 25.5k
297 *
298 * Every channel has 160 bytes control data (64 bytes instruction
299 * queue and 6 CDT entries), which is close to 2k total.
300 *
301 * Address layout:
302 * 0x0000 - 0x03ff CMDs / reserved
303 * 0x0400 - 0x0bff instruction queues + CDs
304 * 0x0c00 - FIFOs
305 */
306
307struct sram_channel cx88_sram_channels[] = {
308 [SRAM_CH21] = {
309 .name = "video y / packed",
310 .cmds_start = 0x180040,
311 .ctrl_start = 0x180400,
4ac97914 312 .cdt = 0x180400 + 64,
1da177e4
LT
313 .fifo_start = 0x180c00,
314 .fifo_size = 0x002800,
315 .ptr1_reg = MO_DMA21_PTR1,
316 .ptr2_reg = MO_DMA21_PTR2,
317 .cnt1_reg = MO_DMA21_CNT1,
318 .cnt2_reg = MO_DMA21_CNT2,
319 },
320 [SRAM_CH22] = {
321 .name = "video u",
322 .cmds_start = 0x180080,
323 .ctrl_start = 0x1804a0,
4ac97914 324 .cdt = 0x1804a0 + 64,
1da177e4
LT
325 .fifo_start = 0x183400,
326 .fifo_size = 0x000800,
327 .ptr1_reg = MO_DMA22_PTR1,
328 .ptr2_reg = MO_DMA22_PTR2,
329 .cnt1_reg = MO_DMA22_CNT1,
330 .cnt2_reg = MO_DMA22_CNT2,
331 },
332 [SRAM_CH23] = {
333 .name = "video v",
334 .cmds_start = 0x1800c0,
335 .ctrl_start = 0x180540,
4ac97914 336 .cdt = 0x180540 + 64,
1da177e4
LT
337 .fifo_start = 0x183c00,
338 .fifo_size = 0x000800,
339 .ptr1_reg = MO_DMA23_PTR1,
340 .ptr2_reg = MO_DMA23_PTR2,
341 .cnt1_reg = MO_DMA23_CNT1,
342 .cnt2_reg = MO_DMA23_CNT2,
343 },
344 [SRAM_CH24] = {
345 .name = "vbi",
346 .cmds_start = 0x180100,
347 .ctrl_start = 0x1805e0,
4ac97914 348 .cdt = 0x1805e0 + 64,
1da177e4
LT
349 .fifo_start = 0x184400,
350 .fifo_size = 0x001000,
351 .ptr1_reg = MO_DMA24_PTR1,
352 .ptr2_reg = MO_DMA24_PTR2,
353 .cnt1_reg = MO_DMA24_CNT1,
354 .cnt2_reg = MO_DMA24_CNT2,
355 },
356 [SRAM_CH25] = {
357 .name = "audio from",
358 .cmds_start = 0x180140,
359 .ctrl_start = 0x180680,
4ac97914 360 .cdt = 0x180680 + 64,
1da177e4
LT
361 .fifo_start = 0x185400,
362 .fifo_size = 0x000200,
363 .ptr1_reg = MO_DMA25_PTR1,
364 .ptr2_reg = MO_DMA25_PTR2,
365 .cnt1_reg = MO_DMA25_CNT1,
366 .cnt2_reg = MO_DMA25_CNT2,
367 },
368 [SRAM_CH26] = {
369 .name = "audio to",
370 .cmds_start = 0x180180,
371 .ctrl_start = 0x180720,
4ac97914 372 .cdt = 0x180680 + 64, /* same as audio IN */
1da177e4
LT
373 .fifo_start = 0x185400, /* same as audio IN */
374 .fifo_size = 0x000200, /* same as audio IN */
375 .ptr1_reg = MO_DMA26_PTR1,
376 .ptr2_reg = MO_DMA26_PTR2,
377 .cnt1_reg = MO_DMA26_CNT1,
378 .cnt2_reg = MO_DMA26_CNT2,
379 },
380 [SRAM_CH28] = {
381 .name = "mpeg",
382 .cmds_start = 0x180200,
383 .ctrl_start = 0x1807C0,
384 .cdt = 0x1807C0 + 64,
385 .fifo_start = 0x185600,
386 .fifo_size = 0x001000,
387 .ptr1_reg = MO_DMA28_PTR1,
388 .ptr2_reg = MO_DMA28_PTR2,
389 .cnt1_reg = MO_DMA28_CNT1,
390 .cnt2_reg = MO_DMA28_CNT2,
391 },
392};
393
394int cx88_sram_channel_setup(struct cx88_core *core,
395 struct sram_channel *ch,
396 unsigned int bpl, u32 risc)
397{
398 unsigned int i,lines;
399 u32 cdt;
400
401 bpl = (bpl + 7) & ~7; /* alignment */
402 cdt = ch->cdt;
403 lines = ch->fifo_size / bpl;
404 if (lines > 6)
405 lines = 6;
406 BUG_ON(lines < 2);
407
408 /* write CDT */
409 for (i = 0; i < lines; i++)
410 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
411
412 /* write CMDS */
413 cx_write(ch->cmds_start + 0, risc);
414 cx_write(ch->cmds_start + 4, cdt);
415 cx_write(ch->cmds_start + 8, (lines*16) >> 3);
416 cx_write(ch->cmds_start + 12, ch->ctrl_start);
417 cx_write(ch->cmds_start + 16, 64 >> 2);
418 for (i = 20; i < 64; i += 4)
419 cx_write(ch->cmds_start + i, 0);
420
421 /* fill registers */
422 cx_write(ch->ptr1_reg, ch->fifo_start);
423 cx_write(ch->ptr2_reg, cdt);
424 cx_write(ch->cnt1_reg, (bpl >> 3) -1);
425 cx_write(ch->cnt2_reg, (lines*16) >> 3);
426
427 dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
428 return 0;
429}
430
431/* ------------------------------------------------------------------ */
432/* debug helper code */
433
f9e7a020 434static int cx88_risc_decode(u32 risc)
1da177e4
LT
435{
436 static char *instr[16] = {
437 [ RISC_SYNC >> 28 ] = "sync",
438 [ RISC_WRITE >> 28 ] = "write",
439 [ RISC_WRITEC >> 28 ] = "writec",
440 [ RISC_READ >> 28 ] = "read",
441 [ RISC_READC >> 28 ] = "readc",
442 [ RISC_JUMP >> 28 ] = "jump",
443 [ RISC_SKIP >> 28 ] = "skip",
444 [ RISC_WRITERM >> 28 ] = "writerm",
445 [ RISC_WRITECM >> 28 ] = "writecm",
446 [ RISC_WRITECR >> 28 ] = "writecr",
447 };
448 static int incr[16] = {
449 [ RISC_WRITE >> 28 ] = 2,
450 [ RISC_JUMP >> 28 ] = 2,
451 [ RISC_WRITERM >> 28 ] = 3,
452 [ RISC_WRITECM >> 28 ] = 3,
453 [ RISC_WRITECR >> 28 ] = 4,
454 };
455 static char *bits[] = {
456 "12", "13", "14", "resync",
457 "cnt0", "cnt1", "18", "19",
458 "20", "21", "22", "23",
459 "irq1", "irq2", "eol", "sol",
460 };
461 int i;
462
463 printk("0x%08x [ %s", risc,
464 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
465 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
466 if (risc & (1 << (i + 12)))
467 printk(" %s",bits[i]);
468 printk(" count=%d ]\n", risc & 0xfff);
469 return incr[risc >> 28] ? incr[risc >> 28] : 1;
470}
471
1da177e4
LT
472
473void cx88_sram_channel_dump(struct cx88_core *core,
474 struct sram_channel *ch)
475{
476 static char *name[] = {
477 "initial risc",
478 "cdt base",
479 "cdt size",
480 "iq base",
481 "iq size",
482 "risc pc",
483 "iq wr ptr",
484 "iq rd ptr",
485 "cdt current",
486 "pci target",
487 "line / byte",
488 };
489 u32 risc;
490 unsigned int i,j,n;
491
492 printk("%s: %s - dma channel status dump\n",
493 core->name,ch->name);
494 for (i = 0; i < ARRAY_SIZE(name); i++)
495 printk("%s: cmds: %-12s: 0x%08x\n",
496 core->name,name[i],
497 cx_read(ch->cmds_start + 4*i));
498 for (i = 0; i < 4; i++) {
499 risc = cx_read(ch->cmds_start + 4 * (i+11));
500 printk("%s: risc%d: ", core->name, i);
501 cx88_risc_decode(risc);
502 }
503 for (i = 0; i < 16; i += n) {
504 risc = cx_read(ch->ctrl_start + 4 * i);
505 printk("%s: iq %x: ", core->name, i);
506 n = cx88_risc_decode(risc);
507 for (j = 1; j < n; j++) {
508 risc = cx_read(ch->ctrl_start + 4 * (i+j));
509 printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
510 core->name, i+j, risc, j);
511 }
512 }
513
514 printk("%s: fifo: 0x%08x -> 0x%x\n",
515 core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
516 printk("%s: ctrl: 0x%08x -> 0x%x\n",
517 core->name, ch->ctrl_start, ch->ctrl_start+6*16);
518 printk("%s: ptr1_reg: 0x%08x\n",
519 core->name,cx_read(ch->ptr1_reg));
520 printk("%s: ptr2_reg: 0x%08x\n",
521 core->name,cx_read(ch->ptr2_reg));
522 printk("%s: cnt1_reg: 0x%08x\n",
523 core->name,cx_read(ch->cnt1_reg));
524 printk("%s: cnt2_reg: 0x%08x\n",
525 core->name,cx_read(ch->cnt2_reg));
526}
527
408b664a 528static char *cx88_pci_irqs[32] = {
1da177e4
LT
529 "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
530 "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
531 "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
532 "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
533};
1da177e4
LT
534
535void cx88_print_irqbits(char *name, char *tag, char **strings,
536 u32 bits, u32 mask)
537{
538 unsigned int i;
539
540 printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
541 for (i = 0; i < 32; i++) {
542 if (!(bits & (1 << i)))
543 continue;
544 if (strings[i])
545 printk(" %s", strings[i]);
546 else
547 printk(" %d", i);
548 if (!(mask & (1 << i)))
549 continue;
550 printk("*");
551 }
552 printk("\n");
553}
554
555/* ------------------------------------------------------------------ */
556
557int cx88_core_irq(struct cx88_core *core, u32 status)
558{
559 int handled = 0;
560
561 if (status & (1<<18)) {
562 cx88_ir_irq(core);
563 handled++;
564 }
565 if (!handled)
566 cx88_print_irqbits(core->name, "irq pci",
567 cx88_pci_irqs, status,
568 core->pci_irqmask);
569 return handled;
570}
571
572void cx88_wakeup(struct cx88_core *core,
573 struct cx88_dmaqueue *q, u32 count)
574{
575 struct cx88_buffer *buf;
576 int bc;
577
578 for (bc = 0;; bc++) {
579 if (list_empty(&q->active))
580 break;
581 buf = list_entry(q->active.next,
582 struct cx88_buffer, vb.queue);
1da177e4
LT
583 /* count comes from the hw and is is 16bit wide --
584 * this trick handles wrap-arounds correctly for
585 * up to 32767 buffers in flight... */
586 if ((s16) (count - buf->count) < 0)
587 break;
1da177e4
LT
588 do_gettimeofday(&buf->vb.ts);
589 dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
590 count, buf->count);
591 buf->vb.state = STATE_DONE;
592 list_del(&buf->vb.queue);
593 wake_up(&buf->vb.done);
594 }
595 if (list_empty(&q->active)) {
596 del_timer(&q->timeout);
597 } else {
598 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
599 }
600 if (bc != 1)
601 printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
602}
603
604void cx88_shutdown(struct cx88_core *core)
605{
606 /* disable RISC controller + IRQs */
607 cx_write(MO_DEV_CNTRL2, 0);
608
609 /* stop dma transfers */
610 cx_write(MO_VID_DMACNTRL, 0x0);
611 cx_write(MO_AUD_DMACNTRL, 0x0);
612 cx_write(MO_TS_DMACNTRL, 0x0);
613 cx_write(MO_VIP_DMACNTRL, 0x0);
614 cx_write(MO_GPHST_DMACNTRL, 0x0);
615
616 /* stop interrupts */
617 cx_write(MO_PCI_INTMSK, 0x0);
618 cx_write(MO_VID_INTMSK, 0x0);
619 cx_write(MO_AUD_INTMSK, 0x0);
620 cx_write(MO_TS_INTMSK, 0x0);
621 cx_write(MO_VIP_INTMSK, 0x0);
622 cx_write(MO_GPHST_INTMSK, 0x0);
623
624 /* stop capturing */
625 cx_write(VID_CAPTURE_CONTROL, 0);
626}
627
628int cx88_reset(struct cx88_core *core)
629{
630 dprintk(1,"%s\n",__FUNCTION__);
631 cx88_shutdown(core);
632
633 /* clear irq status */
634 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
635 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
636 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
637
638 /* wait a bit */
639 msleep(100);
640
641 /* init sram */
642 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
643 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
644 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
645 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
646 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
647 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
648 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
649
650 /* misc init ... */
651 cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
652 (1 << 12) | // agc gain
653 (1 << 11) | // adaptibe agc
654 (0 << 10) | // chroma agc
655 (0 << 9) | // ckillen
656 (7)));
657
658 /* setup image format */
659 cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
660
661 /* setup FIFO Threshholds */
662 cx_write(MO_PDMA_STHRSH, 0x0807);
663 cx_write(MO_PDMA_DTHRSH, 0x0807);
664
665 /* fixes flashing of image */
666 cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
667 cx_write(MO_AGC_BACK_VBI, 0x00E00555);
668
669 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
670 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
671 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
672
673 /* Reset on-board parts */
674 cx_write(MO_SRST_IO, 0);
675 msleep(10);
676 cx_write(MO_SRST_IO, 1);
677
678 return 0;
679}
680
681/* ------------------------------------------------------------------ */
682
683static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
684{
685 return (norm->id & V4L2_STD_625_50) ? 922 : 754;
686}
687
688static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
689{
690 return (norm->id & V4L2_STD_625_50) ? 186 : 135;
691}
692
693static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
694{
695 return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18;
696}
697
698static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
699{
700 static const unsigned int ntsc = 28636360;
701 static const unsigned int pal = 35468950;
59dcd948
MCC
702 static const unsigned int palm = 28604892;
703
704 if (norm->id & V4L2_STD_PAL_M)
705 return palm;
1da177e4
LT
706
707 return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
708}
709
710static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
711{
712 return (norm->id & V4L2_STD_625_50)
713 ? HLNotchFilter135PAL
714 : HLNotchFilter135NTSC;
715}
716
717static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
718{
59dcd948
MCC
719 /* Should always be Line Draw Time / (4*FSC) */
720
721 if (norm->id & V4L2_STD_PAL_M)
722 return 909;
723
1da177e4
LT
724 return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
725}
726
727static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
728{
729 return (norm->id & V4L2_STD_625_50) ? 511 : 288;
730}
731
732int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
733 enum v4l2_field field)
734{
735 unsigned int swidth = norm_swidth(core->tvnorm);
736 unsigned int sheight = norm_maxh(core->tvnorm);
737 u32 value;
738
739 dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
740 V4L2_FIELD_HAS_TOP(field) ? "T" : "",
741 V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
742 core->tvnorm->name);
743 if (!V4L2_FIELD_HAS_BOTH(field))
744 height *= 2;
745
746 // recalc H delay and scale registers
747 value = (width * norm_hdelay(core->tvnorm)) / swidth;
748 value &= 0x3fe;
749 cx_write(MO_HDELAY_EVEN, value);
750 cx_write(MO_HDELAY_ODD, value);
751 dprintk(1,"set_scale: hdelay 0x%04x\n", value);
752
753 value = (swidth * 4096 / width) - 4096;
754 cx_write(MO_HSCALE_EVEN, value);
755 cx_write(MO_HSCALE_ODD, value);
756 dprintk(1,"set_scale: hscale 0x%04x\n", value);
757
758 cx_write(MO_HACTIVE_EVEN, width);
759 cx_write(MO_HACTIVE_ODD, width);
760 dprintk(1,"set_scale: hactive 0x%04x\n", width);
761
762 // recalc V scale Register (delay is constant)
763 cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
764 cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
765 dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
766
767 value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
768 cx_write(MO_VSCALE_EVEN, value);
769 cx_write(MO_VSCALE_ODD, value);
770 dprintk(1,"set_scale: vscale 0x%04x\n", value);
771
772 cx_write(MO_VACTIVE_EVEN, sheight);
773 cx_write(MO_VACTIVE_ODD, sheight);
774 dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
775
776 // setup filters
777 value = 0;
778 value |= (1 << 19); // CFILT (default)
779 if (core->tvnorm->id & V4L2_STD_SECAM) {
780 value |= (1 << 15);
781 value |= (1 << 16);
782 }
783 if (INPUT(core->input)->type == CX88_VMUX_SVIDEO)
784 value |= (1 << 13) | (1 << 5);
785 if (V4L2_FIELD_INTERLACED == field)
786 value |= (1 << 3); // VINT (interlaced vertical scaling)
787 if (width < 385)
788 value |= (1 << 0); // 3-tap interpolation
789 if (width < 193)
790 value |= (1 << 1); // 5-tap interpolation
791 if (nocomb)
792 value |= (3 << 5); // disable comb filter
793
794 cx_write(MO_FILTER_EVEN, value);
795 cx_write(MO_FILTER_ODD, value);
796 dprintk(1,"set_scale: filter 0x%04x\n", value);
797
798 return 0;
799}
800
801static const u32 xtal = 28636363;
802
803static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
804{
805 static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
806 u64 pll;
807 u32 reg;
808 int i;
809
810 if (prescale < 2)
811 prescale = 2;
812 if (prescale > 5)
813 prescale = 5;
814
815 pll = ofreq * 8 * prescale * (u64)(1 << 20);
816 do_div(pll,xtal);
817 reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
818 if (((reg >> 20) & 0x3f) < 14) {
819 printk("%s/0: pll out of range\n",core->name);
820 return -1;
821 }
822
823 dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
824 reg, cx_read(MO_PLL_REG), ofreq);
825 cx_write(MO_PLL_REG, reg);
826 for (i = 0; i < 100; i++) {
827 reg = cx_read(MO_DEVICE_STATUS);
828 if (reg & (1<<2)) {
829 dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
830 prescale,ofreq);
831 return 0;
832 }
833 dprintk(1,"pll not locked yet, waiting ...\n");
834 msleep(10);
835 }
836 dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
837 return -1;
838}
839
840static int set_tvaudio(struct cx88_core *core)
841{
842 struct cx88_tvnorm *norm = core->tvnorm;
843
844 if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
845 return 0;
846
847 if (V4L2_STD_PAL_BG & norm->id) {
b1706b91 848 core->tvaudio = WW_BG;
1da177e4
LT
849
850 } else if (V4L2_STD_PAL_DK & norm->id) {
b1706b91 851 core->tvaudio = WW_DK;
1da177e4
LT
852
853 } else if (V4L2_STD_PAL_I & norm->id) {
b1706b91 854 core->tvaudio = WW_I;
1da177e4
LT
855
856 } else if (V4L2_STD_SECAM_L & norm->id) {
b1706b91 857 core->tvaudio = WW_L;
1da177e4
LT
858
859 } else if (V4L2_STD_SECAM_DK & norm->id) {
b1706b91 860 core->tvaudio = WW_DK;
1da177e4
LT
861
862 } else if ((V4L2_STD_NTSC_M & norm->id) ||
863 (V4L2_STD_PAL_M & norm->id)) {
864 core->tvaudio = WW_BTSC;
865
866 } else if (V4L2_STD_NTSC_M_JP & norm->id) {
867 core->tvaudio = WW_EIAJ;
868
869 } else {
870 printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
871 core->name, norm->name);
872 core->tvaudio = 0;
873 return 0;
874 }
875
876 cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
877 cx88_set_tvaudio(core);
e52e98a7 878 /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
1da177e4
LT
879
880 cx_write(MO_AUDD_LNGTH, 128); /* fifo size */
881 cx_write(MO_AUDR_LNGTH, 128); /* fifo size */
882 cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */
883 return 0;
884}
885
886int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
887{
888 u32 fsc8;
889 u32 adc_clock;
890 u32 vdec_clock;
891 u32 step_db,step_dr;
892 u64 tmp64;
893 u32 bdelay,agcdelay,htotal;
894
895 core->tvnorm = norm;
896 fsc8 = norm_fsc8(norm);
897 adc_clock = xtal;
898 vdec_clock = fsc8;
899 step_db = fsc8;
900 step_dr = fsc8;
901
902 if (norm->id & V4L2_STD_SECAM) {
903 step_db = 4250000 * 8;
904 step_dr = 4406250 * 8;
905 }
906
907 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
908 norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr);
909 set_pll(core,2,vdec_clock);
910
911 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
912 norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
913 cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat);
914
1da177e4
LT
915 // FIXME: as-is from DScaler
916 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
917 norm->cxoformat, cx_read(MO_OUTPUT_FORMAT));
918 cx_write(MO_OUTPUT_FORMAT, norm->cxoformat);
1da177e4
LT
919
920 // MO_SCONV_REG = adc clock / video dec clock * 2^17
921 tmp64 = adc_clock * (u64)(1 << 17);
922 do_div(tmp64, vdec_clock);
923 dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
924 (u32)tmp64, cx_read(MO_SCONV_REG));
925 cx_write(MO_SCONV_REG, (u32)tmp64);
926
927 // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
928 tmp64 = step_db * (u64)(1 << 22);
929 do_div(tmp64, vdec_clock);
930 dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
931 (u32)tmp64, cx_read(MO_SUB_STEP));
932 cx_write(MO_SUB_STEP, (u32)tmp64);
933
934 // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
935 tmp64 = step_dr * (u64)(1 << 22);
936 do_div(tmp64, vdec_clock);
937 dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
938 (u32)tmp64, cx_read(MO_SUB_STEP_DR));
939 cx_write(MO_SUB_STEP_DR, (u32)tmp64);
940
941 // bdelay + agcdelay
942 bdelay = vdec_clock * 65 / 20000000 + 21;
943 agcdelay = vdec_clock * 68 / 20000000 + 15;
944 dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
945 (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
946 cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
947
948 // htotal
949 tmp64 = norm_htotal(norm) * (u64)vdec_clock;
950 do_div(tmp64, fsc8);
951 htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11);
952 dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
953 htotal, cx_read(MO_HTOTAL), (u32)tmp64);
954 cx_write(MO_HTOTAL, htotal);
955
956 // vbi stuff
957 cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */
958 norm_vbipack(norm)));
959
960 // this is needed as well to set all tvnorm parameter
961 cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
962
963 // audio
964 set_tvaudio(core);
965
966 // tell i2c chips
1da177e4 967 cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);
1da177e4
LT
968
969 // done
970 return 0;
971}
972
973/* ------------------------------------------------------------------ */
974
975static int cx88_pci_quirks(char *name, struct pci_dev *pci)
976{
977 unsigned int lat = UNSET;
978 u8 ctrl = 0;
979 u8 value;
980
981 /* check pci quirks */
982 if (pci_pci_problems & PCIPCI_TRITON) {
983 printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
984 name);
985 ctrl |= CX88X_EN_TBFX;
986 }
987 if (pci_pci_problems & PCIPCI_NATOMA) {
988 printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
989 name);
990 ctrl |= CX88X_EN_TBFX;
991 }
992 if (pci_pci_problems & PCIPCI_VIAETBF) {
993 printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
994 name);
995 ctrl |= CX88X_EN_TBFX;
996 }
997 if (pci_pci_problems & PCIPCI_VSFX) {
998 printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
999 name);
1000 ctrl |= CX88X_EN_VSFX;
1001 }
1002#ifdef PCIPCI_ALIMAGIK
1003 if (pci_pci_problems & PCIPCI_ALIMAGIK) {
1004 printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
1005 name);
1006 lat = 0x0A;
1007 }
1008#endif
1009
1010 /* check insmod options */
1011 if (UNSET != latency)
1012 lat = latency;
1013
1014 /* apply stuff */
1015 if (ctrl) {
1016 pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
1017 value |= ctrl;
1018 pci_write_config_byte(pci, CX88X_DEVCTRL, value);
1019 }
1020 if (UNSET != lat) {
1021 printk(KERN_INFO "%s: setting pci latency timer to %d\n",
1022 name, latency);
1023 pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
1024 }
1025 return 0;
1026}
1027
1028/* ------------------------------------------------------------------ */
1029
1030struct video_device *cx88_vdev_init(struct cx88_core *core,
1031 struct pci_dev *pci,
1032 struct video_device *template,
1033 char *type)
1034{
1035 struct video_device *vfd;
1036
1037 vfd = video_device_alloc();
1038 if (NULL == vfd)
1039 return NULL;
1040 *vfd = *template;
1041 vfd->minor = -1;
1042 vfd->dev = &pci->dev;
1043 vfd->release = video_device_release;
1044 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1045 core->name, type, cx88_boards[core->board].name);
1046 return vfd;
1047}
1048
1049static int get_ressources(struct cx88_core *core, struct pci_dev *pci)
1050{
1051 if (request_mem_region(pci_resource_start(pci,0),
1052 pci_resource_len(pci,0),
1053 core->name))
1054 return 0;
1055 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",
1056 core->name,pci_resource_start(pci,0));
1057 return -EBUSY;
1058}
1059
1060struct cx88_core* cx88_core_get(struct pci_dev *pci)
1061{
1062 struct cx88_core *core;
1063 struct list_head *item;
1064 int i;
1065
1066 down(&devlist);
1067 list_for_each(item,&cx88_devlist) {
1068 core = list_entry(item, struct cx88_core, devlist);
1069 if (pci->bus->number != core->pci_bus)
1070 continue;
1071 if (PCI_SLOT(pci->devfn) != core->pci_slot)
1072 continue;
1073
1074 if (0 != get_ressources(core,pci))
1075 goto fail_unlock;
1076 atomic_inc(&core->refcount);
1077 up(&devlist);
1078 return core;
1079 }
1080 core = kmalloc(sizeof(*core),GFP_KERNEL);
1081 if (NULL == core)
1082 goto fail_unlock;
1083
1084 memset(core,0,sizeof(*core));
1085 atomic_inc(&core->refcount);
1086 core->pci_bus = pci->bus->number;
1087 core->pci_slot = PCI_SLOT(pci->devfn);
1088 core->pci_irqmask = 0x00fc00;
e52e98a7 1089 init_MUTEX(&core->lock);
1da177e4
LT
1090
1091 core->nr = cx88_devcount++;
1092 sprintf(core->name,"cx88[%d]",core->nr);
1093 if (0 != get_ressources(core,pci)) {
e52e98a7
MCC
1094 printk(KERN_ERR "CORE %s No more PCI ressources for "
1095 "subsystem: %04x:%04x, board: %s\n",
1096 core->name,pci->subsystem_vendor,
1097 pci->subsystem_device,
1098 cx88_boards[core->board].name);
1099
1da177e4
LT
1100 cx88_devcount--;
1101 goto fail_free;
1102 }
1103 list_add_tail(&core->devlist,&cx88_devlist);
1104
1105 /* PCI stuff */
1106 cx88_pci_quirks(core->name, pci);
1107 core->lmmio = ioremap(pci_resource_start(pci,0),
1108 pci_resource_len(pci,0));
1109 core->bmmio = (u8 __iomem *)core->lmmio;
1110
1111 /* board config */
1112 core->board = UNSET;
1113 if (card[core->nr] < cx88_bcount)
1114 core->board = card[core->nr];
1115 for (i = 0; UNSET == core->board && i < cx88_idcount; i++)
1116 if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
1117 pci->subsystem_device == cx88_subids[i].subdevice)
1118 core->board = cx88_subids[i].card;
1119 if (UNSET == core->board) {
1120 core->board = CX88_BOARD_UNKNOWN;
1121 cx88_card_list(core,pci);
1122 }
e52e98a7
MCC
1123 printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
1124 core->name,pci->subsystem_vendor,
1125 pci->subsystem_device,cx88_boards[core->board].name,
1126 core->board, card[core->nr] == core->board ?
1127 "insmod option" : "autodetected");
1da177e4
LT
1128
1129 core->tuner_type = tuner[core->nr];
b45009b0 1130 core->radio_type = radio[core->nr];
1da177e4
LT
1131 if (UNSET == core->tuner_type)
1132 core->tuner_type = cx88_boards[core->board].tuner_type;
b45009b0
MCC
1133 if (UNSET == core->radio_type)
1134 core->radio_type = cx88_boards[core->board].radio_type;
1135 if (!core->tuner_addr)
1136 core->tuner_addr = cx88_boards[core->board].tuner_addr;
1137 if (!core->radio_addr)
1138 core->radio_addr = cx88_boards[core->board].radio_addr;
1139
4ac97914 1140 printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
b45009b0
MCC
1141 core->tuner_type, core->tuner_addr<<1,
1142 core->radio_type, core->radio_addr<<1);
1143
1da177e4
LT
1144 core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
1145
1146 /* init hardware */
1147 cx88_reset(core);
1148 cx88_i2c_init(core,pci);
87f07831 1149 cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
1da177e4
LT
1150 cx88_card_setup(core);
1151 cx88_ir_init(core,pci);
1152
1153 up(&devlist);
1154 return core;
1155
1156fail_free:
1157 kfree(core);
1158fail_unlock:
1159 up(&devlist);
1160 return NULL;
1161}
1162
1163void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1164{
1165 release_mem_region(pci_resource_start(pci,0),
1166 pci_resource_len(pci,0));
1167
1168 if (!atomic_dec_and_test(&core->refcount))
1169 return;
1170
1171 down(&devlist);
1172 cx88_ir_fini(core);
1173 if (0 == core->i2c_rc)
1174 i2c_bit_del_bus(&core->i2c_adap);
1175 list_del(&core->devlist);
1176 iounmap(core->lmmio);
1177 cx88_devcount--;
1178 up(&devlist);
1179 kfree(core);
1180}
1181
1182/* ------------------------------------------------------------------ */
1183
1184EXPORT_SYMBOL(cx88_print_ioctl);
1da177e4
LT
1185EXPORT_SYMBOL(cx88_print_irqbits);
1186
1187EXPORT_SYMBOL(cx88_core_irq);
1188EXPORT_SYMBOL(cx88_wakeup);
1189EXPORT_SYMBOL(cx88_reset);
1190EXPORT_SYMBOL(cx88_shutdown);
1191
1192EXPORT_SYMBOL(cx88_risc_buffer);
1193EXPORT_SYMBOL(cx88_risc_databuffer);
1194EXPORT_SYMBOL(cx88_risc_stopper);
1195EXPORT_SYMBOL(cx88_free_buffer);
1196
1197EXPORT_SYMBOL(cx88_sram_channels);
1198EXPORT_SYMBOL(cx88_sram_channel_setup);
1199EXPORT_SYMBOL(cx88_sram_channel_dump);
1200
1201EXPORT_SYMBOL(cx88_set_tvnorm);
1202EXPORT_SYMBOL(cx88_set_scale);
1203
1204EXPORT_SYMBOL(cx88_vdev_init);
1205EXPORT_SYMBOL(cx88_core_get);
1206EXPORT_SYMBOL(cx88_core_put);
1207
1208/*
1209 * Local variables:
1210 * c-basic-offset: 8
1211 * End:
e52e98a7 1212 * 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 1213 */