ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / media / video / cx88 / cx88-core.c
1 /*
2  * device driver for Conexant 2388x based TV cards
3  * driver core
4  *
5  * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <linux/init.h>
23 #include <linux/list.h>
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 #include <linux/kmod.h>
28 #include <linux/sound.h>
29 #include <linux/interrupt.h>
30 #include <linux/pci.h>
31 #include <linux/videodev.h>
32
33 #include "cx88.h"
34
35 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
36 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
37 MODULE_LICENSE("GPL");
38
39 /* ------------------------------------------------------------------ */
40
41 #if 0
42 static unsigned int gpio_tracking = 0;
43 MODULE_PARM(gpio_tracking,"i");
44 MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
45
46 static unsigned int ts_nr = -1;
47 MODULE_PARM(ts_nr,"i");
48 MODULE_PARM_DESC(ts_nr,"ts device number");
49
50 static unsigned int vbi_nr = -1;
51 MODULE_PARM(vbi_nr,"i");
52 MODULE_PARM_DESC(vbi_nr,"vbi device number");
53
54 static unsigned int radio_nr = -1;
55 MODULE_PARM(radio_nr,"i");
56 MODULE_PARM_DESC(radio_nr,"radio device number");
57
58 static unsigned int oss = 0;
59 MODULE_PARM(oss,"i");
60 MODULE_PARM_DESC(oss,"register oss devices (default: no)");
61
62 static unsigned int dsp_nr = -1;
63 MODULE_PARM(dsp_nr,"i");
64 MODULE_PARM_DESC(dsp_nr,"oss dsp device number");
65
66 static unsigned int mixer_nr = -1;
67 MODULE_PARM(mixer_nr,"i");
68 MODULE_PARM_DESC(mixer_nr,"oss mixer device number");
69 #endif
70
71 static unsigned int core_debug = 0;
72 MODULE_PARM(core_debug,"i");
73 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
74
75 #define dprintk(fmt, arg...)    if (core_debug) \
76         printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
77
78 /* ------------------------------------------------------------------ */
79 /* debug help functions                                               */
80
81 static const char *v4l1_ioctls[] = {
82         "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
83         "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
84         "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
85         "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
86         "SMICROCODE", "GVBIFMT", "SVBIFMT" };
87 #define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
88
89 static const char *v4l2_ioctls[] = {
90         "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
91         "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
92         "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
93         "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
94         "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
95         "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
96         "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
97         "44", "45",  "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
98         "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
99         "S_MODULATOR"
100 };
101 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
102
103 void cx88_print_ioctl(char *name, unsigned int cmd)
104 {
105         char *dir;
106
107         switch (_IOC_DIR(cmd)) {
108         case _IOC_NONE:              dir = "--"; break;
109         case _IOC_READ:              dir = "r-"; break;
110         case _IOC_WRITE:             dir = "-w"; break;
111         case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
112         default:                     dir = "??"; break;
113         }
114         switch (_IOC_TYPE(cmd)) {
115         case 'v':
116                 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
117                        name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
118                        v4l1_ioctls[_IOC_NR(cmd)] : "???");
119                 break;
120         case 'V':
121                 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
122                        name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
123                        v4l2_ioctls[_IOC_NR(cmd)] : "???");
124                 break;
125         default:
126                 printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
127                        name, cmd, dir, _IOC_NR(cmd));
128         }
129 }
130
131 /* ------------------------------------------------------------------ */
132
133 static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
134                             unsigned int offset, u32 sync_line,
135                             unsigned int bpl, unsigned int padding,
136                             unsigned int lines)
137 {
138         struct scatterlist *sg;
139         unsigned int line,todo;
140
141         /* sync instruction */
142         *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
143         
144         /* scan lines */
145         sg = sglist;
146         for (line = 0; line < lines; line++) {
147                 while (offset && offset >= sg_dma_len(sg)) {
148                         offset -= sg_dma_len(sg);
149                         sg++;
150                 }
151                 if (bpl <= sg_dma_len(sg)-offset) {
152                         /* fits into current chunk */
153                         *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
154                         *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
155                         offset+=bpl;
156                 } else {
157                         /* scanline needs to be splitted */
158                         todo = bpl;
159                         *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
160                                             (sg_dma_len(sg)-offset));
161                         *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
162                         todo -= (sg_dma_len(sg)-offset);
163                         offset = 0;
164                         sg++;
165                         while (todo > sg_dma_len(sg)) {
166                                 *(rp++)=cpu_to_le32(RISC_WRITE|
167                                                     sg_dma_len(sg));
168                                 *(rp++)=cpu_to_le32(sg_dma_address(sg));
169                                 todo -= sg_dma_len(sg);
170                                 sg++;
171                         }
172                         *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
173                         *(rp++)=cpu_to_le32(sg_dma_address(sg));
174                         offset += todo;
175                 }
176                 offset += padding;
177         }
178
179         return rp;
180 }
181
182 int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
183                      struct scatterlist *sglist,
184                      unsigned int top_offset, unsigned int bottom_offset,
185                      unsigned int bpl, unsigned int padding, unsigned int lines)
186 {
187         u32 instructions,fields;
188         u32 *rp;
189         int rc;
190
191         fields = 0;
192         if (UNSET != top_offset)
193                 fields++;
194         if (UNSET != bottom_offset)
195                 fields++;
196
197         /* estimate risc mem: worst case is one write per page border +
198            one write per scan line + syncs + jump (all 2 dwords) */
199         instructions  = (bpl * lines * fields) / PAGE_SIZE + lines * fields;
200         instructions += 3 + 4;
201         if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
202                 return rc;
203
204         /* write risc instructions */
205         rp = risc->cpu;
206         if (UNSET != top_offset)
207                 rp = cx88_risc_field(rp, sglist, top_offset, 0,
208                                      bpl, padding, lines);
209         if (UNSET != bottom_offset)
210                 rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
211                                      bpl, padding, lines);
212
213         /* save pointer to jmp instruction address */
214         risc->jmp = rp;
215         return 0;
216 }
217
218 int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
219                       u32 reg, u32 mask, u32 value)
220 {
221         u32 *rp;
222         int rc;
223
224         if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
225                 return rc;
226
227         /* write risc instructions */
228         rp = risc->cpu;
229         *(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2 | RISC_IMM);
230         *(rp++) = cpu_to_le32(reg);
231         *(rp++) = cpu_to_le32(value);
232         *(rp++) = cpu_to_le32(mask);
233         *(rp++) = cpu_to_le32(RISC_JUMP);
234         *(rp++) = cpu_to_le32(risc->dma);
235         return 0;
236 }
237
238 void
239 cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
240 {
241         if (in_interrupt())
242                 BUG();
243         videobuf_waiton(&buf->vb,0,0);
244         videobuf_dma_pci_unmap(pci, &buf->vb.dma);
245         videobuf_dma_free(&buf->vb.dma);
246         btcx_riscmem_free(pci, &buf->risc);
247         buf->vb.state = STATE_NEEDS_INIT;
248 }
249
250 /* ------------------------------------------------------------------ */
251 /* our SRAM memory layout                                             */
252
253 /* we are going to put all thr risc programs into host memory, so we
254  * can use the whole SDRAM for the DMA fifos.  To simplify things, we
255  * use a static memory layout.  That surely will waste memory in case
256  * we don't use all DMA channels at the same time (which will be the
257  * case most of the time).  But that still gives us enougth FIFO space
258  * to be able to deal with insane long pci latencies ...
259  *
260  * FIFO space allocations:
261  *    channel  21    (y video)  - 10.0k
262  *    channel  24    (vbi)      -  4.0k
263  *    channels 25+26 (audio)    -  0.5k
264  *    everything else           -  2.0k
265  *    TOTAL                     = 29.0k
266  *
267  * Every channel has 160 bytes control data (64 bytes instruction
268  * queue and 6 CDT entries), which is close to 2k total.
269  * 
270  * Address layout:
271  *    0x0000 - 0x03ff    CMDs / reserved
272  *    0x0400 - 0x0bff    instruction queues + CDs
273  *    0x0c00 -           FIFOs
274  */
275
276 struct sram_channel cx88_sram_channels[] = {
277         [SRAM_CH21] = {
278                 .name       = "video y / packed",
279                 .cmds_start = 0x180040,
280                 .ctrl_start = 0x180400,
281                 .cdt        = 0x180400 + 64,
282                 .fifo_start = 0x180c00,
283                 .fifo_size  = 0x002800,
284                 .ptr1_reg   = MO_DMA21_PTR1,
285                 .ptr2_reg   = MO_DMA21_PTR2,
286                 .cnt1_reg   = MO_DMA21_CNT1,
287                 .cnt2_reg   = MO_DMA21_CNT2,
288         },
289         [SRAM_CH22] = {
290                 .name       = "video u",
291                 .cmds_start = 0x180080,
292                 .ctrl_start = 0x1804a0,
293                 .cdt        = 0x1804a0 + 64,
294                 .fifo_start = 0x183400,
295                 .fifo_size  = 0x000800,
296                 .ptr1_reg   = MO_DMA22_PTR1,
297                 .ptr2_reg   = MO_DMA22_PTR2,
298                 .cnt1_reg   = MO_DMA22_CNT1,
299                 .cnt2_reg   = MO_DMA22_CNT2,
300         },
301         [SRAM_CH23] = {
302                 .name       = "video v",
303                 .cmds_start = 0x1800c0,
304                 .ctrl_start = 0x180540,
305                 .cdt        = 0x180540 + 64,
306                 .fifo_start = 0x183c00,
307                 .fifo_size  = 0x000800,
308                 .ptr1_reg   = MO_DMA23_PTR1,
309                 .ptr2_reg   = MO_DMA23_PTR2,
310                 .cnt1_reg   = MO_DMA23_CNT1,
311                 .cnt2_reg   = MO_DMA23_CNT2,
312         },
313         [SRAM_CH24] = {
314                 .name       = "vbi",
315                 .cmds_start = 0x180100,
316                 .ctrl_start = 0x1805e0,
317                 .cdt        = 0x1805e0 + 64,
318                 .fifo_start = 0x184400,
319                 .fifo_size  = 0x001000,
320                 .ptr1_reg   = MO_DMA24_PTR1,
321                 .ptr2_reg   = MO_DMA24_PTR2,
322                 .cnt1_reg   = MO_DMA24_CNT1,
323                 .cnt2_reg   = MO_DMA24_CNT2,
324         },
325         [SRAM_CH25] = {
326                 .name       = "audio from",
327                 .cmds_start = 0x180140,
328                 .ctrl_start = 0x180680,
329                 .cdt        = 0x180680 + 64,
330                 .fifo_start = 0x185400,
331                 .fifo_size  = 0x000200,
332                 .ptr1_reg   = MO_DMA25_PTR1,
333                 .ptr2_reg   = MO_DMA25_PTR2,
334                 .cnt1_reg   = MO_DMA25_CNT1,
335                 .cnt2_reg   = MO_DMA25_CNT2,
336         },
337         [SRAM_CH26] = {
338                 .name       = "audio to",
339                 .cmds_start = 0x180180,
340                 .ctrl_start = 0x180720,
341                 .cdt        = 0x180680 + 64,  /* same as audio IN */
342                 .fifo_start = 0x185400,       /* same as audio IN */
343                 .fifo_size  = 0x000200,       /* same as audio IN */
344                 .ptr1_reg   = MO_DMA26_PTR1,
345                 .ptr2_reg   = MO_DMA26_PTR2,
346                 .cnt1_reg   = MO_DMA26_CNT1,
347                 .cnt2_reg   = MO_DMA26_CNT2,
348         },
349 };
350
351 int cx88_sram_channel_setup(struct cx8800_dev *dev,
352                             struct sram_channel *ch,
353                             unsigned int bpl, u32 risc)
354 {
355         unsigned int i,lines;
356         u32 cdt;
357
358         bpl   = (bpl + 7) & ~7; /* alignment */
359         cdt   = ch->cdt;
360         lines = ch->fifo_size / bpl;
361         if (lines > 6)
362                 lines = 6;
363         BUG_ON(lines < 2);
364
365         /* write CDT */
366         for (i = 0; i < lines; i++)
367                 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
368
369         /* write CMDS */
370         cx_write(ch->cmds_start +  0, risc);
371         cx_write(ch->cmds_start +  4, cdt);
372         cx_write(ch->cmds_start +  8, (lines*16) >> 3);
373         cx_write(ch->cmds_start + 12, ch->ctrl_start);
374         cx_write(ch->cmds_start + 16, 64 >> 2);
375         for (i = 20; i < 64; i += 4)
376                 cx_write(ch->cmds_start + i, 0);
377
378         /* fill registers */
379         cx_write(ch->ptr1_reg, ch->fifo_start);
380         cx_write(ch->ptr2_reg, cdt);
381         cx_write(ch->cnt1_reg, bpl >> 3);
382         cx_write(ch->cnt2_reg, (lines*16) >> 3);
383
384         dprintk("sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
385         return 0;
386 }
387
388 /* ------------------------------------------------------------------ */
389 /* debug helper code                                                  */
390
391 int cx88_risc_decode(u32 risc)
392 {
393         static char *instr[16] = {
394                 [ RISC_SYNC    >> 28 ] = "sync",
395                 [ RISC_WRITE   >> 28 ] = "write",
396                 [ RISC_WRITEC  >> 28 ] = "writec",
397                 [ RISC_READ    >> 28 ] = "read",
398                 [ RISC_READC   >> 28 ] = "readc",
399                 [ RISC_JUMP    >> 28 ] = "jump",
400                 [ RISC_SKIP    >> 28 ] = "skip",
401                 [ RISC_WRITERM >> 28 ] = "writerm",
402                 [ RISC_WRITECM >> 28 ] = "writecm",
403                 [ RISC_WRITECR >> 28 ] = "writecr",
404         };
405         static int incr[16] = {
406                 [ RISC_WRITE   >> 28 ] = 2,
407                 [ RISC_JUMP    >> 28 ] = 2,
408                 [ RISC_WRITERM >> 28 ] = 3,
409                 [ RISC_WRITECM >> 28 ] = 3,
410                 [ RISC_WRITECR >> 28 ] = 4,
411         };
412         static char *bits[] = {
413                 "12",   "13",   "14",   "resync",
414                 "cnt0", "cnt1", "18",   "19",
415                 "20",   "21",   "22",   "23",
416                 "irq1", "irq2", "eol",  "sol",
417         };
418         int i;
419
420         printk("0x%08x [ %s", risc,
421                instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
422         for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
423                 if (risc & (1 << (i + 12)))
424                         printk(" %s",bits[i]);
425         printk(" count=%d ]\n", risc & 0xfff);
426         return incr[risc >> 28] ? incr[risc >> 28] : 1;
427 }
428
429 void cx88_risc_disasm(struct cx8800_dev *dev,
430                       struct btcx_riscmem *risc)
431 {
432         unsigned int i,j,n;
433         
434         printk("%s: risc disasm: %p [dma=0x%08lx]\n",
435                dev->name, risc->cpu, (unsigned long)risc->dma);
436         for (i = 0; i < (risc->size >> 2); i += n) {
437                 printk("%s:   %04d: ", dev->name, i);
438                 n = cx88_risc_decode(risc->cpu[i]);
439                 for (j = 1; j < n; j++)
440                         printk("%s:   %04d: 0x%08x [ arg #%d ]\n",
441                                dev->name, i+j, risc->cpu[i+j], j);
442                 if (risc->cpu[i] == RISC_JUMP)
443                         break;
444         }
445 }
446
447 void cx88_sram_channel_dump(struct cx8800_dev *dev,
448                             struct sram_channel *ch)
449 {
450         static char *name[] = {
451                 "initial risc",
452                 "cdt base",
453                 "cdt size",
454                 "iq base",
455                 "iq size",
456                 "risc pc",
457                 "iq wr ptr",
458                 "iq rd ptr",
459                 "cdt current",
460                 "pci target",
461                 "line / byte",
462         };
463         u32 risc;
464         unsigned int i,j,n;
465
466         printk("%s: %s - dma channel status dump\n",dev->name,ch->name);
467         for (i = 0; i < ARRAY_SIZE(name); i++)
468                 printk("%s:   cmds: %-12s: 0x%08x\n",
469                        dev->name,name[i],
470                        cx_read(ch->cmds_start + 4*i));
471         for (i = 0; i < 4; i++) {
472                 risc = cx_read(ch->cmds_start + 4 * (i+11));
473                 printk("%s:   risc%d: ", dev->name, i);
474                 cx88_risc_decode(risc);
475         }
476         for (i = 0; i < 16; i += n) {
477                 risc = cx_read(ch->ctrl_start + 4 * i);
478                 printk("%s:   iq %x: ", dev->name, i);
479                 n = cx88_risc_decode(risc);
480                 for (j = 1; j < n; j++) {
481                         risc = cx_read(ch->ctrl_start + 4 * (i+j));
482                         printk("%s:   iq %x: 0x%08x [ arg #%d ]\n",
483                                dev->name, i+j, risc, j);
484                 }
485         }
486
487         printk("%s: fifo: 0x%08x -> 0x%x\n",
488                dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
489         printk("%s: ctrl: 0x%08x -> 0x%x\n",
490                dev->name, ch->ctrl_start, ch->ctrl_start+6*16);
491         printk("%s:   ptr1_reg: 0x%08x\n",
492                dev->name,cx_read(ch->ptr1_reg));
493         printk("%s:   ptr2_reg: 0x%08x\n",
494                dev->name,cx_read(ch->ptr2_reg));
495         printk("%s:   cnt1_reg: 0x%08x\n",
496                dev->name,cx_read(ch->cnt1_reg));
497         printk("%s:   cnt2_reg: 0x%08x\n",
498                dev->name,cx_read(ch->cnt2_reg));
499 }
500
501 char *cx88_pci_irqs[32] = {
502         "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1", 
503         "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
504         "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
505         "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
506 };
507 char *cx88_vid_irqs[32] = {
508         "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", 
509         "y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
510         "y_oflow",  "u_oflow",  "v_oflow",  "vbi_oflow",
511         "y_sync",   "u_sync",   "v_sync",   "vbi_sync",
512         "opc_err",  "par_err",  "rip_err",  "pci_abort",
513 };
514
515 void cx88_print_irqbits(char *name, char *tag, char **strings,
516                         u32 bits, u32 mask)
517 {
518         unsigned int i;
519
520         printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
521         for (i = 0; i < 32; i++) {
522                 if (!(bits & (1 << i)))
523                         continue;
524                 printk(" %s",strings[i]);
525                 if (!(mask & (1 << i)))
526                         continue;
527                 printk("*");
528         }
529         printk("\n");
530 }
531
532 /* ------------------------------------------------------------------ */
533
534 int cx88_pci_quirks(char *name, struct pci_dev *pci, unsigned int *latency)
535 {
536         u8 ctrl = 0;
537         u8 value;
538
539         if (0 == pci_pci_problems)
540                 return 0;
541
542         if (pci_pci_problems & PCIPCI_TRITON) {
543                 printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
544                        name);
545                 ctrl |= CX88X_EN_TBFX;
546         }
547         if (pci_pci_problems & PCIPCI_NATOMA) {
548                 printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
549                        name);
550                 ctrl |= CX88X_EN_TBFX;
551         }
552         if (pci_pci_problems & PCIPCI_VIAETBF) {
553                 printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
554                        name);
555                 ctrl |= CX88X_EN_TBFX;
556         }
557         if (pci_pci_problems & PCIPCI_VSFX) {
558                 printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
559                        name);
560                 ctrl |= CX88X_EN_VSFX;
561         }
562 #ifdef PCIPCI_ALIMAGIK
563         if (pci_pci_problems & PCIPCI_ALIMAGIK) {
564                 printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
565                        name);
566                 *latency = 0x0A;
567         }
568 #endif
569         if (ctrl) {
570                 pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
571                 value |= ctrl;
572                 pci_write_config_byte(pci, CX88X_DEVCTRL, value);
573         }
574         return 0;
575 }
576
577 /* ------------------------------------------------------------------ */
578
579 EXPORT_SYMBOL(cx88_print_ioctl);
580 EXPORT_SYMBOL(cx88_pci_irqs);
581 EXPORT_SYMBOL(cx88_vid_irqs);
582 EXPORT_SYMBOL(cx88_print_irqbits);
583
584 EXPORT_SYMBOL(cx88_risc_buffer);
585 EXPORT_SYMBOL(cx88_risc_stopper);
586 EXPORT_SYMBOL(cx88_free_buffer);
587
588 EXPORT_SYMBOL(cx88_risc_disasm);
589
590 EXPORT_SYMBOL(cx88_sram_channels);
591 EXPORT_SYMBOL(cx88_sram_channel_setup);
592 EXPORT_SYMBOL(cx88_sram_channel_dump);
593
594 EXPORT_SYMBOL(cx88_pci_quirks);
595
596 /*
597  * Local variables:
598  * c-basic-offset: 8
599  * End:
600  */