aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/video/cx88
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r--drivers/media/video/cx88/Kconfig86
-rw-r--r--drivers/media/video/cx88/Makefile16
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c992
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c1385
-rw-r--r--drivers/media/video/cx88/cx88-cards.c3699
-rw-r--r--drivers/media/video/cx88/cx88-core.c1129
-rw-r--r--drivers/media/video/cx88/cx88-dsp.c322
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c1764
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c184
-rw-r--r--drivers/media/video/cx88/cx88-input.c631
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c929
-rw-r--r--drivers/media/video/cx88/cx88-reg.h836
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c1059
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c245
-rw-r--r--drivers/media/video/cx88/cx88-video.c2194
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.c159
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.h41
-rw-r--r--drivers/media/video/cx88/cx88.h730
18 files changed, 16401 insertions, 0 deletions
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
new file mode 100644
index 00000000000..5c42abdf422
--- /dev/null
+++ b/drivers/media/video/cx88/Kconfig
@@ -0,0 +1,86 @@
1config VIDEO_CX88
2 tristate "Conexant 2388x (bt878 successor) support"
3 depends on VIDEO_DEV && PCI && I2C && RC_CORE
4 select I2C_ALGOBIT
5 select VIDEO_BTCX
6 select VIDEOBUF_DMA_SG
7 select VIDEO_TUNER
8 select VIDEO_TVEEPROM
9 select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO
10 ---help---
11 This is a video4linux driver for Conexant 2388x based
12 TV cards.
13
14 To compile this driver as a module, choose M here: the
15 module will be called cx8800
16
17config VIDEO_CX88_ALSA
18 tristate "Conexant 2388x DMA audio support"
19 depends on VIDEO_CX88 && SND
20 select SND_PCM
21 ---help---
22 This is a video4linux driver for direct (DMA) audio on
23 Conexant 2388x based TV cards using ALSA.
24
25 It only works with boards with function 01 enabled.
26 To check if your board supports, use lspci -n.
27 If supported, you should see 14f1:8801 or 14f1:8811
28 PCI device.
29
30 To compile this driver as a module, choose M here: the
31 module will be called cx88-alsa.
32
33config VIDEO_CX88_BLACKBIRD
34 tristate "Blackbird MPEG encoder support (cx2388x + cx23416)"
35 depends on VIDEO_CX88
36 select VIDEO_CX2341X
37 ---help---
38 This adds support for MPEG encoder cards based on the
39 Blackbird reference design, using the Conexant 2388x
40 and 23416 chips.
41
42 To compile this driver as a module, choose M here: the
43 module will be called cx88-blackbird.
44
45config VIDEO_CX88_DVB
46 tristate "DVB/ATSC Support for cx2388x based TV cards"
47 depends on VIDEO_CX88 && DVB_CORE
48 select VIDEOBUF_DVB
49 select DVB_PLL if !DVB_FE_CUSTOMISE
50 select DVB_MT352 if !DVB_FE_CUSTOMISE
51 select DVB_ZL10353 if !DVB_FE_CUSTOMISE
52 select DVB_OR51132 if !DVB_FE_CUSTOMISE
53 select DVB_CX22702 if !DVB_FE_CUSTOMISE
54 select DVB_LGDT330X if !DVB_FE_CUSTOMISE
55 select DVB_NXT200X if !DVB_FE_CUSTOMISE
56 select DVB_CX24123 if !DVB_FE_CUSTOMISE
57 select DVB_ISL6421 if !DVB_FE_CUSTOMISE
58 select DVB_S5H1411 if !DVB_FE_CUSTOMISE
59 select DVB_CX24116 if !DVB_FE_CUSTOMISE
60 select DVB_STV0299 if !DVB_FE_CUSTOMISE
61 select DVB_STV0288 if !DVB_FE_CUSTOMISE
62 select DVB_STB6000 if !DVB_FE_CUSTOMISE
63 select DVB_STV0900 if !DVB_FE_CUSTOMISE
64 select DVB_STB6100 if !DVB_FE_CUSTOMISE
65 select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
66 ---help---
67 This adds support for DVB/ATSC cards based on the
68 Conexant 2388x chip.
69
70 To compile this driver as a module, choose M here: the
71 module will be called cx88-dvb.
72
73config VIDEO_CX88_MPEG
74 tristate
75 depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
76 default y
77
78config VIDEO_CX88_VP3054
79 tristate "VP-3054 Secondary I2C Bus Support"
80 default m
81 depends on VIDEO_CX88_DVB && DVB_MT352
82 ---help---
83 This adds DVB-T support for cards based on the
84 Conexant 2388x chip and the MT352 demodulator,
85 which also require support for the VP-3054
86 Secondary I2C bus, such at DNTV Live! DVB-T Pro.
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
new file mode 100644
index 00000000000..5b7e26761f0
--- /dev/null
+++ b/drivers/media/video/cx88/Makefile
@@ -0,0 +1,16 @@
1cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
2 cx88-dsp.o cx88-input.o
3cx8800-objs := cx88-video.o cx88-vbi.o
4cx8802-objs := cx88-mpeg.o
5
6obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o
7obj-$(CONFIG_VIDEO_CX88_MPEG) += cx8802.o
8obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
9obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o
10obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
11obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
12
13EXTRA_CFLAGS += -Idrivers/media/video
14EXTRA_CFLAGS += -Idrivers/media/common/tuners
15EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
16EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
new file mode 100644
index 00000000000..68d1240f493
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -0,0 +1,992 @@
1/*
2 *
3 * Support for audio capture
4 * PCI function #1 of the cx2388x.
5 *
6 * (c) 2007 Trent Piepho <xyzzy@speakeasy.org>
7 * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
8 * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
9 * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
10 * Based on dummy.c by Jaroslav Kysela <perex@perex.cz>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/device.h>
30#include <linux/interrupt.h>
31#include <linux/vmalloc.h>
32#include <linux/dma-mapping.h>
33#include <linux/pci.h>
34#include <linux/slab.h>
35
36#include <asm/delay.h>
37#include <sound/core.h>
38#include <sound/pcm.h>
39#include <sound/pcm_params.h>
40#include <sound/control.h>
41#include <sound/initval.h>
42#include <sound/tlv.h>
43#include <media/wm8775.h>
44
45#include "cx88.h"
46#include "cx88-reg.h"
47
48#define dprintk(level,fmt, arg...) if (debug >= level) \
49 printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg)
50
51#define dprintk_core(level,fmt, arg...) if (debug >= level) \
52 printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg)
53
54/****************************************************************************
55 Data type declarations - Can be moded to a header file later
56 ****************************************************************************/
57
58struct cx88_audio_buffer {
59 unsigned int bpl;
60 struct btcx_riscmem risc;
61 struct videobuf_dmabuf dma;
62};
63
64struct cx88_audio_dev {
65 struct cx88_core *core;
66 struct cx88_dmaqueue q;
67
68 /* pci i/o */
69 struct pci_dev *pci;
70
71 /* audio controls */
72 int irq;
73
74 struct snd_card *card;
75
76 spinlock_t reg_lock;
77 atomic_t count;
78
79 unsigned int dma_size;
80 unsigned int period_size;
81 unsigned int num_periods;
82
83 struct videobuf_dmabuf *dma_risc;
84
85 struct cx88_audio_buffer *buf;
86
87 struct snd_pcm_substream *substream;
88};
89typedef struct cx88_audio_dev snd_cx88_card_t;
90
91
92
93/****************************************************************************
94 Module global static vars
95 ****************************************************************************/
96
97static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
98static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
99static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
100
101module_param_array(enable, bool, NULL, 0444);
102MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
103
104module_param_array(index, int, NULL, 0444);
105MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s).");
106
107
108/****************************************************************************
109 Module macros
110 ****************************************************************************/
111
112MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
113MODULE_AUTHOR("Ricardo Cerqueira");
114MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
115MODULE_LICENSE("GPL");
116MODULE_VERSION(CX88_VERSION);
117
118MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
119 "{{Conexant,23882},"
120 "{{Conexant,23883}");
121static unsigned int debug;
122module_param(debug,int,0644);
123MODULE_PARM_DESC(debug,"enable debug messages");
124
125/****************************************************************************
126 Module specific funtions
127 ****************************************************************************/
128
129/*
130 * BOARD Specific: Sets audio DMA
131 */
132
133static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
134{
135 struct cx88_audio_buffer *buf = chip->buf;
136 struct cx88_core *core=chip->core;
137 const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
138
139 /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
140 cx_clear(MO_AUD_DMACNTRL, 0x11);
141
142 /* setup fifo + format - out channel */
143 cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma);
144
145 /* sets bpl size */
146 cx_write(MO_AUDD_LNGTH, buf->bpl);
147
148 /* reset counter */
149 cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
150 atomic_set(&chip->count, 0);
151
152 dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
153 "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1,
154 chip->num_periods, buf->bpl * chip->num_periods);
155
156 /* Enables corresponding bits at AUD_INT_STAT */
157 cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
158 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
159
160 /* Clean any pending interrupt bits already set */
161 cx_write(MO_AUD_INTSTAT, ~0);
162
163 /* enable audio irqs */
164 cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT);
165
166 /* start dma */
167 cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
168 cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */
169
170 if (debug)
171 cx88_sram_channel_dump(chip->core, audio_ch);
172
173 return 0;
174}
175
176/*
177 * BOARD Specific: Resets audio DMA
178 */
179static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
180{
181 struct cx88_core *core=chip->core;
182 dprintk(1, "Stopping audio DMA\n");
183
184 /* stop dma */
185 cx_clear(MO_AUD_DMACNTRL, 0x11);
186
187 /* disable irqs */
188 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
189 cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
190 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
191
192 if (debug)
193 cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
194
195 return 0;
196}
197
198#define MAX_IRQ_LOOP 50
199
200/*
201 * BOARD Specific: IRQ dma bits
202 */
203static const char *cx88_aud_irqs[32] = {
204 "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
205 NULL, /* reserved */
206 "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
207 NULL, /* reserved */
208 "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */
209 NULL, /* reserved */
210 "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */
211 NULL, /* reserved */
212 "opc_err", "par_err", "rip_err", /* 16-18 */
213 "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */
214};
215
216/*
217 * BOARD Specific: Threats IRQ audio specific calls
218 */
219static void cx8801_aud_irq(snd_cx88_card_t *chip)
220{
221 struct cx88_core *core = chip->core;
222 u32 status, mask;
223
224 status = cx_read(MO_AUD_INTSTAT);
225 mask = cx_read(MO_AUD_INTMSK);
226 if (0 == (status & mask))
227 return;
228 cx_write(MO_AUD_INTSTAT, status);
229 if (debug > 1 || (status & mask & ~0xff))
230 cx88_print_irqbits(core->name, "irq aud",
231 cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs),
232 status, mask);
233 /* risc op code error */
234 if (status & AUD_INT_OPC_ERR) {
235 printk(KERN_WARNING "%s/1: Audio risc op code error\n",core->name);
236 cx_clear(MO_AUD_DMACNTRL, 0x11);
237 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]);
238 }
239 if (status & AUD_INT_DN_SYNC) {
240 dprintk(1, "Downstream sync error\n");
241 cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
242 return;
243 }
244 /* risc1 downstream */
245 if (status & AUD_INT_DN_RISCI1) {
246 atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT));
247 snd_pcm_period_elapsed(chip->substream);
248 }
249 /* FIXME: Any other status should deserve a special handling? */
250}
251
252/*
253 * BOARD Specific: Handles IRQ calls
254 */
255static irqreturn_t cx8801_irq(int irq, void *dev_id)
256{
257 snd_cx88_card_t *chip = dev_id;
258 struct cx88_core *core = chip->core;
259 u32 status;
260 int loop, handled = 0;
261
262 for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
263 status = cx_read(MO_PCI_INTSTAT) &
264 (core->pci_irqmask | PCI_INT_AUDINT);
265 if (0 == status)
266 goto out;
267 dprintk(3, "cx8801_irq loop %d/%d, status %x\n",
268 loop, MAX_IRQ_LOOP, status);
269 handled = 1;
270 cx_write(MO_PCI_INTSTAT, status);
271
272 if (status & core->pci_irqmask)
273 cx88_core_irq(core, status);
274 if (status & PCI_INT_AUDINT)
275 cx8801_aud_irq(chip);
276 }
277
278 if (MAX_IRQ_LOOP == loop) {
279 printk(KERN_ERR
280 "%s/1: IRQ loop detected, disabling interrupts\n",
281 core->name);
282 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
283 }
284
285 out:
286 return IRQ_RETVAL(handled);
287}
288
289
290static int dsp_buffer_free(snd_cx88_card_t *chip)
291{
292 BUG_ON(!chip->dma_size);
293
294 dprintk(2,"Freeing buffer\n");
295 videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
296 videobuf_dma_free(chip->dma_risc);
297 btcx_riscmem_free(chip->pci,&chip->buf->risc);
298 kfree(chip->buf);
299
300 chip->dma_risc = NULL;
301 chip->dma_size = 0;
302
303 return 0;
304}
305
306/****************************************************************************
307 ALSA PCM Interface
308 ****************************************************************************/
309
310/*
311 * Digital hardware definition
312 */
313#define DEFAULT_FIFO_SIZE 4096
314static const struct snd_pcm_hardware snd_cx88_digital_hw = {
315 .info = SNDRV_PCM_INFO_MMAP |
316 SNDRV_PCM_INFO_INTERLEAVED |
317 SNDRV_PCM_INFO_BLOCK_TRANSFER |
318 SNDRV_PCM_INFO_MMAP_VALID,
319 .formats = SNDRV_PCM_FMTBIT_S16_LE,
320
321 .rates = SNDRV_PCM_RATE_48000,
322 .rate_min = 48000,
323 .rate_max = 48000,
324 .channels_min = 2,
325 .channels_max = 2,
326 /* Analog audio output will be full of clicks and pops if there
327 are not exactly four lines in the SRAM FIFO buffer. */
328 .period_bytes_min = DEFAULT_FIFO_SIZE/4,
329 .period_bytes_max = DEFAULT_FIFO_SIZE/4,
330 .periods_min = 1,
331 .periods_max = 1024,
332 .buffer_bytes_max = (1024*1024),
333};
334
335/*
336 * audio pcm capture open callback
337 */
338static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
339{
340 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
341 struct snd_pcm_runtime *runtime = substream->runtime;
342 int err;
343
344 if (!chip) {
345 printk(KERN_ERR "BUG: cx88 can't find device struct."
346 " Can't proceed with open\n");
347 return -ENODEV;
348 }
349
350 err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
351 if (err < 0)
352 goto _error;
353
354 chip->substream = substream;
355
356 runtime->hw = snd_cx88_digital_hw;
357
358 if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) {
359 unsigned int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4;
360 bpl &= ~7; /* must be multiple of 8 */
361 runtime->hw.period_bytes_min = bpl;
362 runtime->hw.period_bytes_max = bpl;
363 }
364
365 return 0;
366_error:
367 dprintk(1,"Error opening PCM!\n");
368 return err;
369}
370
371/*
372 * audio close callback
373 */
374static int snd_cx88_close(struct snd_pcm_substream *substream)
375{
376 return 0;
377}
378
379/*
380 * hw_params callback
381 */
382static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
383 struct snd_pcm_hw_params * hw_params)
384{
385 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
386 struct videobuf_dmabuf *dma;
387
388 struct cx88_audio_buffer *buf;
389 int ret;
390
391 if (substream->runtime->dma_area) {
392 dsp_buffer_free(chip);
393 substream->runtime->dma_area = NULL;
394 }
395
396 chip->period_size = params_period_bytes(hw_params);
397 chip->num_periods = params_periods(hw_params);
398 chip->dma_size = chip->period_size * params_periods(hw_params);
399
400 BUG_ON(!chip->dma_size);
401 BUG_ON(chip->num_periods & (chip->num_periods-1));
402
403 buf = kzalloc(sizeof(*buf), GFP_KERNEL);
404 if (NULL == buf)
405 return -ENOMEM;
406
407 buf->bpl = chip->period_size;
408
409 dma = &buf->dma;
410 videobuf_dma_init(dma);
411 ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
412 (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
413 if (ret < 0)
414 goto error;
415
416 ret = videobuf_dma_map(&chip->pci->dev, dma);
417 if (ret < 0)
418 goto error;
419
420 ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
421 chip->period_size, chip->num_periods, 1);
422 if (ret < 0)
423 goto error;
424
425 /* Loop back to start of program */
426 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
427 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
428
429 chip->buf = buf;
430 chip->dma_risc = dma;
431
432 substream->runtime->dma_area = chip->dma_risc->vaddr;
433 substream->runtime->dma_bytes = chip->dma_size;
434 substream->runtime->dma_addr = 0;
435 return 0;
436
437error:
438 kfree(buf);
439 return ret;
440}
441
442/*
443 * hw free callback
444 */
445static int snd_cx88_hw_free(struct snd_pcm_substream * substream)
446{
447
448 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
449
450 if (substream->runtime->dma_area) {
451 dsp_buffer_free(chip);
452 substream->runtime->dma_area = NULL;
453 }
454
455 return 0;
456}
457
458/*
459 * prepare callback
460 */
461static int snd_cx88_prepare(struct snd_pcm_substream *substream)
462{
463 return 0;
464}
465
466/*
467 * trigger callback
468 */
469static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd)
470{
471 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
472 int err;
473
474 /* Local interrupts are already disabled by ALSA */
475 spin_lock(&chip->reg_lock);
476
477 switch (cmd) {
478 case SNDRV_PCM_TRIGGER_START:
479 err=_cx88_start_audio_dma(chip);
480 break;
481 case SNDRV_PCM_TRIGGER_STOP:
482 err=_cx88_stop_audio_dma(chip);
483 break;
484 default:
485 err=-EINVAL;
486 break;
487 }
488
489 spin_unlock(&chip->reg_lock);
490
491 return err;
492}
493
494/*
495 * pointer callback
496 */
497static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
498{
499 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
500 struct snd_pcm_runtime *runtime = substream->runtime;
501 u16 count;
502
503 count = atomic_read(&chip->count);
504
505// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__,
506// count, new, count & (runtime->periods-1),
507// runtime->period_size * (count & (runtime->periods-1)));
508 return runtime->period_size * (count & (runtime->periods-1));
509}
510
511/*
512 * page callback (needed for mmap)
513 */
514static struct page *snd_cx88_page(struct snd_pcm_substream *substream,
515 unsigned long offset)
516{
517 void *pageptr = substream->runtime->dma_area + offset;
518 return vmalloc_to_page(pageptr);
519}
520
521/*
522 * operators
523 */
524static struct snd_pcm_ops snd_cx88_pcm_ops = {
525 .open = snd_cx88_pcm_open,
526 .close = snd_cx88_close,
527 .ioctl = snd_pcm_lib_ioctl,
528 .hw_params = snd_cx88_hw_params,
529 .hw_free = snd_cx88_hw_free,
530 .prepare = snd_cx88_prepare,
531 .trigger = snd_cx88_card_trigger,
532 .pointer = snd_cx88_pointer,
533 .page = snd_cx88_page,
534};
535
536/*
537 * create a PCM device
538 */
539static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name)
540{
541 int err;
542 struct snd_pcm *pcm;
543
544 err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
545 if (err < 0)
546 return err;
547 pcm->private_data = chip;
548 strcpy(pcm->name, name);
549 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops);
550
551 return 0;
552}
553
554/****************************************************************************
555 CONTROL INTERFACE
556 ****************************************************************************/
557static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol,
558 struct snd_ctl_elem_info *info)
559{
560 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
561 info->count = 2;
562 info->value.integer.min = 0;
563 info->value.integer.max = 0x3f;
564
565 return 0;
566}
567
568static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol,
569 struct snd_ctl_elem_value *value)
570{
571 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
572 struct cx88_core *core=chip->core;
573 int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f),
574 bal = cx_read(AUD_BAL_CTL);
575
576 value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol;
577 vol -= (bal & 0x3f);
578 value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol;
579
580 return 0;
581}
582
583static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
584 struct snd_ctl_elem_value *value)
585{
586 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
587 struct cx88_core *core = chip->core;
588 struct v4l2_control client_ctl;
589 int left = value->value.integer.value[0];
590 int right = value->value.integer.value[1];
591 int v, b;
592
593 memset(&client_ctl, 0, sizeof(client_ctl));
594
595 /* Pass volume & balance onto any WM8775 */
596 if (left >= right) {
597 v = left << 10;
598 b = left ? (0x8000 * right) / left : 0x8000;
599 } else {
600 v = right << 10;
601 b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
602 }
603 client_ctl.value = v;
604 client_ctl.id = V4L2_CID_AUDIO_VOLUME;
605 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
606
607 client_ctl.value = b;
608 client_ctl.id = V4L2_CID_AUDIO_BALANCE;
609 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
610}
611
612/* OK - TODO: test it */
613static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
614 struct snd_ctl_elem_value *value)
615{
616 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
617 struct cx88_core *core=chip->core;
618 int left, right, v, b;
619 int changed = 0;
620 u32 old;
621
622 if (core->board.audio_chip == V4L2_IDENT_WM8775)
623 snd_cx88_wm8775_volume_put(kcontrol, value);
624
625 left = value->value.integer.value[0] & 0x3f;
626 right = value->value.integer.value[1] & 0x3f;
627 b = right - left;
628 if (b < 0) {
629 v = 0x3f - left;
630 b = (-b) | 0x40;
631 } else {
632 v = 0x3f - right;
633 }
634 /* Do we really know this will always be called with IRQs on? */
635 spin_lock_irq(&chip->reg_lock);
636 old = cx_read(AUD_VOL_CTL);
637 if (v != (old & 0x3f)) {
638 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
639 changed = 1;
640 }
641 if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
642 cx_write(AUD_BAL_CTL, b);
643 changed = 1;
644 }
645 spin_unlock_irq(&chip->reg_lock);
646
647 return changed;
648}
649
650static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0);
651
652static const struct snd_kcontrol_new snd_cx88_volume = {
653 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
654 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
655 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
656 .name = "Analog-TV Volume",
657 .info = snd_cx88_volume_info,
658 .get = snd_cx88_volume_get,
659 .put = snd_cx88_volume_put,
660 .tlv.p = snd_cx88_db_scale,
661};
662
663static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol,
664 struct snd_ctl_elem_value *value)
665{
666 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
667 struct cx88_core *core = chip->core;
668 u32 bit = kcontrol->private_value;
669
670 value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit);
671 return 0;
672}
673
674static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
675 struct snd_ctl_elem_value *value)
676{
677 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
678 struct cx88_core *core = chip->core;
679 u32 bit = kcontrol->private_value;
680 int ret = 0;
681 u32 vol;
682
683 spin_lock_irq(&chip->reg_lock);
684 vol = cx_read(AUD_VOL_CTL);
685 if (value->value.integer.value[0] != !(vol & bit)) {
686 vol ^= bit;
687 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
688 /* Pass mute onto any WM8775 */
689 if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
690 ((1<<6) == bit)) {
691 struct v4l2_control client_ctl;
692
693 memset(&client_ctl, 0, sizeof(client_ctl));
694 client_ctl.value = 0 != (vol & bit);
695 client_ctl.id = V4L2_CID_AUDIO_MUTE;
696 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
697 }
698 ret = 1;
699 }
700 spin_unlock_irq(&chip->reg_lock);
701 return ret;
702}
703
704static const struct snd_kcontrol_new snd_cx88_dac_switch = {
705 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
706 .name = "Audio-Out Switch",
707 .info = snd_ctl_boolean_mono_info,
708 .get = snd_cx88_switch_get,
709 .put = snd_cx88_switch_put,
710 .private_value = (1<<8),
711};
712
713static const struct snd_kcontrol_new snd_cx88_source_switch = {
714 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
715 .name = "Analog-TV Switch",
716 .info = snd_ctl_boolean_mono_info,
717 .get = snd_cx88_switch_get,
718 .put = snd_cx88_switch_put,
719 .private_value = (1<<6),
720};
721
722static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
723 struct snd_ctl_elem_value *value)
724{
725 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
726 struct cx88_core *core = chip->core;
727 struct v4l2_control client_ctl;
728
729 memset(&client_ctl, 0, sizeof(client_ctl));
730 client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
731 call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
732 value->value.integer.value[0] = client_ctl.value ? 1 : 0;
733
734 return 0;
735}
736
737static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
738 struct snd_ctl_elem_value *value)
739{
740 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
741 struct cx88_core *core = chip->core;
742 struct v4l2_control client_ctl;
743
744 memset(&client_ctl, 0, sizeof(client_ctl));
745 client_ctl.value = 0 != value->value.integer.value[0];
746 client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
747 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
748
749 return 0;
750}
751
752static struct snd_kcontrol_new snd_cx88_alc_switch = {
753 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
754 .name = "Line-In ALC Switch",
755 .info = snd_ctl_boolean_mono_info,
756 .get = snd_cx88_alc_get,
757 .put = snd_cx88_alc_put,
758};
759
760/****************************************************************************
761 Basic Flow for Sound Devices
762 ****************************************************************************/
763
764/*
765 * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
766 * Only boards with eeprom and byte 1 at eeprom=1 have it
767 */
768
769static const struct pci_device_id const cx88_audio_pci_tbl[] __devinitdata = {
770 {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
771 {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
772 {0, }
773};
774MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
775
776/*
777 * Chip-specific destructor
778 */
779
780static int snd_cx88_free(snd_cx88_card_t *chip)
781{
782
783 if (chip->irq >= 0)
784 free_irq(chip->irq, chip);
785
786 cx88_core_put(chip->core,chip->pci);
787
788 pci_disable_device(chip->pci);
789 return 0;
790}
791
792/*
793 * Component Destructor
794 */
795static void snd_cx88_dev_free(struct snd_card * card)
796{
797 snd_cx88_card_t *chip = card->private_data;
798
799 snd_cx88_free(chip);
800}
801
802
803/*
804 * Alsa Constructor - Component probe
805 */
806
807static int devno;
808static int __devinit snd_cx88_create(struct snd_card *card,
809 struct pci_dev *pci,
810 snd_cx88_card_t **rchip,
811 struct cx88_core **core_ptr)
812{
813 snd_cx88_card_t *chip;
814 struct cx88_core *core;
815 int err;
816 unsigned char pci_lat;
817
818 *rchip = NULL;
819
820 err = pci_enable_device(pci);
821 if (err < 0)
822 return err;
823
824 pci_set_master(pci);
825
826 chip = card->private_data;
827
828 core = cx88_core_get(pci);
829 if (NULL == core) {
830 err = -EINVAL;
831 return err;
832 }
833
834 if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) {
835 dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
836 err = -EIO;
837 cx88_core_put(core, pci);
838 return err;
839 }
840
841
842 /* pci init */
843 chip->card = card;
844 chip->pci = pci;
845 chip->irq = -1;
846 spin_lock_init(&chip->reg_lock);
847
848 chip->core = core;
849
850 /* get irq */
851 err = request_irq(chip->pci->irq, cx8801_irq,
852 IRQF_SHARED | IRQF_DISABLED, chip->core->name, chip);
853 if (err < 0) {
854 dprintk(0, "%s: can't get IRQ %d\n",
855 chip->core->name, chip->pci->irq);
856 return err;
857 }
858
859 /* print pci info */
860 pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat);
861
862 dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, "
863 "latency: %d, mmio: 0x%llx\n", core->name, devno,
864 pci_name(pci), pci->revision, pci->irq,
865 pci_lat, (unsigned long long)pci_resource_start(pci,0));
866
867 chip->irq = pci->irq;
868 synchronize_irq(chip->irq);
869
870 snd_card_set_dev(card, &pci->dev);
871
872 *rchip = chip;
873 *core_ptr = core;
874
875 return 0;
876}
877
878static int __devinit cx88_audio_initdev(struct pci_dev *pci,
879 const struct pci_device_id *pci_id)
880{
881 struct snd_card *card;
882 snd_cx88_card_t *chip;
883 struct cx88_core *core = NULL;
884 int err;
885
886 if (devno >= SNDRV_CARDS)
887 return (-ENODEV);
888
889 if (!enable[devno]) {
890 ++devno;
891 return (-ENOENT);
892 }
893
894 err = snd_card_create(index[devno], id[devno], THIS_MODULE,
895 sizeof(snd_cx88_card_t), &card);
896 if (err < 0)
897 return err;
898
899 card->private_free = snd_cx88_dev_free;
900
901 err = snd_cx88_create(card, pci, &chip, &core);
902 if (err < 0)
903 goto error;
904
905 err = snd_cx88_pcm(chip, 0, "CX88 Digital");
906 if (err < 0)
907 goto error;
908
909 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_volume, chip));
910 if (err < 0)
911 goto error;
912 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_dac_switch, chip));
913 if (err < 0)
914 goto error;
915 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_source_switch, chip));
916 if (err < 0)
917 goto error;
918
919 /* If there's a wm8775 then add a Line-In ALC switch */
920 if (core->board.audio_chip == V4L2_IDENT_WM8775)
921 snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip));
922
923 strcpy (card->driver, "CX88x");
924 sprintf(card->shortname, "Conexant CX%x", pci->device);
925 sprintf(card->longname, "%s at %#llx",
926 card->shortname,(unsigned long long)pci_resource_start(pci, 0));
927 strcpy (card->mixername, "CX88");
928
929 dprintk (0, "%s/%i: ALSA support for cx2388x boards\n",
930 card->driver,devno);
931
932 err = snd_card_register(card);
933 if (err < 0)
934 goto error;
935 pci_set_drvdata(pci,card);
936
937 devno++;
938 return 0;
939
940error:
941 snd_card_free(card);
942 return err;
943}
944/*
945 * ALSA destructor
946 */
947static void __devexit cx88_audio_finidev(struct pci_dev *pci)
948{
949 struct cx88_audio_dev *card = pci_get_drvdata(pci);
950
951 snd_card_free((void *)card);
952
953 pci_set_drvdata(pci, NULL);
954
955 devno--;
956}
957
958/*
959 * PCI driver definition
960 */
961
962static struct pci_driver cx88_audio_pci_driver = {
963 .name = "cx88_audio",
964 .id_table = cx88_audio_pci_tbl,
965 .probe = cx88_audio_initdev,
966 .remove = __devexit_p(cx88_audio_finidev),
967};
968
969/****************************************************************************
970 LINUX MODULE INIT
971 ****************************************************************************/
972
973/*
974 * module init
975 */
976static int __init cx88_audio_init(void)
977{
978 printk(KERN_INFO "cx2388x alsa driver version %s loaded\n",
979 CX88_VERSION);
980 return pci_register_driver(&cx88_audio_pci_driver);
981}
982
983/*
984 * module remove
985 */
986static void __exit cx88_audio_fini(void)
987{
988 pci_unregister_driver(&cx88_audio_pci_driver);
989}
990
991module_init(cx88_audio_init);
992module_exit(cx88_audio_fini);
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
new file mode 100644
index 00000000000..e46446a449c
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -0,0 +1,1385 @@
1/*
2 *
3 * Support for a cx23416 mpeg encoder via cx2388x host port.
4 * "blackbird" reference design.
5 *
6 * (c) 2004 Jelle Foks <jelle@foks.us>
7 * (c) 2004 Gerd Knorr <kraxel@bytesex.org>
8 *
9 * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
10 * - video_ioctl2 conversion
11 *
12 * Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/fs.h>
33#include <linux/delay.h>
34#include <linux/device.h>
35#include <linux/firmware.h>
36#include <media/v4l2-common.h>
37#include <media/v4l2-ioctl.h>
38#include <media/cx2341x.h>
39
40#include "cx88.h"
41
42MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
43MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
44MODULE_LICENSE("GPL");
45MODULE_VERSION(CX88_VERSION);
46
47static unsigned int mpegbufs = 32;
48module_param(mpegbufs,int,0644);
49MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
50
51static unsigned int debug;
52module_param(debug,int,0644);
53MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
54
55#define dprintk(level,fmt, arg...) if (debug >= level) \
56 printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
57
58
59/* ------------------------------------------------------------------ */
60
61#define BLACKBIRD_FIRM_IMAGE_SIZE 376836
62
63/* defines below are from ivtv-driver.h */
64
65#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
66
67/* Firmware API commands */
68#define IVTV_API_STD_TIMEOUT 500
69
70enum blackbird_capture_type {
71 BLACKBIRD_MPEG_CAPTURE,
72 BLACKBIRD_RAW_CAPTURE,
73 BLACKBIRD_RAW_PASSTHRU_CAPTURE
74};
75enum blackbird_capture_bits {
76 BLACKBIRD_RAW_BITS_NONE = 0x00,
77 BLACKBIRD_RAW_BITS_YUV_CAPTURE = 0x01,
78 BLACKBIRD_RAW_BITS_PCM_CAPTURE = 0x02,
79 BLACKBIRD_RAW_BITS_VBI_CAPTURE = 0x04,
80 BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
81 BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE = 0x10
82};
83enum blackbird_capture_end {
84 BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
85 BLACKBIRD_END_NOW, /* stop immediately, no irq */
86};
87enum blackbird_framerate {
88 BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
89 BLACKBIRD_FRAMERATE_PAL_25 /* PAL: 25fps */
90};
91enum blackbird_stream_port {
92 BLACKBIRD_OUTPUT_PORT_MEMORY,
93 BLACKBIRD_OUTPUT_PORT_STREAMING,
94 BLACKBIRD_OUTPUT_PORT_SERIAL
95};
96enum blackbird_data_xfer_status {
97 BLACKBIRD_MORE_BUFFERS_FOLLOW,
98 BLACKBIRD_LAST_BUFFER,
99};
100enum blackbird_picture_mask {
101 BLACKBIRD_PICTURE_MASK_NONE,
102 BLACKBIRD_PICTURE_MASK_I_FRAMES,
103 BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
104 BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
105};
106enum blackbird_vbi_mode_bits {
107 BLACKBIRD_VBI_BITS_SLICED,
108 BLACKBIRD_VBI_BITS_RAW,
109};
110enum blackbird_vbi_insertion_bits {
111 BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
112 BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
113 BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
114 BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
115 BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
116};
117enum blackbird_dma_unit {
118 BLACKBIRD_DMA_BYTES,
119 BLACKBIRD_DMA_FRAMES,
120};
121enum blackbird_dma_transfer_status_bits {
122 BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
123 BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
124 BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
125};
126enum blackbird_pause {
127 BLACKBIRD_PAUSE_ENCODING,
128 BLACKBIRD_RESUME_ENCODING,
129};
130enum blackbird_copyright {
131 BLACKBIRD_COPYRIGHT_OFF,
132 BLACKBIRD_COPYRIGHT_ON,
133};
134enum blackbird_notification_type {
135 BLACKBIRD_NOTIFICATION_REFRESH,
136};
137enum blackbird_notification_status {
138 BLACKBIRD_NOTIFICATION_OFF,
139 BLACKBIRD_NOTIFICATION_ON,
140};
141enum blackbird_notification_mailbox {
142 BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
143};
144enum blackbird_field1_lines {
145 BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
146 BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
147 BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
148};
149enum blackbird_field2_lines {
150 BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
151 BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
152 BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
153};
154enum blackbird_custom_data_type {
155 BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
156 BLACKBIRD_CUSTOM_PRIVATE_PACKET,
157};
158enum blackbird_mute {
159 BLACKBIRD_UNMUTE,
160 BLACKBIRD_MUTE,
161};
162enum blackbird_mute_video_mask {
163 BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
164 BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
165 BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
166};
167enum blackbird_mute_video_shift {
168 BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
169 BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
170 BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
171};
172
173/* Registers */
174#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
175#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC /*| IVTV_REG_OFFSET*/)
176#define IVTV_REG_SPU (0x9050 /*| IVTV_REG_OFFSET*/)
177#define IVTV_REG_HW_BLOCKS (0x9054 /*| IVTV_REG_OFFSET*/)
178#define IVTV_REG_VPU (0x9058 /*| IVTV_REG_OFFSET*/)
179#define IVTV_REG_APU (0xA064 /*| IVTV_REG_OFFSET*/)
180
181/* ------------------------------------------------------------------ */
182
183static void host_setup(struct cx88_core *core)
184{
185 /* toggle reset of the host */
186 cx_write(MO_GPHST_SOFT_RST, 1);
187 udelay(100);
188 cx_write(MO_GPHST_SOFT_RST, 0);
189 udelay(100);
190
191 /* host port setup */
192 cx_write(MO_GPHST_WSC, 0x44444444U);
193 cx_write(MO_GPHST_XFR, 0);
194 cx_write(MO_GPHST_WDTH, 15);
195 cx_write(MO_GPHST_HDSHK, 0);
196 cx_write(MO_GPHST_MUX16, 0x44448888U);
197 cx_write(MO_GPHST_MODE, 0);
198}
199
200/* ------------------------------------------------------------------ */
201
202#define P1_MDATA0 0x390000
203#define P1_MDATA1 0x390001
204#define P1_MDATA2 0x390002
205#define P1_MDATA3 0x390003
206#define P1_MADDR2 0x390004
207#define P1_MADDR1 0x390005
208#define P1_MADDR0 0x390006
209#define P1_RDATA0 0x390008
210#define P1_RDATA1 0x390009
211#define P1_RDATA2 0x39000A
212#define P1_RDATA3 0x39000B
213#define P1_RADDR0 0x39000C
214#define P1_RADDR1 0x39000D
215#define P1_RRDWR 0x39000E
216
217static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state)
218{
219 unsigned long timeout = jiffies + msecs_to_jiffies(1);
220 u32 gpio0,need;
221
222 need = state ? 2 : 0;
223 for (;;) {
224 gpio0 = cx_read(MO_GP0_IO) & 2;
225 if (need == gpio0)
226 return 0;
227 if (time_after(jiffies,timeout))
228 return -1;
229 udelay(1);
230 }
231}
232
233static int memory_write(struct cx88_core *core, u32 address, u32 value)
234{
235 /* Warning: address is dword address (4 bytes) */
236 cx_writeb(P1_MDATA0, (unsigned int)value);
237 cx_writeb(P1_MDATA1, (unsigned int)(value >> 8));
238 cx_writeb(P1_MDATA2, (unsigned int)(value >> 16));
239 cx_writeb(P1_MDATA3, (unsigned int)(value >> 24));
240 cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) | 0x40);
241 cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
242 cx_writeb(P1_MADDR0, (unsigned int)address);
243 cx_read(P1_MDATA0);
244 cx_read(P1_MADDR0);
245
246 return wait_ready_gpio0_bit1(core,1);
247}
248
249static int memory_read(struct cx88_core *core, u32 address, u32 *value)
250{
251 int retval;
252 u32 val;
253
254 /* Warning: address is dword address (4 bytes) */
255 cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) & ~0xC0);
256 cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
257 cx_writeb(P1_MADDR0, (unsigned int)address);
258 cx_read(P1_MADDR0);
259
260 retval = wait_ready_gpio0_bit1(core,1);
261
262 cx_writeb(P1_MDATA3, 0);
263 val = (unsigned char)cx_read(P1_MDATA3) << 24;
264 cx_writeb(P1_MDATA2, 0);
265 val |= (unsigned char)cx_read(P1_MDATA2) << 16;
266 cx_writeb(P1_MDATA1, 0);
267 val |= (unsigned char)cx_read(P1_MDATA1) << 8;
268 cx_writeb(P1_MDATA0, 0);
269 val |= (unsigned char)cx_read(P1_MDATA0);
270
271 *value = val;
272 return retval;
273}
274
275static int register_write(struct cx88_core *core, u32 address, u32 value)
276{
277 cx_writeb(P1_RDATA0, (unsigned int)value);
278 cx_writeb(P1_RDATA1, (unsigned int)(value >> 8));
279 cx_writeb(P1_RDATA2, (unsigned int)(value >> 16));
280 cx_writeb(P1_RDATA3, (unsigned int)(value >> 24));
281 cx_writeb(P1_RADDR0, (unsigned int)address);
282 cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
283 cx_writeb(P1_RRDWR, 1);
284 cx_read(P1_RDATA0);
285 cx_read(P1_RADDR0);
286
287 return wait_ready_gpio0_bit1(core,1);
288}
289
290
291static int register_read(struct cx88_core *core, u32 address, u32 *value)
292{
293 int retval;
294 u32 val;
295
296 cx_writeb(P1_RADDR0, (unsigned int)address);
297 cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
298 cx_writeb(P1_RRDWR, 0);
299 cx_read(P1_RADDR0);
300
301 retval = wait_ready_gpio0_bit1(core,1);
302 val = (unsigned char)cx_read(P1_RDATA0);
303 val |= (unsigned char)cx_read(P1_RDATA1) << 8;
304 val |= (unsigned char)cx_read(P1_RDATA2) << 16;
305 val |= (unsigned char)cx_read(P1_RDATA3) << 24;
306
307 *value = val;
308 return retval;
309}
310
311/* ------------------------------------------------------------------ */
312
313static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
314{
315 struct cx8802_dev *dev = priv;
316 unsigned long timeout;
317 u32 value, flag, retval;
318 int i;
319
320 dprintk(1,"%s: 0x%X\n", __func__, command);
321
322 /* this may not be 100% safe if we can't read any memory location
323 without side effects */
324 memory_read(dev->core, dev->mailbox - 4, &value);
325 if (value != 0x12345678) {
326 dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
327 return -1;
328 }
329
330 memory_read(dev->core, dev->mailbox, &flag);
331 if (flag) {
332 dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
333 return -1;
334 }
335
336 flag |= 1; /* tell 'em we're working on it */
337 memory_write(dev->core, dev->mailbox, flag);
338
339 /* write command + args + fill remaining with zeros */
340 memory_write(dev->core, dev->mailbox + 1, command); /* command code */
341 memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
342 for (i = 0; i < in; i++) {
343 memory_write(dev->core, dev->mailbox + 4 + i, data[i]);
344 dprintk(1, "API Input %d = %d\n", i, data[i]);
345 }
346 for (; i < CX2341X_MBOX_MAX_DATA; i++)
347 memory_write(dev->core, dev->mailbox + 4 + i, 0);
348
349 flag |= 3; /* tell 'em we're done writing */
350 memory_write(dev->core, dev->mailbox, flag);
351
352 /* wait for firmware to handle the API command */
353 timeout = jiffies + msecs_to_jiffies(10);
354 for (;;) {
355 memory_read(dev->core, dev->mailbox, &flag);
356 if (0 != (flag & 4))
357 break;
358 if (time_after(jiffies,timeout)) {
359 dprintk(0, "ERROR: API Mailbox timeout\n");
360 return -1;
361 }
362 udelay(10);
363 }
364
365 /* read output values */
366 for (i = 0; i < out; i++) {
367 memory_read(dev->core, dev->mailbox + 4 + i, data + i);
368 dprintk(1, "API Output %d = %d\n", i, data[i]);
369 }
370
371 memory_read(dev->core, dev->mailbox + 2, &retval);
372 dprintk(1, "API result = %d\n",retval);
373
374 flag = 0;
375 memory_write(dev->core, dev->mailbox, flag);
376 return retval;
377}
378/* ------------------------------------------------------------------ */
379
380/* We don't need to call the API often, so using just one mailbox will probably suffice */
381static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
382 u32 inputcnt, u32 outputcnt, ...)
383{
384 u32 data[CX2341X_MBOX_MAX_DATA];
385 va_list vargs;
386 int i, err;
387
388 va_start(vargs, outputcnt);
389
390 for (i = 0; i < inputcnt; i++) {
391 data[i] = va_arg(vargs, int);
392 }
393 err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data);
394 for (i = 0; i < outputcnt; i++) {
395 int *vptr = va_arg(vargs, int *);
396 *vptr = data[i];
397 }
398 va_end(vargs);
399 return err;
400}
401
402static int blackbird_find_mailbox(struct cx8802_dev *dev)
403{
404 u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456};
405 int signaturecnt=0;
406 u32 value;
407 int i;
408
409 for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
410 memory_read(dev->core, i, &value);
411 if (value == signature[signaturecnt])
412 signaturecnt++;
413 else
414 signaturecnt = 0;
415 if (4 == signaturecnt) {
416 dprintk(1, "Mailbox signature found\n");
417 return i+1;
418 }
419 }
420 dprintk(0, "Mailbox signature values not found!\n");
421 return -1;
422}
423
424static int blackbird_load_firmware(struct cx8802_dev *dev)
425{
426 static const unsigned char magic[8] = {
427 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
428 };
429 const struct firmware *firmware;
430 int i, retval = 0;
431 u32 value = 0;
432 u32 checksum = 0;
433 u32 *dataptr;
434
435 retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
436 retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
437 retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640);
438 retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
439 msleep(1);
440 retval |= register_write(dev->core, IVTV_REG_APU, 0);
441
442 if (retval < 0)
443 dprintk(0, "Error with register_write\n");
444
445 retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
446 &dev->pci->dev);
447
448
449 if (retval != 0) {
450 dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
451 CX2341X_FIRM_ENC_FILENAME);
452 dprintk(0, "Please fix your hotplug setup, the board will "
453 "not work without firmware loaded!\n");
454 return -1;
455 }
456
457 if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
458 dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
459 firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
460 release_firmware(firmware);
461 return -1;
462 }
463
464 if (0 != memcmp(firmware->data, magic, 8)) {
465 dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
466 release_firmware(firmware);
467 return -1;
468 }
469
470 /* transfer to the chip */
471 dprintk(1,"Loading firmware ...\n");
472 dataptr = (u32*)firmware->data;
473 for (i = 0; i < (firmware->size >> 2); i++) {
474 value = *dataptr;
475 checksum += ~value;
476 memory_write(dev->core, i, value);
477 dataptr++;
478 }
479
480 /* read back to verify with the checksum */
481 for (i--; i >= 0; i--) {
482 memory_read(dev->core, i, &value);
483 checksum -= ~value;
484 }
485 if (checksum) {
486 dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
487 release_firmware(firmware);
488 return -1;
489 }
490 release_firmware(firmware);
491 dprintk(0, "Firmware upload successful.\n");
492
493 retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
494 retval |= register_read(dev->core, IVTV_REG_SPU, &value);
495 retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE);
496 msleep(1);
497
498 retval |= register_read(dev->core, IVTV_REG_VPU, &value);
499 retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8);
500
501 if (retval < 0)
502 dprintk(0, "Error with register_write\n");
503 return 0;
504}
505
506/**
507 Settings used by the windows tv app for PVR2000:
508=================================================================================================================
509Profile | Codec | Resolution | CBR/VBR | Video Qlty | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
510-----------------------------------------------------------------------------------------------------------------
511MPEG-1 | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 2000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
512MPEG-2 | MPEG2 | 720x576PAL | VBR | 600 :Good | 4000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
513VCD | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 1150 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
514DVD | MPEG2 | 720x576PAL | VBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
515DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
516=================================================================================================================
517*DB: "DirectBurn"
518*/
519
520static void blackbird_codec_settings(struct cx8802_dev *dev)
521{
522 /* assign frame size */
523 blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
524 dev->height, dev->width);
525
526 dev->params.width = dev->width;
527 dev->params.height = dev->height;
528 dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0;
529
530 cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
531}
532
533static int blackbird_initialize_codec(struct cx8802_dev *dev)
534{
535 struct cx88_core *core = dev->core;
536 int version;
537 int retval;
538
539 dprintk(1,"Initialize codec\n");
540 retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
541 if (retval < 0) {
542
543 dev->mpeg_active = 0;
544
545 /* ping was not successful, reset and upload firmware */
546 cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
547 cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
548 retval = blackbird_load_firmware(dev);
549 if (retval < 0)
550 return retval;
551
552 retval = blackbird_find_mailbox(dev);
553 if (retval < 0)
554 return -1;
555
556 dev->mailbox = retval;
557
558 retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
559 if (retval < 0) {
560 dprintk(0, "ERROR: Firmware ping failed!\n");
561 return -1;
562 }
563
564 retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version);
565 if (retval < 0) {
566 dprintk(0, "ERROR: Firmware get encoder version failed!\n");
567 return -1;
568 }
569 dprintk(0, "Firmware version is 0x%08x\n", version);
570 }
571
572 cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */
573 cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */
574 cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */
575 cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */
576
577 blackbird_codec_settings(dev);
578
579 blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
580 BLACKBIRD_FIELD1_SAA7115,
581 BLACKBIRD_FIELD2_SAA7115
582 );
583
584 blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
585 BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
586 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
587
588 return 0;
589}
590
591static int blackbird_start_codec(struct file *file, void *priv)
592{
593 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
594 struct cx88_core *core = dev->core;
595 /* start capturing to the host interface */
596 u32 reg;
597
598 int i;
599 int lastchange = -1;
600 int lastval = 0;
601
602 for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) {
603 reg = cx_read(AUD_STATUS);
604
605 dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg);
606 if ((reg & 0x0F) != lastval) {
607 lastval = reg & 0x0F;
608 lastchange = i;
609 }
610 msleep(100);
611 }
612
613 /* unmute audio source */
614 cx_clear(AUD_VOL_CTL, (1 << 6));
615
616 blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0);
617
618 /* initialize the video input */
619 blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
620
621 /* start capturing to the host interface */
622 blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
623 BLACKBIRD_MPEG_CAPTURE,
624 BLACKBIRD_RAW_BITS_NONE
625 );
626
627 dev->mpeg_active = 1;
628 return 0;
629}
630
631static int blackbird_stop_codec(struct cx8802_dev *dev)
632{
633 blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
634 BLACKBIRD_END_NOW,
635 BLACKBIRD_MPEG_CAPTURE,
636 BLACKBIRD_RAW_BITS_NONE
637 );
638
639 dev->mpeg_active = 0;
640 return 0;
641}
642
643/* ------------------------------------------------------------------ */
644
645static int bb_buf_setup(struct videobuf_queue *q,
646 unsigned int *count, unsigned int *size)
647{
648 struct cx8802_fh *fh = q->priv_data;
649
650 fh->dev->ts_packet_size = 188 * 4; /* was: 512 */
651 fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
652
653 *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
654 *count = fh->dev->ts_packet_count;
655 return 0;
656}
657
658static int
659bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
660 enum v4l2_field field)
661{
662 struct cx8802_fh *fh = q->priv_data;
663 return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
664}
665
666static void
667bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
668{
669 struct cx8802_fh *fh = q->priv_data;
670 cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
671}
672
673static void
674bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
675{
676 cx88_free_buffer(q, (struct cx88_buffer*)vb);
677}
678
679static struct videobuf_queue_ops blackbird_qops = {
680 .buf_setup = bb_buf_setup,
681 .buf_prepare = bb_buf_prepare,
682 .buf_queue = bb_buf_queue,
683 .buf_release = bb_buf_release,
684};
685
686/* ------------------------------------------------------------------ */
687
688static const u32 *ctrl_classes[] = {
689 cx88_user_ctrls,
690 cx2341x_mpeg_ctrls,
691 NULL
692};
693
694static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qctrl)
695{
696 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
697 if (qctrl->id == 0)
698 return -EINVAL;
699
700 /* Standard V4L2 controls */
701 if (cx8800_ctrl_query(dev->core, qctrl) == 0)
702 return 0;
703
704 /* MPEG V4L2 controls */
705 if (cx2341x_ctrl_query(&dev->params, qctrl))
706 qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
707 return 0;
708}
709
710/* ------------------------------------------------------------------ */
711/* IOCTL Handlers */
712
713static int vidioc_querymenu (struct file *file, void *priv,
714 struct v4l2_querymenu *qmenu)
715{
716 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
717 struct v4l2_queryctrl qctrl;
718
719 qctrl.id = qmenu->id;
720 blackbird_queryctrl(dev, &qctrl);
721 return v4l2_ctrl_query_menu(qmenu, &qctrl,
722 cx2341x_ctrl_get_menu(&dev->params, qmenu->id));
723}
724
725static int vidioc_querycap (struct file *file, void *priv,
726 struct v4l2_capability *cap)
727{
728 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
729 struct cx88_core *core = dev->core;
730
731 strcpy(cap->driver, "cx88_blackbird");
732 strlcpy(cap->card, core->board.name, sizeof(cap->card));
733 sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
734 cap->capabilities =
735 V4L2_CAP_VIDEO_CAPTURE |
736 V4L2_CAP_READWRITE |
737 V4L2_CAP_STREAMING;
738 if (UNSET != core->board.tuner_type)
739 cap->capabilities |= V4L2_CAP_TUNER;
740 return 0;
741}
742
743static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
744 struct v4l2_fmtdesc *f)
745{
746 if (f->index != 0)
747 return -EINVAL;
748
749 strlcpy(f->description, "MPEG", sizeof(f->description));
750 f->pixelformat = V4L2_PIX_FMT_MPEG;
751 return 0;
752}
753
754static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
755 struct v4l2_format *f)
756{
757 struct cx8802_fh *fh = priv;
758 struct cx8802_dev *dev = fh->dev;
759
760 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
761 f->fmt.pix.bytesperline = 0;
762 f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
763 f->fmt.pix.colorspace = 0;
764 f->fmt.pix.width = dev->width;
765 f->fmt.pix.height = dev->height;
766 f->fmt.pix.field = fh->mpegq.field;
767 dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
768 dev->width, dev->height, fh->mpegq.field );
769 return 0;
770}
771
772static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
773 struct v4l2_format *f)
774{
775 struct cx8802_fh *fh = priv;
776 struct cx8802_dev *dev = fh->dev;
777
778 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
779 f->fmt.pix.bytesperline = 0;
780 f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
781 f->fmt.pix.colorspace = 0;
782 dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
783 dev->width, dev->height, fh->mpegq.field );
784 return 0;
785}
786
787static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
788 struct v4l2_format *f)
789{
790 struct cx8802_fh *fh = priv;
791 struct cx8802_dev *dev = fh->dev;
792 struct cx88_core *core = dev->core;
793
794 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
795 f->fmt.pix.bytesperline = 0;
796 f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
797 f->fmt.pix.colorspace = 0;
798 dev->width = f->fmt.pix.width;
799 dev->height = f->fmt.pix.height;
800 fh->mpegq.field = f->fmt.pix.field;
801 cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
802 blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
803 f->fmt.pix.height, f->fmt.pix.width);
804 dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
805 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
806 return 0;
807}
808
809static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
810{
811 struct cx8802_fh *fh = priv;
812 return (videobuf_reqbufs(&fh->mpegq, p));
813}
814
815static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
816{
817 struct cx8802_fh *fh = priv;
818 return (videobuf_querybuf(&fh->mpegq, p));
819}
820
821static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
822{
823 struct cx8802_fh *fh = priv;
824 return (videobuf_qbuf(&fh->mpegq, p));
825}
826
827static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
828{
829 struct cx8802_fh *fh = priv;
830 return (videobuf_dqbuf(&fh->mpegq, p,
831 file->f_flags & O_NONBLOCK));
832}
833
834static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
835{
836 struct cx8802_fh *fh = priv;
837 return videobuf_streamon(&fh->mpegq);
838}
839
840static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
841{
842 struct cx8802_fh *fh = priv;
843 return videobuf_streamoff(&fh->mpegq);
844}
845
846static int vidioc_g_ext_ctrls (struct file *file, void *priv,
847 struct v4l2_ext_controls *f)
848{
849 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
850
851 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
852 return -EINVAL;
853 return cx2341x_ext_ctrls(&dev->params, 0, f, VIDIOC_G_EXT_CTRLS);
854}
855
856static int vidioc_s_ext_ctrls (struct file *file, void *priv,
857 struct v4l2_ext_controls *f)
858{
859 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
860 struct cx2341x_mpeg_params p;
861 int err;
862
863 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
864 return -EINVAL;
865
866 if (dev->mpeg_active)
867 blackbird_stop_codec(dev);
868
869 p = dev->params;
870 err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS);
871 if (!err) {
872 err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
873 dev->params = p;
874 }
875 return err;
876}
877
878static int vidioc_try_ext_ctrls (struct file *file, void *priv,
879 struct v4l2_ext_controls *f)
880{
881 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
882 struct cx2341x_mpeg_params p;
883 int err;
884
885 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
886 return -EINVAL;
887 p = dev->params;
888 err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
889
890 return err;
891}
892
893static int vidioc_s_frequency (struct file *file, void *priv,
894 struct v4l2_frequency *f)
895{
896 struct cx8802_fh *fh = priv;
897 struct cx8802_dev *dev = fh->dev;
898 struct cx88_core *core = dev->core;
899
900 if (dev->mpeg_active)
901 blackbird_stop_codec(dev);
902
903 cx88_set_freq (core,f);
904 blackbird_initialize_codec(dev);
905 cx88_set_scale(dev->core, dev->width, dev->height,
906 fh->mpegq.field);
907 return 0;
908}
909
910static int vidioc_log_status (struct file *file, void *priv)
911{
912 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
913 struct cx88_core *core = dev->core;
914 char name[32 + 2];
915
916 snprintf(name, sizeof(name), "%s/2", core->name);
917 printk("%s/2: ============ START LOG STATUS ============\n",
918 core->name);
919 call_all(core, core, log_status);
920 cx2341x_log_status(&dev->params, name);
921 printk("%s/2: ============= END LOG STATUS =============\n",
922 core->name);
923 return 0;
924}
925
926static int vidioc_queryctrl (struct file *file, void *priv,
927 struct v4l2_queryctrl *qctrl)
928{
929 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
930
931 if (blackbird_queryctrl(dev, qctrl) == 0)
932 return 0;
933
934 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
935 if (unlikely(qctrl->id == 0))
936 return -EINVAL;
937 return cx8800_ctrl_query(dev->core, qctrl);
938}
939
940static int vidioc_enum_input (struct file *file, void *priv,
941 struct v4l2_input *i)
942{
943 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
944 return cx88_enum_input (core,i);
945}
946
947static int vidioc_g_ctrl (struct file *file, void *priv,
948 struct v4l2_control *ctl)
949{
950 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
951 return
952 cx88_get_control(core,ctl);
953}
954
955static int vidioc_s_ctrl (struct file *file, void *priv,
956 struct v4l2_control *ctl)
957{
958 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
959 return
960 cx88_set_control(core,ctl);
961}
962
963static int vidioc_g_frequency (struct file *file, void *priv,
964 struct v4l2_frequency *f)
965{
966 struct cx8802_fh *fh = priv;
967 struct cx88_core *core = fh->dev->core;
968
969 if (unlikely(UNSET == core->board.tuner_type))
970 return -EINVAL;
971
972 f->type = V4L2_TUNER_ANALOG_TV;
973 f->frequency = core->freq;
974 call_all(core, tuner, g_frequency, f);
975
976 return 0;
977}
978
979static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
980{
981 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
982
983 *i = core->input;
984 return 0;
985}
986
987static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
988{
989 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
990
991 if (i >= 4)
992 return -EINVAL;
993
994 mutex_lock(&core->lock);
995 cx88_newstation(core);
996 cx88_video_mux(core,i);
997 mutex_unlock(&core->lock);
998 return 0;
999}
1000
1001static int vidioc_g_tuner (struct file *file, void *priv,
1002 struct v4l2_tuner *t)
1003{
1004 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1005 u32 reg;
1006
1007 if (unlikely(UNSET == core->board.tuner_type))
1008 return -EINVAL;
1009 if (0 != t->index)
1010 return -EINVAL;
1011
1012 strcpy(t->name, "Television");
1013 t->type = V4L2_TUNER_ANALOG_TV;
1014 t->capability = V4L2_TUNER_CAP_NORM;
1015 t->rangehigh = 0xffffffffUL;
1016
1017 cx88_get_stereo(core ,t);
1018 reg = cx_read(MO_DEVICE_STATUS);
1019 t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
1020 return 0;
1021}
1022
1023static int vidioc_s_tuner (struct file *file, void *priv,
1024 struct v4l2_tuner *t)
1025{
1026 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1027
1028 if (UNSET == core->board.tuner_type)
1029 return -EINVAL;
1030 if (0 != t->index)
1031 return -EINVAL;
1032
1033 cx88_set_stereo(core, t->audmode, 1);
1034 return 0;
1035}
1036
1037static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
1038{
1039 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1040
1041 mutex_lock(&core->lock);
1042 cx88_set_tvnorm(core,*id);
1043 mutex_unlock(&core->lock);
1044 return 0;
1045}
1046
1047/* FIXME: cx88_ioctl_hook not implemented */
1048
1049static int mpeg_open(struct file *file)
1050{
1051 struct video_device *vdev = video_devdata(file);
1052 struct cx8802_dev *dev = video_drvdata(file);
1053 struct cx8802_fh *fh;
1054 struct cx8802_driver *drv = NULL;
1055 int err;
1056
1057 dprintk( 1, "%s\n", __func__);
1058
1059 mutex_lock(&dev->core->lock);
1060
1061 /* Make sure we can acquire the hardware */
1062 drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
1063 if (!drv) {
1064 dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
1065 mutex_unlock(&dev->core->lock);
1066 return -ENODEV;
1067 }
1068
1069 err = drv->request_acquire(drv);
1070 if (err != 0) {
1071 dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
1072 mutex_unlock(&dev->core->lock);
1073 return err;
1074 }
1075
1076 if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) {
1077 drv->request_release(drv);
1078 mutex_unlock(&dev->core->lock);
1079 return -EINVAL;
1080 }
1081 dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
1082
1083 /* allocate + initialize per filehandle data */
1084 fh = kzalloc(sizeof(*fh),GFP_KERNEL);
1085 if (NULL == fh) {
1086 drv->request_release(drv);
1087 mutex_unlock(&dev->core->lock);
1088 return -ENOMEM;
1089 }
1090 file->private_data = fh;
1091 fh->dev = dev;
1092
1093 videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
1094 &dev->pci->dev, &dev->slock,
1095 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1096 V4L2_FIELD_INTERLACED,
1097 sizeof(struct cx88_buffer),
1098 fh, NULL);
1099
1100 /* FIXME: locking against other video device */
1101 cx88_set_scale(dev->core, dev->width, dev->height,
1102 fh->mpegq.field);
1103
1104 dev->core->mpeg_users++;
1105 mutex_unlock(&dev->core->lock);
1106 return 0;
1107}
1108
1109static int mpeg_release(struct file *file)
1110{
1111 struct cx8802_fh *fh = file->private_data;
1112 struct cx8802_dev *dev = fh->dev;
1113 struct cx8802_driver *drv = NULL;
1114
1115 mutex_lock(&dev->core->lock);
1116
1117 if (dev->mpeg_active && dev->core->mpeg_users == 1)
1118 blackbird_stop_codec(dev);
1119
1120 cx8802_cancel_buffers(fh->dev);
1121 /* stop mpeg capture */
1122 videobuf_stop(&fh->mpegq);
1123
1124 videobuf_mmap_free(&fh->mpegq);
1125
1126 file->private_data = NULL;
1127 kfree(fh);
1128
1129 /* Make sure we release the hardware */
1130 drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
1131 WARN_ON(!drv);
1132 if (drv)
1133 drv->request_release(drv);
1134
1135 dev->core->mpeg_users--;
1136
1137 mutex_unlock(&dev->core->lock);
1138
1139 return 0;
1140}
1141
1142static ssize_t
1143mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1144{
1145 struct cx8802_fh *fh = file->private_data;
1146 struct cx8802_dev *dev = fh->dev;
1147
1148 if (!dev->mpeg_active)
1149 blackbird_start_codec(file, fh);
1150
1151 return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
1152 file->f_flags & O_NONBLOCK);
1153}
1154
1155static unsigned int
1156mpeg_poll(struct file *file, struct poll_table_struct *wait)
1157{
1158 struct cx8802_fh *fh = file->private_data;
1159 struct cx8802_dev *dev = fh->dev;
1160
1161 if (!dev->mpeg_active)
1162 blackbird_start_codec(file, fh);
1163
1164 return videobuf_poll_stream(file, &fh->mpegq, wait);
1165}
1166
1167static int
1168mpeg_mmap(struct file *file, struct vm_area_struct * vma)
1169{
1170 struct cx8802_fh *fh = file->private_data;
1171
1172 return videobuf_mmap_mapper(&fh->mpegq, vma);
1173}
1174
1175static const struct v4l2_file_operations mpeg_fops =
1176{
1177 .owner = THIS_MODULE,
1178 .open = mpeg_open,
1179 .release = mpeg_release,
1180 .read = mpeg_read,
1181 .poll = mpeg_poll,
1182 .mmap = mpeg_mmap,
1183 .ioctl = video_ioctl2,
1184};
1185
1186static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
1187 .vidioc_querymenu = vidioc_querymenu,
1188 .vidioc_querycap = vidioc_querycap,
1189 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1190 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1191 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1192 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1193 .vidioc_reqbufs = vidioc_reqbufs,
1194 .vidioc_querybuf = vidioc_querybuf,
1195 .vidioc_qbuf = vidioc_qbuf,
1196 .vidioc_dqbuf = vidioc_dqbuf,
1197 .vidioc_streamon = vidioc_streamon,
1198 .vidioc_streamoff = vidioc_streamoff,
1199 .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
1200 .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
1201 .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
1202 .vidioc_s_frequency = vidioc_s_frequency,
1203 .vidioc_log_status = vidioc_log_status,
1204 .vidioc_queryctrl = vidioc_queryctrl,
1205 .vidioc_enum_input = vidioc_enum_input,
1206 .vidioc_g_ctrl = vidioc_g_ctrl,
1207 .vidioc_s_ctrl = vidioc_s_ctrl,
1208 .vidioc_g_frequency = vidioc_g_frequency,
1209 .vidioc_g_input = vidioc_g_input,
1210 .vidioc_s_input = vidioc_s_input,
1211 .vidioc_g_tuner = vidioc_g_tuner,
1212 .vidioc_s_tuner = vidioc_s_tuner,
1213 .vidioc_s_std = vidioc_s_std,
1214};
1215
1216static struct video_device cx8802_mpeg_template = {
1217 .name = "cx8802",
1218 .fops = &mpeg_fops,
1219 .ioctl_ops = &mpeg_ioctl_ops,
1220 .tvnorms = CX88_NORMS,
1221 .current_norm = V4L2_STD_NTSC_M,
1222};
1223
1224/* ------------------------------------------------------------------ */
1225
1226/* The CX8802 MPEG API will call this when we can use the hardware */
1227static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
1228{
1229 struct cx88_core *core = drv->core;
1230 int err = 0;
1231
1232 switch (core->boardnr) {
1233 case CX88_BOARD_HAUPPAUGE_HVR1300:
1234 /* By default, core setup will leave the cx22702 out of reset, on the bus.
1235 * We left the hardware on power up with the cx22702 active.
1236 * We're being given access to re-arrange the GPIOs.
1237 * Take the bus off the cx22702 and put the cx23416 on it.
1238 */
1239 /* Toggle reset on cx22702 leaving i2c active */
1240 cx_set(MO_GP0_IO, 0x00000080);
1241 udelay(1000);
1242 cx_clear(MO_GP0_IO, 0x00000080);
1243 udelay(50);
1244 cx_set(MO_GP0_IO, 0x00000080);
1245 udelay(1000);
1246 /* tri-state the cx22702 pins */
1247 cx_set(MO_GP0_IO, 0x00000004);
1248 udelay(1000);
1249 break;
1250 default:
1251 err = -ENODEV;
1252 }
1253 return err;
1254}
1255
1256/* The CX8802 MPEG API will call this when we need to release the hardware */
1257static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
1258{
1259 struct cx88_core *core = drv->core;
1260 int err = 0;
1261
1262 switch (core->boardnr) {
1263 case CX88_BOARD_HAUPPAUGE_HVR1300:
1264 /* Exit leaving the cx23416 on the bus */
1265 break;
1266 default:
1267 err = -ENODEV;
1268 }
1269 return err;
1270}
1271
1272static void blackbird_unregister_video(struct cx8802_dev *dev)
1273{
1274 if (dev->mpeg_dev) {
1275 if (video_is_registered(dev->mpeg_dev))
1276 video_unregister_device(dev->mpeg_dev);
1277 else
1278 video_device_release(dev->mpeg_dev);
1279 dev->mpeg_dev = NULL;
1280 }
1281}
1282
1283static int blackbird_register_video(struct cx8802_dev *dev)
1284{
1285 int err;
1286
1287 dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
1288 &cx8802_mpeg_template,"mpeg");
1289 video_set_drvdata(dev->mpeg_dev, dev);
1290 err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
1291 if (err < 0) {
1292 printk(KERN_INFO "%s/2: can't register mpeg device\n",
1293 dev->core->name);
1294 return err;
1295 }
1296 printk(KERN_INFO "%s/2: registered device %s [mpeg]\n",
1297 dev->core->name, video_device_node_name(dev->mpeg_dev));
1298 return 0;
1299}
1300
1301/* ----------------------------------------------------------- */
1302
1303static int cx8802_blackbird_probe(struct cx8802_driver *drv)
1304{
1305 struct cx88_core *core = drv->core;
1306 struct cx8802_dev *dev = core->dvbdev;
1307 int err;
1308
1309 dprintk( 1, "%s\n", __func__);
1310 dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
1311 core->boardnr,
1312 core->name,
1313 core->pci_bus,
1314 core->pci_slot);
1315
1316 err = -ENODEV;
1317 if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
1318 goto fail_core;
1319
1320 dev->width = 720;
1321 dev->height = 576;
1322 cx2341x_fill_defaults(&dev->params);
1323 dev->params.port = CX2341X_PORT_STREAMING;
1324
1325 cx8802_mpeg_template.current_norm = core->tvnorm;
1326
1327 if (core->tvnorm & V4L2_STD_525_60) {
1328 dev->height = 480;
1329 } else {
1330 dev->height = 576;
1331 }
1332
1333 /* blackbird stuff */
1334 printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
1335 core->name);
1336 host_setup(dev->core);
1337
1338 blackbird_initialize_codec(dev);
1339 blackbird_register_video(dev);
1340
1341 /* initial device configuration: needed ? */
1342// init_controls(core);
1343 cx88_set_tvnorm(core,core->tvnorm);
1344 cx88_video_mux(core,0);
1345
1346 return 0;
1347
1348 fail_core:
1349 return err;
1350}
1351
1352static int cx8802_blackbird_remove(struct cx8802_driver *drv)
1353{
1354 /* blackbird */
1355 blackbird_unregister_video(drv->core->dvbdev);
1356
1357 return 0;
1358}
1359
1360static struct cx8802_driver cx8802_blackbird_driver = {
1361 .type_id = CX88_MPEG_BLACKBIRD,
1362 .hw_access = CX8802_DRVCTL_SHARED,
1363 .probe = cx8802_blackbird_probe,
1364 .remove = cx8802_blackbird_remove,
1365 .advise_acquire = cx8802_blackbird_advise_acquire,
1366 .advise_release = cx8802_blackbird_advise_release,
1367};
1368
1369static int __init blackbird_init(void)
1370{
1371 printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n",
1372 CX88_VERSION);
1373 return cx8802_register_driver(&cx8802_blackbird_driver);
1374}
1375
1376static void __exit blackbird_fini(void)
1377{
1378 cx8802_unregister_driver(&cx8802_blackbird_driver);
1379}
1380
1381module_init(blackbird_init);
1382module_exit(blackbird_fini);
1383
1384module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
1385MODULE_PARM_DESC(debug,"enable debug messages [video]");
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
new file mode 100644
index 00000000000..0d719faafd8
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -0,0 +1,3699 @@
1/*
2 *
3 * device driver for Conexant 2388x based TV cards
4 * card-specific stuff.
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/module.h>
25#include <linux/pci.h>
26#include <linux/delay.h>
27#include <linux/slab.h>
28
29#include "cx88.h"
30#include "tea5767.h"
31#include "xc4000.h"
32
33static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
34static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
35static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
36
37module_param_array(tuner, int, NULL, 0444);
38module_param_array(radio, int, NULL, 0444);
39module_param_array(card, int, NULL, 0444);
40
41MODULE_PARM_DESC(tuner,"tuner type");
42MODULE_PARM_DESC(radio,"radio tuner type");
43MODULE_PARM_DESC(card,"card type");
44
45static unsigned int latency = UNSET;
46module_param(latency,int,0444);
47MODULE_PARM_DESC(latency,"pci latency timer");
48
49static int disable_ir;
50module_param(disable_ir, int, 0444);
51MODULE_PARM_DESC(disable_ir, "Disable IR support");
52
53#define info_printk(core, fmt, arg...) \
54 printk(KERN_INFO "%s: " fmt, core->name , ## arg)
55
56#define warn_printk(core, fmt, arg...) \
57 printk(KERN_WARNING "%s: " fmt, core->name , ## arg)
58
59#define err_printk(core, fmt, arg...) \
60 printk(KERN_ERR "%s: " fmt, core->name , ## arg)
61
62
63/* ------------------------------------------------------------------ */
64/* board config info */
65
66/* If radio_type !=UNSET, radio_addr should be specified
67 */
68
69static const struct cx88_board cx88_boards[] = {
70 [CX88_BOARD_UNKNOWN] = {
71 .name = "UNKNOWN/GENERIC",
72 .tuner_type = UNSET,
73 .radio_type = UNSET,
74 .tuner_addr = ADDR_UNSET,
75 .radio_addr = ADDR_UNSET,
76 .input = {{
77 .type = CX88_VMUX_COMPOSITE1,
78 .vmux = 0,
79 },{
80 .type = CX88_VMUX_COMPOSITE2,
81 .vmux = 1,
82 },{
83 .type = CX88_VMUX_COMPOSITE3,
84 .vmux = 2,
85 },{
86 .type = CX88_VMUX_COMPOSITE4,
87 .vmux = 3,
88 }},
89 },
90 [CX88_BOARD_HAUPPAUGE] = {
91 .name = "Hauppauge WinTV 34xxx models",
92 .tuner_type = UNSET,
93 .radio_type = UNSET,
94 .tuner_addr = ADDR_UNSET,
95 .radio_addr = ADDR_UNSET,
96 .tda9887_conf = TDA9887_PRESENT,
97 .input = {{
98 .type = CX88_VMUX_TELEVISION,
99 .vmux = 0,
100 .gpio0 = 0xff00, // internal decoder
101 },{
102 .type = CX88_VMUX_DEBUG,
103 .vmux = 0,
104 .gpio0 = 0xff01, // mono from tuner chip
105 },{
106 .type = CX88_VMUX_COMPOSITE1,
107 .vmux = 1,
108 .gpio0 = 0xff02,
109 },{
110 .type = CX88_VMUX_SVIDEO,
111 .vmux = 2,
112 .gpio0 = 0xff02,
113 }},
114 .radio = {
115 .type = CX88_RADIO,
116 .gpio0 = 0xff01,
117 },
118 },
119 [CX88_BOARD_GDI] = {
120 .name = "GDI Black Gold",
121 .tuner_type = UNSET,
122 .radio_type = UNSET,
123 .tuner_addr = ADDR_UNSET,
124 .radio_addr = ADDR_UNSET,
125 .input = {{
126 .type = CX88_VMUX_TELEVISION,
127 .vmux = 0,
128 },{
129 .type = CX88_VMUX_SVIDEO,
130 .vmux = 2,
131 }},
132 },
133 [CX88_BOARD_PIXELVIEW] = {
134 .name = "PixelView",
135 .tuner_type = TUNER_PHILIPS_PAL,
136 .radio_type = UNSET,
137 .tuner_addr = ADDR_UNSET,
138 .radio_addr = ADDR_UNSET,
139 .input = {{
140 .type = CX88_VMUX_TELEVISION,
141 .vmux = 0,
142 .gpio0 = 0xff00, // internal decoder
143 },{
144 .type = CX88_VMUX_COMPOSITE1,
145 .vmux = 1,
146 },{
147 .type = CX88_VMUX_SVIDEO,
148 .vmux = 2,
149 }},
150 .radio = {
151 .type = CX88_RADIO,
152 .gpio0 = 0xff10,
153 },
154 },
155 [CX88_BOARD_ATI_WONDER_PRO] = {
156 .name = "ATI TV Wonder Pro",
157 .tuner_type = TUNER_PHILIPS_4IN1,
158 .radio_type = UNSET,
159 .tuner_addr = ADDR_UNSET,
160 .radio_addr = ADDR_UNSET,
161 .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER,
162 .input = {{
163 .type = CX88_VMUX_TELEVISION,
164 .vmux = 0,
165 .gpio0 = 0x03ff,
166 },{
167 .type = CX88_VMUX_COMPOSITE1,
168 .vmux = 1,
169 .gpio0 = 0x03fe,
170 },{
171 .type = CX88_VMUX_SVIDEO,
172 .vmux = 2,
173 .gpio0 = 0x03fe,
174 }},
175 },
176 [CX88_BOARD_WINFAST2000XP_EXPERT] = {
177 .name = "Leadtek Winfast 2000XP Expert",
178 .tuner_type = TUNER_PHILIPS_4IN1,
179 .radio_type = UNSET,
180 .tuner_addr = ADDR_UNSET,
181 .radio_addr = ADDR_UNSET,
182 .tda9887_conf = TDA9887_PRESENT,
183 .input = {{
184 .type = CX88_VMUX_TELEVISION,
185 .vmux = 0,
186 .gpio0 = 0x00F5e700,
187 .gpio1 = 0x00003004,
188 .gpio2 = 0x00F5e700,
189 .gpio3 = 0x02000000,
190 },{
191 .type = CX88_VMUX_COMPOSITE1,
192 .vmux = 1,
193 .gpio0 = 0x00F5c700,
194 .gpio1 = 0x00003004,
195 .gpio2 = 0x00F5c700,
196 .gpio3 = 0x02000000,
197 },{
198 .type = CX88_VMUX_SVIDEO,
199 .vmux = 2,
200 .gpio0 = 0x00F5c700,
201 .gpio1 = 0x00003004,
202 .gpio2 = 0x00F5c700,
203 .gpio3 = 0x02000000,
204 }},
205 .radio = {
206 .type = CX88_RADIO,
207 .gpio0 = 0x00F5d700,
208 .gpio1 = 0x00003004,
209 .gpio2 = 0x00F5d700,
210 .gpio3 = 0x02000000,
211 },
212 },
213 [CX88_BOARD_AVERTV_STUDIO_303] = {
214 .name = "AverTV Studio 303 (M126)",
215 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
216 .radio_type = UNSET,
217 .tuner_addr = ADDR_UNSET,
218 .radio_addr = ADDR_UNSET,
219 .tda9887_conf = TDA9887_PRESENT,
220 .input = {{
221 .type = CX88_VMUX_TELEVISION,
222 .vmux = 0,
223 .gpio1 = 0xe09f,
224 },{
225 .type = CX88_VMUX_COMPOSITE1,
226 .vmux = 1,
227 .gpio1 = 0xe05f,
228 },{
229 .type = CX88_VMUX_SVIDEO,
230 .vmux = 2,
231 .gpio1 = 0xe05f,
232 }},
233 .radio = {
234 .gpio1 = 0xe0df,
235 .type = CX88_RADIO,
236 },
237 },
238 [CX88_BOARD_MSI_TVANYWHERE_MASTER] = {
239 // added gpio values thanks to Michal
240 // values for PAL from DScaler
241 .name = "MSI TV-@nywhere Master",
242 .tuner_type = TUNER_MT2032,
243 .radio_type = UNSET,
244 .tuner_addr = ADDR_UNSET,
245 .radio_addr = ADDR_UNSET,
246 .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER_NTSC,
247 .input = {{
248 .type = CX88_VMUX_TELEVISION,
249 .vmux = 0,
250 .gpio0 = 0x000040bf,
251 .gpio1 = 0x000080c0,
252 .gpio2 = 0x0000ff40,
253 },{
254 .type = CX88_VMUX_COMPOSITE1,
255 .vmux = 1,
256 .gpio0 = 0x000040bf,
257 .gpio1 = 0x000080c0,
258 .gpio2 = 0x0000ff40,
259 },{
260 .type = CX88_VMUX_SVIDEO,
261 .vmux = 2,
262 .gpio0 = 0x000040bf,
263 .gpio1 = 0x000080c0,
264 .gpio2 = 0x0000ff40,
265 }},
266 .radio = {
267 .type = CX88_RADIO,
268 .vmux = 3,
269 .gpio0 = 0x000040bf,
270 .gpio1 = 0x000080c0,
271 .gpio2 = 0x0000ff20,
272 },
273 },
274 [CX88_BOARD_WINFAST_DV2000] = {
275 .name = "Leadtek Winfast DV2000",
276 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
277 .radio_type = UNSET,
278 .tuner_addr = ADDR_UNSET,
279 .radio_addr = ADDR_UNSET,
280 .tda9887_conf = TDA9887_PRESENT,
281 .input = {{
282 .type = CX88_VMUX_TELEVISION,
283 .vmux = 0,
284 .gpio0 = 0x0035e700,
285 .gpio1 = 0x00003004,
286 .gpio2 = 0x0035e700,
287 .gpio3 = 0x02000000,
288 },{
289
290 .type = CX88_VMUX_COMPOSITE1,
291 .vmux = 1,
292 .gpio0 = 0x0035c700,
293 .gpio1 = 0x00003004,
294 .gpio2 = 0x0035c700,
295 .gpio3 = 0x02000000,
296 },{
297 .type = CX88_VMUX_SVIDEO,
298 .vmux = 2,
299 .gpio0 = 0x0035c700,
300 .gpio1 = 0x0035c700,
301 .gpio2 = 0x02000000,
302 .gpio3 = 0x02000000,
303 }},
304 .radio = {
305 .type = CX88_RADIO,
306 .gpio0 = 0x0035d700,
307 .gpio1 = 0x00007004,
308 .gpio2 = 0x0035d700,
309 .gpio3 = 0x02000000,
310 },
311 },
312 [CX88_BOARD_LEADTEK_PVR2000] = {
313 // gpio values for PAL version from regspy by DScaler
314 .name = "Leadtek PVR 2000",
315 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
316 .radio_type = UNSET,
317 .tuner_addr = ADDR_UNSET,
318 .radio_addr = ADDR_UNSET,
319 .tda9887_conf = TDA9887_PRESENT,
320 .input = {{
321 .type = CX88_VMUX_TELEVISION,
322 .vmux = 0,
323 .gpio0 = 0x0000bde2,
324 .audioroute = 1,
325 },{
326 .type = CX88_VMUX_COMPOSITE1,
327 .vmux = 1,
328 .gpio0 = 0x0000bde6,
329 .audioroute = 1,
330 },{
331 .type = CX88_VMUX_SVIDEO,
332 .vmux = 2,
333 .gpio0 = 0x0000bde6,
334 .audioroute = 1,
335 }},
336 .radio = {
337 .type = CX88_RADIO,
338 .gpio0 = 0x0000bd62,
339 .audioroute = 1,
340 },
341 .mpeg = CX88_MPEG_BLACKBIRD,
342 },
343 [CX88_BOARD_IODATA_GVVCP3PCI] = {
344 .name = "IODATA GV-VCP3/PCI",
345 .tuner_type = TUNER_ABSENT,
346 .radio_type = UNSET,
347 .tuner_addr = ADDR_UNSET,
348 .radio_addr = ADDR_UNSET,
349 .input = {{
350 .type = CX88_VMUX_COMPOSITE1,
351 .vmux = 0,
352 },{
353 .type = CX88_VMUX_COMPOSITE2,
354 .vmux = 1,
355 },{
356 .type = CX88_VMUX_SVIDEO,
357 .vmux = 2,
358 }},
359 },
360 [CX88_BOARD_PROLINK_PLAYTVPVR] = {
361 .name = "Prolink PlayTV PVR",
362 .tuner_type = TUNER_PHILIPS_FM1236_MK3,
363 .radio_type = UNSET,
364 .tuner_addr = ADDR_UNSET,
365 .radio_addr = ADDR_UNSET,
366 .tda9887_conf = TDA9887_PRESENT,
367 .input = {{
368 .type = CX88_VMUX_TELEVISION,
369 .vmux = 0,
370 .gpio0 = 0xbff0,
371 },{
372 .type = CX88_VMUX_COMPOSITE1,
373 .vmux = 1,
374 .gpio0 = 0xbff3,
375 },{
376 .type = CX88_VMUX_SVIDEO,
377 .vmux = 2,
378 .gpio0 = 0xbff3,
379 }},
380 .radio = {
381 .type = CX88_RADIO,
382 .gpio0 = 0xbff0,
383 },
384 },
385 [CX88_BOARD_ASUS_PVR_416] = {
386 .name = "ASUS PVR-416",
387 .tuner_type = TUNER_PHILIPS_FM1236_MK3,
388 .radio_type = UNSET,
389 .tuner_addr = ADDR_UNSET,
390 .radio_addr = ADDR_UNSET,
391 .tda9887_conf = TDA9887_PRESENT,
392 .input = {{
393 .type = CX88_VMUX_TELEVISION,
394 .vmux = 0,
395 .gpio0 = 0x0000fde6,
396 },{
397 .type = CX88_VMUX_SVIDEO,
398 .vmux = 2,
399 .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
400 .audioroute = 1,
401 }},
402 .radio = {
403 .type = CX88_RADIO,
404 .gpio0 = 0x0000fde2,
405 },
406 .mpeg = CX88_MPEG_BLACKBIRD,
407 },
408 [CX88_BOARD_MSI_TVANYWHERE] = {
409 .name = "MSI TV-@nywhere",
410 .tuner_type = TUNER_MT2032,
411 .radio_type = UNSET,
412 .tuner_addr = ADDR_UNSET,
413 .radio_addr = ADDR_UNSET,
414 .tda9887_conf = TDA9887_PRESENT,
415 .input = {{
416 .type = CX88_VMUX_TELEVISION,
417 .vmux = 0,
418 .gpio0 = 0x00000fbf,
419 .gpio2 = 0x0000fc08,
420 },{
421 .type = CX88_VMUX_COMPOSITE1,
422 .vmux = 1,
423 .gpio0 = 0x00000fbf,
424 .gpio2 = 0x0000fc68,
425 },{
426 .type = CX88_VMUX_SVIDEO,
427 .vmux = 2,
428 .gpio0 = 0x00000fbf,
429 .gpio2 = 0x0000fc68,
430 }},
431 },
432 [CX88_BOARD_KWORLD_DVB_T] = {
433 .name = "KWorld/VStream XPert DVB-T",
434 .tuner_type = TUNER_ABSENT,
435 .radio_type = UNSET,
436 .tuner_addr = ADDR_UNSET,
437 .radio_addr = ADDR_UNSET,
438 .input = {{
439 .type = CX88_VMUX_COMPOSITE1,
440 .vmux = 1,
441 .gpio0 = 0x0700,
442 .gpio2 = 0x0101,
443 },{
444 .type = CX88_VMUX_SVIDEO,
445 .vmux = 2,
446 .gpio0 = 0x0700,
447 .gpio2 = 0x0101,
448 }},
449 .mpeg = CX88_MPEG_DVB,
450 },
451 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
452 .name = "DViCO FusionHDTV DVB-T1",
453 .tuner_type = TUNER_ABSENT, /* No analog tuner */
454 .radio_type = UNSET,
455 .tuner_addr = ADDR_UNSET,
456 .radio_addr = ADDR_UNSET,
457 .input = {{
458 .type = CX88_VMUX_COMPOSITE1,
459 .vmux = 1,
460 .gpio0 = 0x000027df,
461 },{
462 .type = CX88_VMUX_SVIDEO,
463 .vmux = 2,
464 .gpio0 = 0x000027df,
465 }},
466 .mpeg = CX88_MPEG_DVB,
467 },
468 [CX88_BOARD_KWORLD_LTV883] = {
469 .name = "KWorld LTV883RF",
470 .tuner_type = TUNER_TNF_8831BGFF,
471 .radio_type = UNSET,
472 .tuner_addr = ADDR_UNSET,
473 .radio_addr = ADDR_UNSET,
474 .input = {{
475 .type = CX88_VMUX_TELEVISION,
476 .vmux = 0,
477 .gpio0 = 0x07f8,
478 },{
479 .type = CX88_VMUX_DEBUG,
480 .vmux = 0,
481 .gpio0 = 0x07f9, // mono from tuner chip
482 },{
483 .type = CX88_VMUX_COMPOSITE1,
484 .vmux = 1,
485 .gpio0 = 0x000007fa,
486 },{
487 .type = CX88_VMUX_SVIDEO,
488 .vmux = 2,
489 .gpio0 = 0x000007fa,
490 }},
491 .radio = {
492 .type = CX88_RADIO,
493 .gpio0 = 0x000007f8,
494 },
495 },
496 [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q] = {
497 .name = "DViCO FusionHDTV 3 Gold-Q",
498 .tuner_type = TUNER_MICROTUNE_4042FI5,
499 .radio_type = UNSET,
500 .tuner_addr = ADDR_UNSET,
501 .radio_addr = ADDR_UNSET,
502 /*
503 GPIO[0] resets DT3302 DTV receiver
504 0 - reset asserted
505 1 - normal operation
506 GPIO[1] mutes analog audio output connector
507 0 - enable selected source
508 1 - mute
509 GPIO[2] selects source for analog audio output connector
510 0 - analog audio input connector on tab
511 1 - analog DAC output from CX23881 chip
512 GPIO[3] selects RF input connector on tuner module
513 0 - RF connector labeled CABLE
514 1 - RF connector labeled ANT
515 GPIO[4] selects high RF for QAM256 mode
516 0 - normal RF
517 1 - high RF
518 */
519 .input = {{
520 .type = CX88_VMUX_TELEVISION,
521 .vmux = 0,
522 .gpio0 = 0x0f0d,
523 },{
524 .type = CX88_VMUX_CABLE,
525 .vmux = 0,
526 .gpio0 = 0x0f05,
527 },{
528 .type = CX88_VMUX_COMPOSITE1,
529 .vmux = 1,
530 .gpio0 = 0x0f00,
531 },{
532 .type = CX88_VMUX_SVIDEO,
533 .vmux = 2,
534 .gpio0 = 0x0f00,
535 }},
536 .mpeg = CX88_MPEG_DVB,
537 },
538 [CX88_BOARD_HAUPPAUGE_DVB_T1] = {
539 .name = "Hauppauge Nova-T DVB-T",
540 .tuner_type = TUNER_ABSENT,
541 .radio_type = UNSET,
542 .tuner_addr = ADDR_UNSET,
543 .radio_addr = ADDR_UNSET,
544 .input = {{
545 .type = CX88_VMUX_DVB,
546 .vmux = 0,
547 }},
548 .mpeg = CX88_MPEG_DVB,
549 },
550 [CX88_BOARD_CONEXANT_DVB_T1] = {
551 .name = "Conexant DVB-T reference design",
552 .tuner_type = TUNER_ABSENT,
553 .radio_type = UNSET,
554 .tuner_addr = ADDR_UNSET,
555 .radio_addr = ADDR_UNSET,
556 .input = {{
557 .type = CX88_VMUX_DVB,
558 .vmux = 0,
559 }},
560 .mpeg = CX88_MPEG_DVB,
561 },
562 [CX88_BOARD_PROVIDEO_PV259] = {
563 .name = "Provideo PV259",
564 .tuner_type = TUNER_PHILIPS_FQ1216ME,
565 .radio_type = UNSET,
566 .tuner_addr = ADDR_UNSET,
567 .radio_addr = ADDR_UNSET,
568 .input = {{
569 .type = CX88_VMUX_TELEVISION,
570 .vmux = 0,
571 .audioroute = 1,
572 }},
573 .mpeg = CX88_MPEG_BLACKBIRD,
574 },
575 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
576 .name = "DViCO FusionHDTV DVB-T Plus",
577 .tuner_type = TUNER_ABSENT, /* No analog tuner */
578 .radio_type = UNSET,
579 .tuner_addr = ADDR_UNSET,
580 .radio_addr = ADDR_UNSET,
581 .input = {{
582 .type = CX88_VMUX_COMPOSITE1,
583 .vmux = 1,
584 .gpio0 = 0x000027df,
585 },{
586 .type = CX88_VMUX_SVIDEO,
587 .vmux = 2,
588 .gpio0 = 0x000027df,
589 }},
590 .mpeg = CX88_MPEG_DVB,
591 },
592 [CX88_BOARD_DNTV_LIVE_DVB_T] = {
593 .name = "digitalnow DNTV Live! DVB-T",
594 .tuner_type = TUNER_ABSENT,
595 .radio_type = UNSET,
596 .tuner_addr = ADDR_UNSET,
597 .radio_addr = ADDR_UNSET,
598 .input = {{
599 .type = CX88_VMUX_COMPOSITE1,
600 .vmux = 1,
601 .gpio0 = 0x00000700,
602 .gpio2 = 0x00000101,
603 },{
604 .type = CX88_VMUX_SVIDEO,
605 .vmux = 2,
606 .gpio0 = 0x00000700,
607 .gpio2 = 0x00000101,
608 }},
609 .mpeg = CX88_MPEG_DVB,
610 },
611 [CX88_BOARD_PCHDTV_HD3000] = {
612 .name = "pcHDTV HD3000 HDTV",
613 .tuner_type = TUNER_THOMSON_DTT761X,
614 .radio_type = UNSET,
615 .tuner_addr = ADDR_UNSET,
616 .radio_addr = ADDR_UNSET,
617 .tda9887_conf = TDA9887_PRESENT,
618 /* GPIO[2] = audio source for analog audio out connector
619 * 0 = analog audio input connector
620 * 1 = CX88 audio DACs
621 *
622 * GPIO[7] = input to CX88's audio/chroma ADC
623 * 0 = FM 10.7 MHz IF
624 * 1 = Sound 4.5 MHz IF
625 *
626 * GPIO[1,5,6] = Oren 51132 pins 27,35,28 respectively
627 *
628 * GPIO[16] = Remote control input
629 */
630 .input = {{
631 .type = CX88_VMUX_TELEVISION,
632 .vmux = 0,
633 .gpio0 = 0x00008484,
634 },{
635 .type = CX88_VMUX_COMPOSITE1,
636 .vmux = 1,
637 .gpio0 = 0x00008400,
638 },{
639 .type = CX88_VMUX_SVIDEO,
640 .vmux = 2,
641 .gpio0 = 0x00008400,
642 }},
643 .radio = {
644 .type = CX88_RADIO,
645 .gpio0 = 0x00008404,
646 },
647 .mpeg = CX88_MPEG_DVB,
648 },
649 [CX88_BOARD_HAUPPAUGE_ROSLYN] = {
650 // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
651 // GPIO values obtained from regspy, courtesy Sean Covel
652 .name = "Hauppauge WinTV 28xxx (Roslyn) models",
653 .tuner_type = UNSET,
654 .radio_type = UNSET,
655 .tuner_addr = ADDR_UNSET,
656 .radio_addr = ADDR_UNSET,
657 .input = {{
658 .type = CX88_VMUX_TELEVISION,
659 .vmux = 0,
660 .gpio0 = 0xed1a,
661 .gpio2 = 0x00ff,
662 },{
663 .type = CX88_VMUX_DEBUG,
664 .vmux = 0,
665 .gpio0 = 0xff01,
666 },{
667 .type = CX88_VMUX_COMPOSITE1,
668 .vmux = 1,
669 .gpio0 = 0xff02,
670 },{
671 .type = CX88_VMUX_SVIDEO,
672 .vmux = 2,
673 .gpio0 = 0xed92,
674 .gpio2 = 0x00ff,
675 }},
676 .radio = {
677 .type = CX88_RADIO,
678 .gpio0 = 0xed96,
679 .gpio2 = 0x00ff,
680 },
681 .mpeg = CX88_MPEG_BLACKBIRD,
682 },
683 [CX88_BOARD_DIGITALLOGIC_MEC] = {
684 .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
685 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
686 .radio_type = UNSET,
687 .tuner_addr = ADDR_UNSET,
688 .radio_addr = ADDR_UNSET,
689 .tda9887_conf = TDA9887_PRESENT,
690 .input = {{
691 .type = CX88_VMUX_TELEVISION,
692 .vmux = 0,
693 .gpio0 = 0x00009d80,
694 .audioroute = 1,
695 },{
696 .type = CX88_VMUX_COMPOSITE1,
697 .vmux = 1,
698 .gpio0 = 0x00009d76,
699 .audioroute = 1,
700 },{
701 .type = CX88_VMUX_SVIDEO,
702 .vmux = 2,
703 .gpio0 = 0x00009d76,
704 .audioroute = 1,
705 }},
706 .radio = {
707 .type = CX88_RADIO,
708 .gpio0 = 0x00009d00,
709 .audioroute = 1,
710 },
711 .mpeg = CX88_MPEG_BLACKBIRD,
712 },
713 [CX88_BOARD_IODATA_GVBCTV7E] = {
714 .name = "IODATA GV/BCTV7E",
715 .tuner_type = TUNER_PHILIPS_FQ1286,
716 .radio_type = UNSET,
717 .tuner_addr = ADDR_UNSET,
718 .radio_addr = ADDR_UNSET,
719 .tda9887_conf = TDA9887_PRESENT,
720 .input = {{
721 .type = CX88_VMUX_TELEVISION,
722 .vmux = 1,
723 .gpio1 = 0x0000e03f,
724 },{
725 .type = CX88_VMUX_COMPOSITE1,
726 .vmux = 2,
727 .gpio1 = 0x0000e07f,
728 },{
729 .type = CX88_VMUX_SVIDEO,
730 .vmux = 3,
731 .gpio1 = 0x0000e07f,
732 }}
733 },
734 [CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO] = {
735 .name = "PixelView PlayTV Ultra Pro (Stereo)",
736 /* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */
737 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
738 .radio_type = UNSET,
739 .tuner_addr = ADDR_UNSET,
740 .radio_addr = ADDR_UNSET,
741 /* Some variants use a tda9874 and so need the tvaudio module. */
742 .audio_chip = V4L2_IDENT_TVAUDIO,
743 .input = {{
744 .type = CX88_VMUX_TELEVISION,
745 .vmux = 0,
746 .gpio0 = 0xbf61, /* internal decoder */
747 },{
748 .type = CX88_VMUX_COMPOSITE1,
749 .vmux = 1,
750 .gpio0 = 0xbf63,
751 },{
752 .type = CX88_VMUX_SVIDEO,
753 .vmux = 2,
754 .gpio0 = 0xbf63,
755 }},
756 .radio = {
757 .type = CX88_RADIO,
758 .gpio0 = 0xbf60,
759 },
760 },
761 [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
762 .name = "DViCO FusionHDTV 3 Gold-T",
763 .tuner_type = TUNER_THOMSON_DTT761X,
764 .radio_type = UNSET,
765 .tuner_addr = ADDR_UNSET,
766 .radio_addr = ADDR_UNSET,
767 .tda9887_conf = TDA9887_PRESENT,
768 .input = {{
769 .type = CX88_VMUX_TELEVISION,
770 .vmux = 0,
771 .gpio0 = 0x97ed,
772 },{
773 .type = CX88_VMUX_COMPOSITE1,
774 .vmux = 1,
775 .gpio0 = 0x97e9,
776 },{
777 .type = CX88_VMUX_SVIDEO,
778 .vmux = 2,
779 .gpio0 = 0x97e9,
780 }},
781 .mpeg = CX88_MPEG_DVB,
782 },
783 [CX88_BOARD_ADSTECH_DVB_T_PCI] = {
784 .name = "ADS Tech Instant TV DVB-T PCI",
785 .tuner_type = TUNER_ABSENT,
786 .radio_type = UNSET,
787 .tuner_addr = ADDR_UNSET,
788 .radio_addr = ADDR_UNSET,
789 .input = {{
790 .type = CX88_VMUX_COMPOSITE1,
791 .vmux = 1,
792 .gpio0 = 0x0700,
793 .gpio2 = 0x0101,
794 },{
795 .type = CX88_VMUX_SVIDEO,
796 .vmux = 2,
797 .gpio0 = 0x0700,
798 .gpio2 = 0x0101,
799 }},
800 .mpeg = CX88_MPEG_DVB,
801 },
802 [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = {
803 .name = "TerraTec Cinergy 1400 DVB-T",
804 .tuner_type = TUNER_ABSENT,
805 .input = {{
806 .type = CX88_VMUX_DVB,
807 .vmux = 0,
808 },{
809 .type = CX88_VMUX_COMPOSITE1,
810 .vmux = 2,
811 },{
812 .type = CX88_VMUX_SVIDEO,
813 .vmux = 2,
814 }},
815 .mpeg = CX88_MPEG_DVB,
816 },
817 [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = {
818 .name = "DViCO FusionHDTV 5 Gold",
819 .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H062F */
820 .radio_type = UNSET,
821 .tuner_addr = ADDR_UNSET,
822 .radio_addr = ADDR_UNSET,
823 .tda9887_conf = TDA9887_PRESENT,
824 .input = {{
825 .type = CX88_VMUX_TELEVISION,
826 .vmux = 0,
827 .gpio0 = 0x87fd,
828 },{
829 .type = CX88_VMUX_COMPOSITE1,
830 .vmux = 1,
831 .gpio0 = 0x87f9,
832 },{
833 .type = CX88_VMUX_SVIDEO,
834 .vmux = 2,
835 .gpio0 = 0x87f9,
836 }},
837 .mpeg = CX88_MPEG_DVB,
838 },
839 [CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = {
840 .name = "AverMedia UltraTV Media Center PCI 550",
841 .tuner_type = TUNER_PHILIPS_FM1236_MK3,
842 .radio_type = UNSET,
843 .tuner_addr = ADDR_UNSET,
844 .radio_addr = ADDR_UNSET,
845 .tda9887_conf = TDA9887_PRESENT,
846 .input = {{
847 .type = CX88_VMUX_COMPOSITE1,
848 .vmux = 0,
849 .gpio0 = 0x0000cd73,
850 .audioroute = 1,
851 },{
852 .type = CX88_VMUX_SVIDEO,
853 .vmux = 1,
854 .gpio0 = 0x0000cd73,
855 .audioroute = 1,
856 },{
857 .type = CX88_VMUX_TELEVISION,
858 .vmux = 3,
859 .gpio0 = 0x0000cdb3,
860 .audioroute = 1,
861 }},
862 .radio = {
863 .type = CX88_RADIO,
864 .vmux = 2,
865 .gpio0 = 0x0000cdf3,
866 .audioroute = 1,
867 },
868 .mpeg = CX88_MPEG_BLACKBIRD,
869 },
870 [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = {
871 /* Alexander Wold <awold@bigfoot.com> */
872 .name = "Kworld V-Stream Xpert DVD",
873 .tuner_type = UNSET,
874 .input = {{
875 .type = CX88_VMUX_COMPOSITE1,
876 .vmux = 1,
877 .gpio0 = 0x03000000,
878 .gpio1 = 0x01000000,
879 .gpio2 = 0x02000000,
880 .gpio3 = 0x00100000,
881 },{
882 .type = CX88_VMUX_SVIDEO,
883 .vmux = 2,
884 .gpio0 = 0x03000000,
885 .gpio1 = 0x01000000,
886 .gpio2 = 0x02000000,
887 .gpio3 = 0x00100000,
888 }},
889 },
890 [CX88_BOARD_ATI_HDTVWONDER] = {
891 .name = "ATI HDTV Wonder",
892 .tuner_type = TUNER_PHILIPS_TUV1236D,
893 .radio_type = UNSET,
894 .tuner_addr = ADDR_UNSET,
895 .radio_addr = ADDR_UNSET,
896 .input = {{
897 .type = CX88_VMUX_TELEVISION,
898 .vmux = 0,
899 .gpio0 = 0x00000ff7,
900 .gpio1 = 0x000000ff,
901 .gpio2 = 0x00000001,
902 .gpio3 = 0x00000000,
903 },{
904 .type = CX88_VMUX_COMPOSITE1,
905 .vmux = 1,
906 .gpio0 = 0x00000ffe,
907 .gpio1 = 0x000000ff,
908 .gpio2 = 0x00000001,
909 .gpio3 = 0x00000000,
910 },{
911 .type = CX88_VMUX_SVIDEO,
912 .vmux = 2,
913 .gpio0 = 0x00000ffe,
914 .gpio1 = 0x000000ff,
915 .gpio2 = 0x00000001,
916 .gpio3 = 0x00000000,
917 }},
918 .mpeg = CX88_MPEG_DVB,
919 },
920 [CX88_BOARD_WINFAST_DTV1000] = {
921 .name = "WinFast DTV1000-T",
922 .tuner_type = TUNER_ABSENT,
923 .radio_type = UNSET,
924 .tuner_addr = ADDR_UNSET,
925 .radio_addr = ADDR_UNSET,
926 .input = {{
927 .type = CX88_VMUX_DVB,
928 .vmux = 0,
929 },{
930 .type = CX88_VMUX_COMPOSITE1,
931 .vmux = 1,
932 },{
933 .type = CX88_VMUX_SVIDEO,
934 .vmux = 2,
935 }},
936 .mpeg = CX88_MPEG_DVB,
937 },
938 [CX88_BOARD_AVERTV_303] = {
939 .name = "AVerTV 303 (M126)",
940 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
941 .radio_type = UNSET,
942 .tuner_addr = ADDR_UNSET,
943 .radio_addr = ADDR_UNSET,
944 .tda9887_conf = TDA9887_PRESENT,
945 .input = {{
946 .type = CX88_VMUX_TELEVISION,
947 .vmux = 0,
948 .gpio0 = 0x00ff,
949 .gpio1 = 0xe09f,
950 .gpio2 = 0x0010,
951 .gpio3 = 0x0000,
952 },{
953 .type = CX88_VMUX_COMPOSITE1,
954 .vmux = 1,
955 .gpio0 = 0x00ff,
956 .gpio1 = 0xe05f,
957 .gpio2 = 0x0010,
958 .gpio3 = 0x0000,
959 },{
960 .type = CX88_VMUX_SVIDEO,
961 .vmux = 2,
962 .gpio0 = 0x00ff,
963 .gpio1 = 0xe05f,
964 .gpio2 = 0x0010,
965 .gpio3 = 0x0000,
966 }},
967 },
968 [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = {
969 .name = "Hauppauge Nova-S-Plus DVB-S",
970 .tuner_type = TUNER_ABSENT,
971 .radio_type = UNSET,
972 .tuner_addr = ADDR_UNSET,
973 .radio_addr = ADDR_UNSET,
974 .audio_chip = V4L2_IDENT_WM8775,
975 .i2sinputcntl = 2,
976 .input = {{
977 .type = CX88_VMUX_DVB,
978 .vmux = 0,
979 /* 2: Line-In */
980 .audioroute = 2,
981 },{
982 .type = CX88_VMUX_COMPOSITE1,
983 .vmux = 1,
984 /* 2: Line-In */
985 .audioroute = 2,
986 },{
987 .type = CX88_VMUX_SVIDEO,
988 .vmux = 2,
989 /* 2: Line-In */
990 .audioroute = 2,
991 }},
992 .mpeg = CX88_MPEG_DVB,
993 },
994 [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
995 .name = "Hauppauge Nova-SE2 DVB-S",
996 .tuner_type = TUNER_ABSENT,
997 .radio_type = UNSET,
998 .tuner_addr = ADDR_UNSET,
999 .radio_addr = ADDR_UNSET,
1000 .input = {{
1001 .type = CX88_VMUX_DVB,
1002 .vmux = 0,
1003 }},
1004 .mpeg = CX88_MPEG_DVB,
1005 },
1006 [CX88_BOARD_KWORLD_DVBS_100] = {
1007 .name = "KWorld DVB-S 100",
1008 .tuner_type = TUNER_ABSENT,
1009 .radio_type = UNSET,
1010 .tuner_addr = ADDR_UNSET,
1011 .radio_addr = ADDR_UNSET,
1012 .audio_chip = V4L2_IDENT_WM8775,
1013 .input = {{
1014 .type = CX88_VMUX_DVB,
1015 .vmux = 0,
1016 /* 2: Line-In */
1017 .audioroute = 2,
1018 },{
1019 .type = CX88_VMUX_COMPOSITE1,
1020 .vmux = 1,
1021 /* 2: Line-In */
1022 .audioroute = 2,
1023 },{
1024 .type = CX88_VMUX_SVIDEO,
1025 .vmux = 2,
1026 /* 2: Line-In */
1027 .audioroute = 2,
1028 }},
1029 .mpeg = CX88_MPEG_DVB,
1030 },
1031 [CX88_BOARD_HAUPPAUGE_HVR1100] = {
1032 .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid",
1033 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
1034 .radio_type = UNSET,
1035 .tuner_addr = ADDR_UNSET,
1036 .radio_addr = ADDR_UNSET,
1037 .tda9887_conf = TDA9887_PRESENT,
1038 .input = {{
1039 .type = CX88_VMUX_TELEVISION,
1040 .vmux = 0,
1041 },{
1042 .type = CX88_VMUX_COMPOSITE1,
1043 .vmux = 1,
1044 },{
1045 .type = CX88_VMUX_SVIDEO,
1046 .vmux = 2,
1047 }},
1048 /* fixme: Add radio support */
1049 .mpeg = CX88_MPEG_DVB,
1050 },
1051 [CX88_BOARD_HAUPPAUGE_HVR1100LP] = {
1052 .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)",
1053 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
1054 .radio_type = UNSET,
1055 .tuner_addr = ADDR_UNSET,
1056 .radio_addr = ADDR_UNSET,
1057 .tda9887_conf = TDA9887_PRESENT,
1058 .input = {{
1059 .type = CX88_VMUX_TELEVISION,
1060 .vmux = 0,
1061 },{
1062 .type = CX88_VMUX_COMPOSITE1,
1063 .vmux = 1,
1064 }},
1065 /* fixme: Add radio support */
1066 .mpeg = CX88_MPEG_DVB,
1067 },
1068 [CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = {
1069 .name = "digitalnow DNTV Live! DVB-T Pro",
1070 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
1071 .radio_type = UNSET,
1072 .tuner_addr = ADDR_UNSET,
1073 .radio_addr = ADDR_UNSET,
1074 .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
1075 TDA9887_PORT2_ACTIVE,
1076 .input = {{
1077 .type = CX88_VMUX_TELEVISION,
1078 .vmux = 0,
1079 .gpio0 = 0xf80808,
1080 },{
1081 .type = CX88_VMUX_COMPOSITE1,
1082 .vmux = 1,
1083 .gpio0 = 0xf80808,
1084 },{
1085 .type = CX88_VMUX_SVIDEO,
1086 .vmux = 2,
1087 .gpio0 = 0xf80808,
1088 }},
1089 .radio = {
1090 .type = CX88_RADIO,
1091 .gpio0 = 0xf80808,
1092 },
1093 .mpeg = CX88_MPEG_DVB,
1094 },
1095 [CX88_BOARD_KWORLD_DVB_T_CX22702] = {
1096 /* Kworld V-stream Xpert DVB-T with Thomson tuner */
1097 /* DTT 7579 Conexant CX22702-19 Conexant CX2388x */
1098 /* Manenti Marco <marco_manenti@colman.it> */
1099 .name = "KWorld/VStream XPert DVB-T with cx22702",
1100 .tuner_type = TUNER_ABSENT,
1101 .radio_type = UNSET,
1102 .tuner_addr = ADDR_UNSET,
1103 .radio_addr = ADDR_UNSET,
1104 .input = {{
1105 .type = CX88_VMUX_COMPOSITE1,
1106 .vmux = 1,
1107 .gpio0 = 0x0700,
1108 .gpio2 = 0x0101,
1109 },{
1110 .type = CX88_VMUX_SVIDEO,
1111 .vmux = 2,
1112 .gpio0 = 0x0700,
1113 .gpio2 = 0x0101,
1114 }},
1115 .mpeg = CX88_MPEG_DVB,
1116 },
1117 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
1118 .name = "DViCO FusionHDTV DVB-T Dual Digital",
1119 .tuner_type = TUNER_ABSENT, /* No analog tuner */
1120 .radio_type = UNSET,
1121 .tuner_addr = ADDR_UNSET,
1122 .radio_addr = ADDR_UNSET,
1123 .input = {{
1124 .type = CX88_VMUX_COMPOSITE1,
1125 .vmux = 1,
1126 .gpio0 = 0x000067df,
1127 },{
1128 .type = CX88_VMUX_SVIDEO,
1129 .vmux = 2,
1130 .gpio0 = 0x000067df,
1131 }},
1132 .mpeg = CX88_MPEG_DVB,
1133 },
1134 [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
1135 .name = "KWorld HardwareMpegTV XPert",
1136 .tuner_type = TUNER_PHILIPS_TDA8290,
1137 .radio_type = UNSET,
1138 .tuner_addr = ADDR_UNSET,
1139 .radio_addr = ADDR_UNSET,
1140 .input = {{
1141 .type = CX88_VMUX_TELEVISION,
1142 .vmux = 0,
1143 .gpio0 = 0x3de2,
1144 .gpio2 = 0x00ff,
1145 },{
1146 .type = CX88_VMUX_COMPOSITE1,
1147 .vmux = 1,
1148 .gpio0 = 0x3de6,
1149 .audioroute = 1,
1150 },{
1151 .type = CX88_VMUX_SVIDEO,
1152 .vmux = 2,
1153 .gpio0 = 0x3de6,
1154 .audioroute = 1,
1155 }},
1156 .radio = {
1157 .type = CX88_RADIO,
1158 .gpio0 = 0x3de6,
1159 .gpio2 = 0x00ff,
1160 },
1161 .mpeg = CX88_MPEG_BLACKBIRD,
1162 },
1163 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = {
1164 .name = "DViCO FusionHDTV DVB-T Hybrid",
1165 .tuner_type = TUNER_THOMSON_FE6600,
1166 .radio_type = UNSET,
1167 .tuner_addr = ADDR_UNSET,
1168 .radio_addr = ADDR_UNSET,
1169 .input = {{
1170 .type = CX88_VMUX_TELEVISION,
1171 .vmux = 0,
1172 .gpio0 = 0x0000a75f,
1173 },{
1174 .type = CX88_VMUX_COMPOSITE1,
1175 .vmux = 1,
1176 .gpio0 = 0x0000a75b,
1177 },{
1178 .type = CX88_VMUX_SVIDEO,
1179 .vmux = 2,
1180 .gpio0 = 0x0000a75b,
1181 }},
1182 .mpeg = CX88_MPEG_DVB,
1183 },
1184 [CX88_BOARD_PCHDTV_HD5500] = {
1185 .name = "pcHDTV HD5500 HDTV",
1186 .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
1187 .radio_type = UNSET,
1188 .tuner_addr = ADDR_UNSET,
1189 .radio_addr = ADDR_UNSET,
1190 .tda9887_conf = TDA9887_PRESENT,
1191 .input = {{
1192 .type = CX88_VMUX_TELEVISION,
1193 .vmux = 0,
1194 .gpio0 = 0x87fd,
1195 },{
1196 .type = CX88_VMUX_COMPOSITE1,
1197 .vmux = 1,
1198 .gpio0 = 0x87f9,
1199 },{
1200 .type = CX88_VMUX_SVIDEO,
1201 .vmux = 2,
1202 .gpio0 = 0x87f9,
1203 }},
1204 .mpeg = CX88_MPEG_DVB,
1205 },
1206 [CX88_BOARD_KWORLD_MCE200_DELUXE] = {
1207 /* FIXME: tested TV input only, disabled composite,
1208 svideo and radio until they can be tested also. */
1209 .name = "Kworld MCE 200 Deluxe",
1210 .tuner_type = TUNER_TENA_9533_DI,
1211 .radio_type = UNSET,
1212 .tda9887_conf = TDA9887_PRESENT,
1213 .tuner_addr = ADDR_UNSET,
1214 .radio_addr = ADDR_UNSET,
1215 .input = {{
1216 .type = CX88_VMUX_TELEVISION,
1217 .vmux = 0,
1218 .gpio0 = 0x0000BDE6
1219 }},
1220 .mpeg = CX88_MPEG_BLACKBIRD,
1221 },
1222 [CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = {
1223 /* FIXME: SVideo, Composite and FM inputs are untested */
1224 .name = "PixelView PlayTV P7000",
1225 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
1226 .radio_type = UNSET,
1227 .tuner_addr = ADDR_UNSET,
1228 .radio_addr = ADDR_UNSET,
1229 .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
1230 TDA9887_PORT2_ACTIVE,
1231 .input = {{
1232 .type = CX88_VMUX_TELEVISION,
1233 .vmux = 0,
1234 .gpio0 = 0x5da6,
1235 }},
1236 .mpeg = CX88_MPEG_BLACKBIRD,
1237 },
1238 [CX88_BOARD_NPGTECH_REALTV_TOP10FM] = {
1239 .name = "NPG Tech Real TV FM Top 10",
1240 .tuner_type = TUNER_TNF_5335MF, /* Actually a TNF9535 */
1241 .radio_type = UNSET,
1242 .tuner_addr = ADDR_UNSET,
1243 .radio_addr = ADDR_UNSET,
1244 .input = {{
1245 .type = CX88_VMUX_TELEVISION,
1246 .vmux = 0,
1247 .gpio0 = 0x0788,
1248 },{
1249 .type = CX88_VMUX_COMPOSITE1,
1250 .vmux = 1,
1251 .gpio0 = 0x078b,
1252 },{
1253 .type = CX88_VMUX_SVIDEO,
1254 .vmux = 2,
1255 .gpio0 = 0x078b,
1256 }},
1257 .radio = {
1258 .type = CX88_RADIO,
1259 .gpio0 = 0x074a,
1260 },
1261 },
1262 [CX88_BOARD_WINFAST_DTV2000H] = {
1263 .name = "WinFast DTV2000 H",
1264 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
1265 .radio_type = UNSET,
1266 .tuner_addr = ADDR_UNSET,
1267 .radio_addr = ADDR_UNSET,
1268 .tda9887_conf = TDA9887_PRESENT,
1269 .input = {{
1270 .type = CX88_VMUX_TELEVISION,
1271 .vmux = 0,
1272 .gpio0 = 0x00017304,
1273 .gpio1 = 0x00008203,
1274 .gpio2 = 0x00017304,
1275 .gpio3 = 0x02000000,
1276 }, {
1277 .type = CX88_VMUX_COMPOSITE1,
1278 .vmux = 1,
1279 .gpio0 = 0x0001d701,
1280 .gpio1 = 0x0000b207,
1281 .gpio2 = 0x0001d701,
1282 .gpio3 = 0x02000000,
1283 }, {
1284 .type = CX88_VMUX_COMPOSITE2,
1285 .vmux = 2,
1286 .gpio0 = 0x0001d503,
1287 .gpio1 = 0x0000b207,
1288 .gpio2 = 0x0001d503,
1289 .gpio3 = 0x02000000,
1290 }, {
1291 .type = CX88_VMUX_SVIDEO,
1292 .vmux = 3,
1293 .gpio0 = 0x0001d701,
1294 .gpio1 = 0x0000b207,
1295 .gpio2 = 0x0001d701,
1296 .gpio3 = 0x02000000,
1297 }},
1298 .radio = {
1299 .type = CX88_RADIO,
1300 .gpio0 = 0x00015702,
1301 .gpio1 = 0x0000f207,
1302 .gpio2 = 0x00015702,
1303 .gpio3 = 0x02000000,
1304 },
1305 .mpeg = CX88_MPEG_DVB,
1306 },
1307 [CX88_BOARD_WINFAST_DTV2000H_J] = {
1308 .name = "WinFast DTV2000 H rev. J",
1309 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
1310 .radio_type = UNSET,
1311 .tuner_addr = ADDR_UNSET,
1312 .radio_addr = ADDR_UNSET,
1313 .tda9887_conf = TDA9887_PRESENT,
1314 .input = {{
1315 .type = CX88_VMUX_TELEVISION,
1316 .vmux = 0,
1317 .gpio0 = 0x00017300,
1318 .gpio1 = 0x00008207,
1319 .gpio2 = 0x00000000,
1320 .gpio3 = 0x02000000,
1321 },{
1322 .type = CX88_VMUX_TELEVISION,
1323 .vmux = 0,
1324 .gpio0 = 0x00018300,
1325 .gpio1 = 0x0000f207,
1326 .gpio2 = 0x00017304,
1327 .gpio3 = 0x02000000,
1328 },{
1329 .type = CX88_VMUX_COMPOSITE1,
1330 .vmux = 1,
1331 .gpio0 = 0x00018301,
1332 .gpio1 = 0x0000f207,
1333 .gpio2 = 0x00017304,
1334 .gpio3 = 0x02000000,
1335 },{
1336 .type = CX88_VMUX_SVIDEO,
1337 .vmux = 2,
1338 .gpio0 = 0x00018301,
1339 .gpio1 = 0x0000f207,
1340 .gpio2 = 0x00017304,
1341 .gpio3 = 0x02000000,
1342 }},
1343 .radio = {
1344 .type = CX88_RADIO,
1345 .gpio0 = 0x00015702,
1346 .gpio1 = 0x0000f207,
1347 .gpio2 = 0x00015702,
1348 .gpio3 = 0x02000000,
1349 },
1350 .mpeg = CX88_MPEG_DVB,
1351 },
1352 [CX88_BOARD_GENIATECH_DVBS] = {
1353 .name = "Geniatech DVB-S",
1354 .tuner_type = TUNER_ABSENT,
1355 .radio_type = UNSET,
1356 .tuner_addr = ADDR_UNSET,
1357 .radio_addr = ADDR_UNSET,
1358 .input = {{
1359 .type = CX88_VMUX_DVB,
1360 .vmux = 0,
1361 },{
1362 .type = CX88_VMUX_COMPOSITE1,
1363 .vmux = 1,
1364 }},
1365 .mpeg = CX88_MPEG_DVB,
1366 },
1367 [CX88_BOARD_HAUPPAUGE_HVR3000] = {
1368 .name = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T",
1369 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
1370 .radio_type = UNSET,
1371 .tuner_addr = ADDR_UNSET,
1372 .radio_addr = ADDR_UNSET,
1373 .tda9887_conf = TDA9887_PRESENT,
1374 .audio_chip = V4L2_IDENT_WM8775,
1375 .input = {{
1376 .type = CX88_VMUX_TELEVISION,
1377 .vmux = 0,
1378 .gpio0 = 0x84bf,
1379 /* 1: TV Audio / FM Mono */
1380 .audioroute = 1,
1381 },{
1382 .type = CX88_VMUX_COMPOSITE1,
1383 .vmux = 1,
1384 .gpio0 = 0x84bf,
1385 /* 2: Line-In */
1386 .audioroute = 2,
1387 },{
1388 .type = CX88_VMUX_SVIDEO,
1389 .vmux = 2,
1390 .gpio0 = 0x84bf,
1391 /* 2: Line-In */
1392 .audioroute = 2,
1393 }},
1394 .radio = {
1395 .type = CX88_RADIO,
1396 .gpio0 = 0x84bf,
1397 /* 4: FM Stereo (untested) */
1398 .audioroute = 8,
1399 },
1400 .mpeg = CX88_MPEG_DVB,
1401 .num_frontends = 2,
1402 },
1403 [CX88_BOARD_NORWOOD_MICRO] = {
1404 .name = "Norwood Micro TV Tuner",
1405 .tuner_type = TUNER_TNF_5335MF,
1406 .radio_type = UNSET,
1407 .tuner_addr = ADDR_UNSET,
1408 .radio_addr = ADDR_UNSET,
1409 .input = {{
1410 .type = CX88_VMUX_TELEVISION,
1411 .vmux = 0,
1412 .gpio0 = 0x0709,
1413 },{
1414 .type = CX88_VMUX_COMPOSITE1,
1415 .vmux = 1,
1416 .gpio0 = 0x070b,
1417 },{
1418 .type = CX88_VMUX_SVIDEO,
1419 .vmux = 2,
1420 .gpio0 = 0x070b,
1421 }},
1422 },
1423 [CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
1424 .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
1425 .tuner_type = TUNER_LG_PAL_NEW_TAPC,
1426 .radio_type = UNSET,
1427 .tuner_addr = ADDR_UNSET,
1428 .radio_addr = ADDR_UNSET,
1429 .input = {{
1430 .type = CX88_VMUX_TELEVISION,
1431 .vmux = 0,
1432 .gpio0 = 0x003fffff,
1433 .gpio1 = 0x00e00000,
1434 .gpio2 = 0x003fffff,
1435 .gpio3 = 0x02000000,
1436 },{
1437 .type = CX88_VMUX_COMPOSITE1,
1438 .vmux = 1,
1439 .gpio0 = 0x003fffff,
1440 .gpio1 = 0x00e00000,
1441 .gpio2 = 0x003fffff,
1442 .gpio3 = 0x02000000,
1443 },{
1444 .type = CX88_VMUX_SVIDEO,
1445 .vmux = 2,
1446 .gpio0 = 0x003fffff,
1447 .gpio1 = 0x00e00000,
1448 .gpio2 = 0x003fffff,
1449 .gpio3 = 0x02000000,
1450 }},
1451 },
1452 [CX88_BOARD_HAUPPAUGE_HVR1300] = {
1453 .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder",
1454 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
1455 .radio_type = UNSET,
1456 .tuner_addr = ADDR_UNSET,
1457 .radio_addr = ADDR_UNSET,
1458 .tda9887_conf = TDA9887_PRESENT,
1459 .audio_chip = V4L2_IDENT_WM8775,
1460 /*
1461 * gpio0 as reported by Mike Crash <mike AT mikecrash.com>
1462 */
1463 .input = {{
1464 .type = CX88_VMUX_TELEVISION,
1465 .vmux = 0,
1466 .gpio0 = 0xef88,
1467 /* 1: TV Audio / FM Mono */
1468 .audioroute = 1,
1469 },{
1470 .type = CX88_VMUX_COMPOSITE1,
1471 .vmux = 1,
1472 .gpio0 = 0xef88,
1473 /* 2: Line-In */
1474 .audioroute = 2,
1475 },{
1476 .type = CX88_VMUX_SVIDEO,
1477 .vmux = 2,
1478 .gpio0 = 0xef88,
1479 /* 2: Line-In */
1480 .audioroute = 2,
1481 }},
1482 .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
1483 .radio = {
1484 .type = CX88_RADIO,
1485 .gpio0 = 0xef88,
1486 /* 4: FM Stereo (untested) */
1487 .audioroute = 8,
1488 },
1489 },
1490 [CX88_BOARD_SAMSUNG_SMT_7020] = {
1491 .name = "Samsung SMT 7020 DVB-S",
1492 .tuner_type = TUNER_ABSENT,
1493 .radio_type = UNSET,
1494 .tuner_addr = ADDR_UNSET,
1495 .radio_addr = ADDR_UNSET,
1496 .input = { {
1497 .type = CX88_VMUX_DVB,
1498 .vmux = 0,
1499 } },
1500 .mpeg = CX88_MPEG_DVB,
1501 },
1502 [CX88_BOARD_ADSTECH_PTV_390] = {
1503 .name = "ADS Tech Instant Video PCI",
1504 .tuner_type = TUNER_ABSENT,
1505 .radio_type = UNSET,
1506 .tuner_addr = ADDR_UNSET,
1507 .radio_addr = ADDR_UNSET,
1508 .input = {{
1509 .type = CX88_VMUX_DEBUG,
1510 .vmux = 3,
1511 .gpio0 = 0x04ff,
1512 },{
1513 .type = CX88_VMUX_COMPOSITE1,
1514 .vmux = 1,
1515 .gpio0 = 0x07fa,
1516 },{
1517 .type = CX88_VMUX_SVIDEO,
1518 .vmux = 2,
1519 .gpio0 = 0x07fa,
1520 }},
1521 },
1522 [CX88_BOARD_PINNACLE_PCTV_HD_800i] = {
1523 .name = "Pinnacle PCTV HD 800i",
1524 .tuner_type = TUNER_XC5000,
1525 .radio_type = UNSET,
1526 .tuner_addr = ADDR_UNSET,
1527 .radio_addr = ADDR_UNSET,
1528 .input = {{
1529 .type = CX88_VMUX_TELEVISION,
1530 .vmux = 0,
1531 .gpio0 = 0x04fb,
1532 .gpio1 = 0x10ff,
1533 },{
1534 .type = CX88_VMUX_COMPOSITE1,
1535 .vmux = 1,
1536 .gpio0 = 0x04fb,
1537 .gpio1 = 0x10ef,
1538 .audioroute = 1,
1539 },{
1540 .type = CX88_VMUX_SVIDEO,
1541 .vmux = 2,
1542 .gpio0 = 0x04fb,
1543 .gpio1 = 0x10ef,
1544 .audioroute = 1,
1545 }},
1546 .mpeg = CX88_MPEG_DVB,
1547 },
1548 [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
1549 .name = "DViCO FusionHDTV 5 PCI nano",
1550 /* xc3008 tuner, digital only for now */
1551 .tuner_type = TUNER_ABSENT,
1552 .radio_type = UNSET,
1553 .tuner_addr = ADDR_UNSET,
1554 .radio_addr = ADDR_UNSET,
1555 .input = {{
1556 .type = CX88_VMUX_TELEVISION,
1557 .vmux = 0,
1558 .gpio0 = 0x000027df, /* Unconfirmed */
1559 }, {
1560 .type = CX88_VMUX_COMPOSITE1,
1561 .vmux = 1,
1562 .gpio0 = 0x000027df, /* Unconfirmed */
1563 .audioroute = 1,
1564 }, {
1565 .type = CX88_VMUX_SVIDEO,
1566 .vmux = 2,
1567 .gpio0 = 0x000027df, /* Unconfirmed */
1568 .audioroute = 1,
1569 } },
1570 .mpeg = CX88_MPEG_DVB,
1571 },
1572 [CX88_BOARD_PINNACLE_HYBRID_PCTV] = {
1573 .name = "Pinnacle Hybrid PCTV",
1574 .tuner_type = TUNER_XC2028,
1575 .tuner_addr = 0x61,
1576 .radio_type = TUNER_XC2028,
1577 .radio_addr = 0x61,
1578 .input = { {
1579 .type = CX88_VMUX_TELEVISION,
1580 .vmux = 0,
1581 .gpio0 = 0x004ff,
1582 .gpio1 = 0x010ff,
1583 .gpio2 = 0x00001,
1584 }, {
1585 .type = CX88_VMUX_COMPOSITE1,
1586 .vmux = 1,
1587 .gpio0 = 0x004fb,
1588 .gpio1 = 0x010ef,
1589 .audioroute = 1,
1590 }, {
1591 .type = CX88_VMUX_SVIDEO,
1592 .vmux = 2,
1593 .gpio0 = 0x004fb,
1594 .gpio1 = 0x010ef,
1595 .audioroute = 1,
1596 } },
1597 .radio = {
1598 .type = CX88_RADIO,
1599 .gpio0 = 0x004ff,
1600 .gpio1 = 0x010ff,
1601 .gpio2 = 0x0ff,
1602 },
1603 .mpeg = CX88_MPEG_DVB,
1604 },
1605 /* Terry Wu <terrywu2009@gmail.com> */
1606 /* TV Audio : set GPIO 2, 18, 19 value to 0, 1, 0 */
1607 /* FM Audio : set GPIO 2, 18, 19 value to 0, 0, 0 */
1608 /* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */
1609 /* Mute Audio : set GPIO 2 value to 1 */
1610 [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
1611 .name = "Leadtek TV2000 XP Global",
1612 .tuner_type = TUNER_XC2028,
1613 .tuner_addr = 0x61,
1614 .radio_type = TUNER_XC2028,
1615 .radio_addr = 0x61,
1616 .input = { {
1617 .type = CX88_VMUX_TELEVISION,
1618 .vmux = 0,
1619 .gpio0 = 0x0400, /* pin 2 = 0 */
1620 .gpio1 = 0x0000,
1621 .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */
1622 .gpio3 = 0x0000,
1623 }, {
1624 .type = CX88_VMUX_COMPOSITE1,
1625 .vmux = 1,
1626 .gpio0 = 0x0400, /* pin 2 = 0 */
1627 .gpio1 = 0x0000,
1628 .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */
1629 .gpio3 = 0x0000,
1630 }, {
1631 .type = CX88_VMUX_SVIDEO,
1632 .vmux = 2,
1633 .gpio0 = 0x0400, /* pin 2 = 0 */
1634 .gpio1 = 0x0000,
1635 .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */
1636 .gpio3 = 0x0000,
1637 } },
1638 .radio = {
1639 .type = CX88_RADIO,
1640 .gpio0 = 0x0400, /* pin 2 = 0 */
1641 .gpio1 = 0x0000,
1642 .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */
1643 .gpio3 = 0x0000,
1644 },
1645 },
1646 [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
1647 .name = "PowerColor RA330", /* Long names may confuse LIRC. */
1648 .tuner_type = TUNER_XC2028,
1649 .tuner_addr = 0x61,
1650 .input = { {
1651 .type = CX88_VMUX_DEBUG,
1652 .vmux = 3, /* Due to the way the cx88 driver is written, */
1653 .gpio0 = 0x00ff, /* there is no way to deactivate audio pass- */
1654 .gpio1 = 0xf39d, /* through without this entry. Furthermore, if */
1655 .gpio3 = 0x0000, /* the TV mux entry is first, you get audio */
1656 }, { /* from the tuner on boot for a little while. */
1657 .type = CX88_VMUX_TELEVISION,
1658 .vmux = 0,
1659 .gpio0 = 0x00ff,
1660 .gpio1 = 0xf35d,
1661 .gpio3 = 0x0000,
1662 }, {
1663 .type = CX88_VMUX_COMPOSITE1,
1664 .vmux = 1,
1665 .gpio0 = 0x00ff,
1666 .gpio1 = 0xf37d,
1667 .gpio3 = 0x0000,
1668 }, {
1669 .type = CX88_VMUX_SVIDEO,
1670 .vmux = 2,
1671 .gpio0 = 0x000ff,
1672 .gpio1 = 0x0f37d,
1673 .gpio3 = 0x00000,
1674 } },
1675 .radio = {
1676 .type = CX88_RADIO,
1677 .gpio0 = 0x000ff,
1678 .gpio1 = 0x0f35d,
1679 .gpio3 = 0x00000,
1680 },
1681 },
1682 [CX88_BOARD_GENIATECH_X8000_MT] = {
1683 /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */
1684 .name = "Geniatech X8000-MT DVBT",
1685 .tuner_type = TUNER_XC2028,
1686 .tuner_addr = 0x61,
1687 .input = { {
1688 .type = CX88_VMUX_TELEVISION,
1689 .vmux = 0,
1690 .gpio0 = 0x00000000,
1691 .gpio1 = 0x00e3e341,
1692 .gpio2 = 0x00000000,
1693 .gpio3 = 0x00000000,
1694 }, {
1695 .type = CX88_VMUX_COMPOSITE1,
1696 .vmux = 1,
1697 .gpio0 = 0x00000000,
1698 .gpio1 = 0x00e3e361,
1699 .gpio2 = 0x00000000,
1700 .gpio3 = 0x00000000,
1701 }, {
1702 .type = CX88_VMUX_SVIDEO,
1703 .vmux = 2,
1704 .gpio0 = 0x00000000,
1705 .gpio1 = 0x00e3e361,
1706 .gpio2 = 0x00000000,
1707 .gpio3 = 0x00000000,
1708 } },
1709 .radio = {
1710 .type = CX88_RADIO,
1711 .gpio0 = 0x00000000,
1712 .gpio1 = 0x00e3e341,
1713 .gpio2 = 0x00000000,
1714 .gpio3 = 0x00000000,
1715 },
1716 .mpeg = CX88_MPEG_DVB,
1717 },
1718 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
1719 .name = "DViCO FusionHDTV DVB-T PRO",
1720 .tuner_type = TUNER_XC2028,
1721 .tuner_addr = 0x61,
1722 .radio_type = UNSET,
1723 .radio_addr = ADDR_UNSET,
1724 .input = { {
1725 .type = CX88_VMUX_COMPOSITE1,
1726 .vmux = 1,
1727 .gpio0 = 0x000067df,
1728 }, {
1729 .type = CX88_VMUX_SVIDEO,
1730 .vmux = 2,
1731 .gpio0 = 0x000067df,
1732 } },
1733 .mpeg = CX88_MPEG_DVB,
1734 },
1735 [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = {
1736 .name = "DViCO FusionHDTV 7 Gold",
1737 .tuner_type = TUNER_XC5000,
1738 .radio_type = UNSET,
1739 .tuner_addr = ADDR_UNSET,
1740 .radio_addr = ADDR_UNSET,
1741 .input = {{
1742 .type = CX88_VMUX_TELEVISION,
1743 .vmux = 0,
1744 .gpio0 = 0x10df,
1745 },{
1746 .type = CX88_VMUX_COMPOSITE1,
1747 .vmux = 1,
1748 .gpio0 = 0x16d9,
1749 },{
1750 .type = CX88_VMUX_SVIDEO,
1751 .vmux = 2,
1752 .gpio0 = 0x16d9,
1753 }},
1754 .mpeg = CX88_MPEG_DVB,
1755 },
1756 [CX88_BOARD_PROLINK_PV_8000GT] = {
1757 .name = "Prolink Pixelview MPEG 8000GT",
1758 .tuner_type = TUNER_XC2028,
1759 .tuner_addr = 0x61,
1760 .input = { {
1761 .type = CX88_VMUX_TELEVISION,
1762 .vmux = 0,
1763 .gpio0 = 0x0ff,
1764 .gpio2 = 0x0cfb,
1765 }, {
1766 .type = CX88_VMUX_COMPOSITE1,
1767 .vmux = 1,
1768 .gpio2 = 0x0cfb,
1769 }, {
1770 .type = CX88_VMUX_SVIDEO,
1771 .vmux = 2,
1772 .gpio2 = 0x0cfb,
1773 } },
1774 .radio = {
1775 .type = CX88_RADIO,
1776 .gpio2 = 0x0cfb,
1777 },
1778 },
1779 [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = {
1780 .name = "Prolink Pixelview Global Extreme",
1781 .tuner_type = TUNER_XC2028,
1782 .tuner_addr = 0x61,
1783 .input = { {
1784 .type = CX88_VMUX_TELEVISION,
1785 .vmux = 0,
1786 .gpio0 = 0x04fb,
1787 .gpio1 = 0x04080,
1788 .gpio2 = 0x0cf7,
1789 }, {
1790 .type = CX88_VMUX_COMPOSITE1,
1791 .vmux = 1,
1792 .gpio0 = 0x04fb,
1793 .gpio1 = 0x04080,
1794 .gpio2 = 0x0cfb,
1795 }, {
1796 .type = CX88_VMUX_SVIDEO,
1797 .vmux = 2,
1798 .gpio0 = 0x04fb,
1799 .gpio1 = 0x04080,
1800 .gpio2 = 0x0cfb,
1801 } },
1802 .radio = {
1803 .type = CX88_RADIO,
1804 .gpio0 = 0x04ff,
1805 .gpio1 = 0x04080,
1806 .gpio2 = 0x0cf7,
1807 },
1808 },
1809 /* Both radio, analog and ATSC work with this board.
1810 However, for analog to work, s5h1409 gate should be open,
1811 otherwise, tuner-xc3028 won't be detected.
1812 A proper fix require using the newer i2c methods to add
1813 tuner-xc3028 without doing an i2c probe.
1814 */
1815 [CX88_BOARD_KWORLD_ATSC_120] = {
1816 .name = "Kworld PlusTV HD PCI 120 (ATSC 120)",
1817 .tuner_type = TUNER_XC2028,
1818 .radio_type = UNSET,
1819 .tuner_addr = ADDR_UNSET,
1820 .radio_addr = ADDR_UNSET,
1821 .input = { {
1822 .type = CX88_VMUX_TELEVISION,
1823 .vmux = 0,
1824 .gpio0 = 0x000000ff,
1825 .gpio1 = 0x0000f35d,
1826 .gpio2 = 0x00000000,
1827 }, {
1828 .type = CX88_VMUX_COMPOSITE1,
1829 .vmux = 1,
1830 .gpio0 = 0x000000ff,
1831 .gpio1 = 0x0000f37e,
1832 .gpio2 = 0x00000000,
1833 }, {
1834 .type = CX88_VMUX_SVIDEO,
1835 .vmux = 2,
1836 .gpio0 = 0x000000ff,
1837 .gpio1 = 0x0000f37e,
1838 .gpio2 = 0x00000000,
1839 } },
1840 .radio = {
1841 .type = CX88_RADIO,
1842 .gpio0 = 0x000000ff,
1843 .gpio1 = 0x0000f35d,
1844 .gpio2 = 0x00000000,
1845 },
1846 .mpeg = CX88_MPEG_DVB,
1847 },
1848 [CX88_BOARD_HAUPPAUGE_HVR4000] = {
1849 .name = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid",
1850 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
1851 .radio_type = UNSET,
1852 .tuner_addr = ADDR_UNSET,
1853 .radio_addr = ADDR_UNSET,
1854 .tda9887_conf = TDA9887_PRESENT,
1855 .audio_chip = V4L2_IDENT_WM8775,
1856 /*
1857 * GPIO0 (WINTV2000)
1858 *
1859 * Analogue SAT DVB-T
1860 * Antenna 0xc4bf 0xc4bb
1861 * Composite 0xc4bf 0xc4bb
1862 * S-Video 0xc4bf 0xc4bb
1863 * Composite1 0xc4ff 0xc4fb
1864 * S-Video1 0xc4ff 0xc4fb
1865 *
1866 * BIT VALUE FUNCTION GP{x}_IO
1867 * 0 1 I:?
1868 * 1 1 I:?
1869 * 2 1 O:MPEG PORT 0=DVB-T 1=DVB-S
1870 * 3 1 I:?
1871 * 4 1 I:?
1872 * 5 1 I:?
1873 * 6 0 O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION
1874 * 7 1 O:DVB-T DEMOD RESET LOW
1875 *
1876 * BIT VALUE FUNCTION GP{x}_OE
1877 * 8 0 I
1878 * 9 0 I
1879 * a 1 O
1880 * b 0 I
1881 * c 0 I
1882 * d 0 I
1883 * e 1 O
1884 * f 1 O
1885 *
1886 * WM8775 ADC
1887 *
1888 * 1: TV Audio / FM Mono
1889 * 2: Line-In
1890 * 3: Line-In Expansion
1891 * 4: FM Stereo
1892 */
1893 .input = {{
1894 .type = CX88_VMUX_TELEVISION,
1895 .vmux = 0,
1896 .gpio0 = 0xc4bf,
1897 /* 1: TV Audio / FM Mono */
1898 .audioroute = 1,
1899 }, {
1900 .type = CX88_VMUX_COMPOSITE1,
1901 .vmux = 1,
1902 .gpio0 = 0xc4bf,
1903 /* 2: Line-In */
1904 .audioroute = 2,
1905 }, {
1906 .type = CX88_VMUX_SVIDEO,
1907 .vmux = 2,
1908 .gpio0 = 0xc4bf,
1909 /* 2: Line-In */
1910 .audioroute = 2,
1911 } },
1912 .radio = {
1913 .type = CX88_RADIO,
1914 .gpio0 = 0xc4bf,
1915 /* 4: FM Stereo */
1916 .audioroute = 8,
1917 },
1918 .mpeg = CX88_MPEG_DVB,
1919 .num_frontends = 2,
1920 },
1921 [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = {
1922 .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2",
1923 .tuner_type = UNSET,
1924 .radio_type = UNSET,
1925 .tuner_addr = ADDR_UNSET,
1926 .radio_addr = ADDR_UNSET,
1927 .input = {{
1928 .type = CX88_VMUX_DVB,
1929 .vmux = 0,
1930 } },
1931 .mpeg = CX88_MPEG_DVB,
1932 },
1933 [CX88_BOARD_TEVII_S420] = {
1934 .name = "TeVii S420 DVB-S",
1935 .tuner_type = UNSET,
1936 .radio_type = UNSET,
1937 .tuner_addr = ADDR_UNSET,
1938 .radio_addr = ADDR_UNSET,
1939 .input = {{
1940 .type = CX88_VMUX_DVB,
1941 .vmux = 0,
1942 } },
1943 .mpeg = CX88_MPEG_DVB,
1944 },
1945 [CX88_BOARD_TEVII_S460] = {
1946 .name = "TeVii S460 DVB-S/S2",
1947 .tuner_type = UNSET,
1948 .radio_type = UNSET,
1949 .tuner_addr = ADDR_UNSET,
1950 .radio_addr = ADDR_UNSET,
1951 .input = {{
1952 .type = CX88_VMUX_DVB,
1953 .vmux = 0,
1954 } },
1955 .mpeg = CX88_MPEG_DVB,
1956 },
1957 [CX88_BOARD_TEVII_S464] = {
1958 .name = "TeVii S464 DVB-S/S2",
1959 .tuner_type = UNSET,
1960 .radio_type = UNSET,
1961 .tuner_addr = ADDR_UNSET,
1962 .radio_addr = ADDR_UNSET,
1963 .input = {{
1964 .type = CX88_VMUX_DVB,
1965 .vmux = 0,
1966 } },
1967 .mpeg = CX88_MPEG_DVB,
1968 },
1969 [CX88_BOARD_OMICOM_SS4_PCI] = {
1970 .name = "Omicom SS4 DVB-S/S2 PCI",
1971 .tuner_type = UNSET,
1972 .radio_type = UNSET,
1973 .tuner_addr = ADDR_UNSET,
1974 .radio_addr = ADDR_UNSET,
1975 .input = {{
1976 .type = CX88_VMUX_DVB,
1977 .vmux = 0,
1978 } },
1979 .mpeg = CX88_MPEG_DVB,
1980 },
1981 [CX88_BOARD_TBS_8910] = {
1982 .name = "TBS 8910 DVB-S",
1983 .tuner_type = UNSET,
1984 .radio_type = UNSET,
1985 .tuner_addr = ADDR_UNSET,
1986 .radio_addr = ADDR_UNSET,
1987 .input = {{
1988 .type = CX88_VMUX_DVB,
1989 .vmux = 0,
1990 } },
1991 .mpeg = CX88_MPEG_DVB,
1992 },
1993 [CX88_BOARD_TBS_8920] = {
1994 .name = "TBS 8920 DVB-S/S2",
1995 .tuner_type = TUNER_ABSENT,
1996 .radio_type = UNSET,
1997 .tuner_addr = ADDR_UNSET,
1998 .radio_addr = ADDR_UNSET,
1999 .input = {{
2000 .type = CX88_VMUX_DVB,
2001 .vmux = 0,
2002 .gpio0 = 0x8080,
2003 } },
2004 .mpeg = CX88_MPEG_DVB,
2005 },
2006 [CX88_BOARD_PROF_6200] = {
2007 .name = "Prof 6200 DVB-S",
2008 .tuner_type = UNSET,
2009 .radio_type = UNSET,
2010 .tuner_addr = ADDR_UNSET,
2011 .radio_addr = ADDR_UNSET,
2012 .input = {{
2013 .type = CX88_VMUX_DVB,
2014 .vmux = 0,
2015 } },
2016 .mpeg = CX88_MPEG_DVB,
2017 },
2018 [CX88_BOARD_PROF_7300] = {
2019 .name = "PROF 7300 DVB-S/S2",
2020 .tuner_type = UNSET,
2021 .radio_type = UNSET,
2022 .tuner_addr = ADDR_UNSET,
2023 .radio_addr = ADDR_UNSET,
2024 .input = {{
2025 .type = CX88_VMUX_DVB,
2026 .vmux = 0,
2027 } },
2028 .mpeg = CX88_MPEG_DVB,
2029 },
2030 [CX88_BOARD_SATTRADE_ST4200] = {
2031 .name = "SATTRADE ST4200 DVB-S/S2",
2032 .tuner_type = UNSET,
2033 .radio_type = UNSET,
2034 .tuner_addr = ADDR_UNSET,
2035 .radio_addr = ADDR_UNSET,
2036 .input = {{
2037 .type = CX88_VMUX_DVB,
2038 .vmux = 0,
2039 } },
2040 .mpeg = CX88_MPEG_DVB,
2041 },
2042 [CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII] = {
2043 .name = "Terratec Cinergy HT PCI MKII",
2044 .tuner_type = TUNER_XC2028,
2045 .tuner_addr = 0x61,
2046 .radio_type = TUNER_XC2028,
2047 .radio_addr = 0x61,
2048 .input = { {
2049 .type = CX88_VMUX_TELEVISION,
2050 .vmux = 0,
2051 .gpio0 = 0x004ff,
2052 .gpio1 = 0x010ff,
2053 .gpio2 = 0x00001,
2054 }, {
2055 .type = CX88_VMUX_COMPOSITE1,
2056 .vmux = 1,
2057 .gpio0 = 0x004fb,
2058 .gpio1 = 0x010ef,
2059 .audioroute = 1,
2060 }, {
2061 .type = CX88_VMUX_SVIDEO,
2062 .vmux = 2,
2063 .gpio0 = 0x004fb,
2064 .gpio1 = 0x010ef,
2065 .audioroute = 1,
2066 } },
2067 .radio = {
2068 .type = CX88_RADIO,
2069 .gpio0 = 0x004ff,
2070 .gpio1 = 0x010ff,
2071 .gpio2 = 0x0ff,
2072 },
2073 .mpeg = CX88_MPEG_DVB,
2074 },
2075 [CX88_BOARD_HAUPPAUGE_IRONLY] = {
2076 .name = "Hauppauge WinTV-IR Only",
2077 .tuner_type = UNSET,
2078 .radio_type = UNSET,
2079 .tuner_addr = ADDR_UNSET,
2080 .radio_addr = ADDR_UNSET,
2081 },
2082 [CX88_BOARD_WINFAST_DTV1800H] = {
2083 .name = "Leadtek WinFast DTV1800 Hybrid",
2084 .tuner_type = TUNER_XC2028,
2085 .radio_type = TUNER_XC2028,
2086 .tuner_addr = 0x61,
2087 .radio_addr = 0x61,
2088 /*
2089 * GPIO setting
2090 *
2091 * 2: mute (0=off,1=on)
2092 * 12: tuner reset pin
2093 * 13: audio source (0=tuner audio,1=line in)
2094 * 14: FM (0=on,1=off ???)
2095 */
2096 .input = {{
2097 .type = CX88_VMUX_TELEVISION,
2098 .vmux = 0,
2099 .gpio0 = 0x0400, /* pin 2 = 0 */
2100 .gpio1 = 0x6040, /* pin 13 = 0, pin 14 = 1 */
2101 .gpio2 = 0x0000,
2102 }, {
2103 .type = CX88_VMUX_COMPOSITE1,
2104 .vmux = 1,
2105 .gpio0 = 0x0400, /* pin 2 = 0 */
2106 .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
2107 .gpio2 = 0x0000,
2108 }, {
2109 .type = CX88_VMUX_SVIDEO,
2110 .vmux = 2,
2111 .gpio0 = 0x0400, /* pin 2 = 0 */
2112 .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
2113 .gpio2 = 0x0000,
2114 } },
2115 .radio = {
2116 .type = CX88_RADIO,
2117 .gpio0 = 0x0400, /* pin 2 = 0 */
2118 .gpio1 = 0x6000, /* pin 13 = 0, pin 14 = 0 */
2119 .gpio2 = 0x0000,
2120 },
2121 .mpeg = CX88_MPEG_DVB,
2122 },
2123 [CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
2124 .name = "Leadtek WinFast DTV1800 H (XC4000)",
2125 .tuner_type = TUNER_XC4000,
2126 .radio_type = TUNER_XC4000,
2127 .tuner_addr = 0x61,
2128 .radio_addr = 0x61,
2129 /*
2130 * GPIO setting
2131 *
2132 * 2: mute (0=off,1=on)
2133 * 12: tuner reset pin
2134 * 13: audio source (0=tuner audio,1=line in)
2135 * 14: FM (0=on,1=off ???)
2136 */
2137 .input = {{
2138 .type = CX88_VMUX_TELEVISION,
2139 .vmux = 0,
2140 .gpio0 = 0x0400, /* pin 2 = 0 */
2141 .gpio1 = 0x6040, /* pin 13 = 0, pin 14 = 1 */
2142 .gpio2 = 0x0000,
2143 }, {
2144 .type = CX88_VMUX_COMPOSITE1,
2145 .vmux = 1,
2146 .gpio0 = 0x0400, /* pin 2 = 0 */
2147 .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
2148 .gpio2 = 0x0000,
2149 }, {
2150 .type = CX88_VMUX_SVIDEO,
2151 .vmux = 2,
2152 .gpio0 = 0x0400, /* pin 2 = 0 */
2153 .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
2154 .gpio2 = 0x0000,
2155 }},
2156 .radio = {
2157 .type = CX88_RADIO,
2158 .gpio0 = 0x0400, /* pin 2 = 0 */
2159 .gpio1 = 0x6000, /* pin 13 = 0, pin 14 = 0 */
2160 .gpio2 = 0x0000,
2161 },
2162 .mpeg = CX88_MPEG_DVB,
2163 },
2164 [CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
2165 .name = "Leadtek WinFast DTV2000 H PLUS",
2166 .tuner_type = TUNER_XC4000,
2167 .radio_type = TUNER_XC4000,
2168 .tuner_addr = 0x61,
2169 .radio_addr = 0x61,
2170 /*
2171 * GPIO
2172 * 2: 1: mute audio
2173 * 12: 0: reset XC4000
2174 * 13: 1: audio input is line in (0: tuner)
2175 * 14: 0: FM radio
2176 * 16: 0: RF input is cable
2177 */
2178 .input = {{
2179 .type = CX88_VMUX_TELEVISION,
2180 .vmux = 0,
2181 .gpio0 = 0x0403,
2182 .gpio1 = 0xF0D7,
2183 .gpio2 = 0x0101,
2184 .gpio3 = 0x0000,
2185 }, {
2186 .type = CX88_VMUX_CABLE,
2187 .vmux = 0,
2188 .gpio0 = 0x0403,
2189 .gpio1 = 0xF0D7,
2190 .gpio2 = 0x0100,
2191 .gpio3 = 0x0000,
2192 }, {
2193 .type = CX88_VMUX_COMPOSITE1,
2194 .vmux = 1,
2195 .gpio0 = 0x0403, /* was 0x0407 */
2196 .gpio1 = 0xF0F7,
2197 .gpio2 = 0x0101,
2198 .gpio3 = 0x0000,
2199 }, {
2200 .type = CX88_VMUX_SVIDEO,
2201 .vmux = 2,
2202 .gpio0 = 0x0403, /* was 0x0407 */
2203 .gpio1 = 0xF0F7,
2204 .gpio2 = 0x0101,
2205 .gpio3 = 0x0000,
2206 }},
2207 .radio = {
2208 .type = CX88_RADIO,
2209 .gpio0 = 0x0403,
2210 .gpio1 = 0xF097,
2211 .gpio2 = 0x0100,
2212 .gpio3 = 0x0000,
2213 },
2214 .mpeg = CX88_MPEG_DVB,
2215 },
2216 [CX88_BOARD_PROF_7301] = {
2217 .name = "Prof 7301 DVB-S/S2",
2218 .tuner_type = UNSET,
2219 .radio_type = UNSET,
2220 .tuner_addr = ADDR_UNSET,
2221 .radio_addr = ADDR_UNSET,
2222 .input = { {
2223 .type = CX88_VMUX_DVB,
2224 .vmux = 0,
2225 } },
2226 .mpeg = CX88_MPEG_DVB,
2227 },
2228 [CX88_BOARD_TWINHAN_VP1027_DVBS] = {
2229 .name = "Twinhan VP-1027 DVB-S",
2230 .tuner_type = TUNER_ABSENT,
2231 .radio_type = UNSET,
2232 .tuner_addr = ADDR_UNSET,
2233 .radio_addr = ADDR_UNSET,
2234 .input = {{
2235 .type = CX88_VMUX_DVB,
2236 .vmux = 0,
2237 } },
2238 .mpeg = CX88_MPEG_DVB,
2239 },
2240};
2241
2242/* ------------------------------------------------------------------ */
2243/* PCI subsystem IDs */
2244
2245static const struct cx88_subid cx88_subids[] = {
2246 {
2247 .subvendor = 0x0070,
2248 .subdevice = 0x3400,
2249 .card = CX88_BOARD_HAUPPAUGE,
2250 },{
2251 .subvendor = 0x0070,
2252 .subdevice = 0x3401,
2253 .card = CX88_BOARD_HAUPPAUGE,
2254 },{
2255 .subvendor = 0x14c7,
2256 .subdevice = 0x0106,
2257 .card = CX88_BOARD_GDI,
2258 },{
2259 .subvendor = 0x14c7,
2260 .subdevice = 0x0107, /* with mpeg encoder */
2261 .card = CX88_BOARD_GDI,
2262 },{
2263 .subvendor = PCI_VENDOR_ID_ATI,
2264 .subdevice = 0x00f8,
2265 .card = CX88_BOARD_ATI_WONDER_PRO,
2266 }, {
2267 .subvendor = PCI_VENDOR_ID_ATI,
2268 .subdevice = 0x00f9,
2269 .card = CX88_BOARD_ATI_WONDER_PRO,
2270 }, {
2271 .subvendor = 0x107d,
2272 .subdevice = 0x6611,
2273 .card = CX88_BOARD_WINFAST2000XP_EXPERT,
2274 },{
2275 .subvendor = 0x107d,
2276 .subdevice = 0x6613, /* NTSC */
2277 .card = CX88_BOARD_WINFAST2000XP_EXPERT,
2278 },{
2279 .subvendor = 0x107d,
2280 .subdevice = 0x6620,
2281 .card = CX88_BOARD_WINFAST_DV2000,
2282 },{
2283 .subvendor = 0x107d,
2284 .subdevice = 0x663b,
2285 .card = CX88_BOARD_LEADTEK_PVR2000,
2286 },{
2287 .subvendor = 0x107d,
2288 .subdevice = 0x663c,
2289 .card = CX88_BOARD_LEADTEK_PVR2000,
2290 },{
2291 .subvendor = 0x1461,
2292 .subdevice = 0x000b,
2293 .card = CX88_BOARD_AVERTV_STUDIO_303,
2294 },{
2295 .subvendor = 0x1462,
2296 .subdevice = 0x8606,
2297 .card = CX88_BOARD_MSI_TVANYWHERE_MASTER,
2298 },{
2299 .subvendor = 0x10fc,
2300 .subdevice = 0xd003,
2301 .card = CX88_BOARD_IODATA_GVVCP3PCI,
2302 },{
2303 .subvendor = 0x1043,
2304 .subdevice = 0x4823, /* with mpeg encoder */
2305 .card = CX88_BOARD_ASUS_PVR_416,
2306 },{
2307 .subvendor = 0x17de,
2308 .subdevice = 0x08a6,
2309 .card = CX88_BOARD_KWORLD_DVB_T,
2310 },{
2311 .subvendor = 0x18ac,
2312 .subdevice = 0xd810,
2313 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
2314 },{
2315 .subvendor = 0x18ac,
2316 .subdevice = 0xd820,
2317 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T,
2318 },{
2319 .subvendor = 0x18ac,
2320 .subdevice = 0xdb00,
2321 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1,
2322 },{
2323 .subvendor = 0x0070,
2324 .subdevice = 0x9002,
2325 .card = CX88_BOARD_HAUPPAUGE_DVB_T1,
2326 },{
2327 .subvendor = 0x14f1,
2328 .subdevice = 0x0187,
2329 .card = CX88_BOARD_CONEXANT_DVB_T1,
2330 },{
2331 .subvendor = 0x1540,
2332 .subdevice = 0x2580,
2333 .card = CX88_BOARD_PROVIDEO_PV259,
2334 },{
2335 .subvendor = 0x18ac,
2336 .subdevice = 0xdb10,
2337 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
2338 },{
2339 .subvendor = 0x1554,
2340 .subdevice = 0x4811,
2341 .card = CX88_BOARD_PIXELVIEW,
2342 },{
2343 .subvendor = 0x7063,
2344 .subdevice = 0x3000, /* HD-3000 card */
2345 .card = CX88_BOARD_PCHDTV_HD3000,
2346 },{
2347 .subvendor = 0x17de,
2348 .subdevice = 0xa8a6,
2349 .card = CX88_BOARD_DNTV_LIVE_DVB_T,
2350 },{
2351 .subvendor = 0x0070,
2352 .subdevice = 0x2801,
2353 .card = CX88_BOARD_HAUPPAUGE_ROSLYN,
2354 },{
2355 .subvendor = 0x14f1,
2356 .subdevice = 0x0342,
2357 .card = CX88_BOARD_DIGITALLOGIC_MEC,
2358 },{
2359 .subvendor = 0x10fc,
2360 .subdevice = 0xd035,
2361 .card = CX88_BOARD_IODATA_GVBCTV7E,
2362 },{
2363 .subvendor = 0x1421,
2364 .subdevice = 0x0334,
2365 .card = CX88_BOARD_ADSTECH_DVB_T_PCI,
2366 },{
2367 .subvendor = 0x153b,
2368 .subdevice = 0x1166,
2369 .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1,
2370 },{
2371 .subvendor = 0x18ac,
2372 .subdevice = 0xd500,
2373 .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD,
2374 },{
2375 .subvendor = 0x1461,
2376 .subdevice = 0x8011,
2377 .card = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550,
2378 },{
2379 .subvendor = PCI_VENDOR_ID_ATI,
2380 .subdevice = 0xa101,
2381 .card = CX88_BOARD_ATI_HDTVWONDER,
2382 },{
2383 .subvendor = 0x107d,
2384 .subdevice = 0x665f,
2385 .card = CX88_BOARD_WINFAST_DTV1000,
2386 },{
2387 .subvendor = 0x1461,
2388 .subdevice = 0x000a,
2389 .card = CX88_BOARD_AVERTV_303,
2390 },{
2391 .subvendor = 0x0070,
2392 .subdevice = 0x9200,
2393 .card = CX88_BOARD_HAUPPAUGE_NOVASE2_S1,
2394 },{
2395 .subvendor = 0x0070,
2396 .subdevice = 0x9201,
2397 .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
2398 },{
2399 .subvendor = 0x0070,
2400 .subdevice = 0x9202,
2401 .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
2402 },{
2403 .subvendor = 0x17de,
2404 .subdevice = 0x08b2,
2405 .card = CX88_BOARD_KWORLD_DVBS_100,
2406 },{
2407 .subvendor = 0x0070,
2408 .subdevice = 0x9400,
2409 .card = CX88_BOARD_HAUPPAUGE_HVR1100,
2410 },{
2411 .subvendor = 0x0070,
2412 .subdevice = 0x9402,
2413 .card = CX88_BOARD_HAUPPAUGE_HVR1100,
2414 },{
2415 .subvendor = 0x0070,
2416 .subdevice = 0x9800,
2417 .card = CX88_BOARD_HAUPPAUGE_HVR1100LP,
2418 },{
2419 .subvendor = 0x0070,
2420 .subdevice = 0x9802,
2421 .card = CX88_BOARD_HAUPPAUGE_HVR1100LP,
2422 },{
2423 .subvendor = 0x0070,
2424 .subdevice = 0x9001,
2425 .card = CX88_BOARD_HAUPPAUGE_DVB_T1,
2426 },{
2427 .subvendor = 0x1822,
2428 .subdevice = 0x0025,
2429 .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
2430 },{
2431 .subvendor = 0x17de,
2432 .subdevice = 0x08a1,
2433 .card = CX88_BOARD_KWORLD_DVB_T_CX22702,
2434 },{
2435 .subvendor = 0x18ac,
2436 .subdevice = 0xdb50,
2437 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
2438 },{
2439 .subvendor = 0x18ac,
2440 .subdevice = 0xdb54,
2441 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
2442 /* Re-branded DViCO: DigitalNow DVB-T Dual */
2443 },{
2444 .subvendor = 0x18ac,
2445 .subdevice = 0xdb11,
2446 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
2447 /* Re-branded DViCO: UltraView DVB-T Plus */
2448 }, {
2449 .subvendor = 0x18ac,
2450 .subdevice = 0xdb30,
2451 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO,
2452 }, {
2453 .subvendor = 0x17de,
2454 .subdevice = 0x0840,
2455 .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
2456 },{
2457 .subvendor = 0x1421,
2458 .subdevice = 0x0305,
2459 .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
2460 },{
2461 .subvendor = 0x18ac,
2462 .subdevice = 0xdb40,
2463 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
2464 },{
2465 .subvendor = 0x18ac,
2466 .subdevice = 0xdb44,
2467 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
2468 },{
2469 .subvendor = 0x7063,
2470 .subdevice = 0x5500,
2471 .card = CX88_BOARD_PCHDTV_HD5500,
2472 },{
2473 .subvendor = 0x17de,
2474 .subdevice = 0x0841,
2475 .card = CX88_BOARD_KWORLD_MCE200_DELUXE,
2476 },{
2477 .subvendor = 0x1822,
2478 .subdevice = 0x0019,
2479 .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
2480 },{
2481 .subvendor = 0x1554,
2482 .subdevice = 0x4813,
2483 .card = CX88_BOARD_PIXELVIEW_PLAYTV_P7000,
2484 },{
2485 .subvendor = 0x14f1,
2486 .subdevice = 0x0842,
2487 .card = CX88_BOARD_NPGTECH_REALTV_TOP10FM,
2488 },{
2489 .subvendor = 0x107d,
2490 .subdevice = 0x665e,
2491 .card = CX88_BOARD_WINFAST_DTV2000H,
2492 },{
2493 .subvendor = 0x107d,
2494 .subdevice = 0x6f2b,
2495 .card = CX88_BOARD_WINFAST_DTV2000H_J,
2496 },{
2497 .subvendor = 0x18ac,
2498 .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */
2499 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
2500 },{
2501 .subvendor = 0x14f1,
2502 .subdevice = 0x0084,
2503 .card = CX88_BOARD_GENIATECH_DVBS,
2504 },{
2505 .subvendor = 0x0070,
2506 .subdevice = 0x1404,
2507 .card = CX88_BOARD_HAUPPAUGE_HVR3000,
2508 }, {
2509 .subvendor = 0x18ac,
2510 .subdevice = 0xdc00,
2511 .card = CX88_BOARD_SAMSUNG_SMT_7020,
2512 }, {
2513 .subvendor = 0x18ac,
2514 .subdevice = 0xdccd,
2515 .card = CX88_BOARD_SAMSUNG_SMT_7020,
2516 },{
2517 .subvendor = 0x1461,
2518 .subdevice = 0xc111, /* AverMedia M150-D */
2519 /* This board is known to work with the ASUS PVR416 config */
2520 .card = CX88_BOARD_ASUS_PVR_416,
2521 },{
2522 .subvendor = 0xc180,
2523 .subdevice = 0xc980,
2524 .card = CX88_BOARD_TE_DTV_250_OEM_SWANN,
2525 },{
2526 .subvendor = 0x0070,
2527 .subdevice = 0x9600,
2528 .card = CX88_BOARD_HAUPPAUGE_HVR1300,
2529 },{
2530 .subvendor = 0x0070,
2531 .subdevice = 0x9601,
2532 .card = CX88_BOARD_HAUPPAUGE_HVR1300,
2533 },{
2534 .subvendor = 0x0070,
2535 .subdevice = 0x9602,
2536 .card = CX88_BOARD_HAUPPAUGE_HVR1300,
2537 },{
2538 .subvendor = 0x107d,
2539 .subdevice = 0x6632,
2540 .card = CX88_BOARD_LEADTEK_PVR2000,
2541 },{
2542 .subvendor = 0x12ab,
2543 .subdevice = 0x2300, /* Club3D Zap TV2100 */
2544 .card = CX88_BOARD_KWORLD_DVB_T_CX22702,
2545 },{
2546 .subvendor = 0x0070,
2547 .subdevice = 0x9000,
2548 .card = CX88_BOARD_HAUPPAUGE_DVB_T1,
2549 },{
2550 .subvendor = 0x0070,
2551 .subdevice = 0x1400,
2552 .card = CX88_BOARD_HAUPPAUGE_HVR3000,
2553 },{
2554 .subvendor = 0x0070,
2555 .subdevice = 0x1401,
2556 .card = CX88_BOARD_HAUPPAUGE_HVR3000,
2557 },{
2558 .subvendor = 0x0070,
2559 .subdevice = 0x1402,
2560 .card = CX88_BOARD_HAUPPAUGE_HVR3000,
2561 },{
2562 .subvendor = 0x1421,
2563 .subdevice = 0x0341, /* ADS Tech InstantTV DVB-S */
2564 .card = CX88_BOARD_KWORLD_DVBS_100,
2565 },{
2566 .subvendor = 0x1421,
2567 .subdevice = 0x0390,
2568 .card = CX88_BOARD_ADSTECH_PTV_390,
2569 },{
2570 .subvendor = 0x11bd,
2571 .subdevice = 0x0051,
2572 .card = CX88_BOARD_PINNACLE_PCTV_HD_800i,
2573 }, {
2574 .subvendor = 0x18ac,
2575 .subdevice = 0xd530,
2576 .card = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO,
2577 }, {
2578 .subvendor = 0x12ab,
2579 .subdevice = 0x1788,
2580 .card = CX88_BOARD_PINNACLE_HYBRID_PCTV,
2581 }, {
2582 .subvendor = 0x14f1,
2583 .subdevice = 0xea3d,
2584 .card = CX88_BOARD_POWERCOLOR_REAL_ANGEL,
2585 }, {
2586 .subvendor = 0x107d,
2587 .subdevice = 0x6f18,
2588 .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
2589 }, {
2590 .subvendor = 0x14f1,
2591 .subdevice = 0x8852,
2592 .card = CX88_BOARD_GENIATECH_X8000_MT,
2593 }, {
2594 .subvendor = 0x18ac,
2595 .subdevice = 0xd610,
2596 .card = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD,
2597 }, {
2598 .subvendor = 0x1554,
2599 .subdevice = 0x4935,
2600 .card = CX88_BOARD_PROLINK_PV_8000GT,
2601 }, {
2602 .subvendor = 0x1554,
2603 .subdevice = 0x4976,
2604 .card = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME,
2605 }, {
2606 .subvendor = 0x17de,
2607 .subdevice = 0x08c1,
2608 .card = CX88_BOARD_KWORLD_ATSC_120,
2609 }, {
2610 .subvendor = 0x0070,
2611 .subdevice = 0x6900,
2612 .card = CX88_BOARD_HAUPPAUGE_HVR4000,
2613 }, {
2614 .subvendor = 0x0070,
2615 .subdevice = 0x6904,
2616 .card = CX88_BOARD_HAUPPAUGE_HVR4000,
2617 }, {
2618 .subvendor = 0x0070,
2619 .subdevice = 0x6902,
2620 .card = CX88_BOARD_HAUPPAUGE_HVR4000,
2621 }, {
2622 .subvendor = 0x0070,
2623 .subdevice = 0x6905,
2624 .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
2625 }, {
2626 .subvendor = 0x0070,
2627 .subdevice = 0x6906,
2628 .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
2629 }, {
2630 .subvendor = 0xd420,
2631 .subdevice = 0x9022,
2632 .card = CX88_BOARD_TEVII_S420,
2633 }, {
2634 .subvendor = 0xd460,
2635 .subdevice = 0x9022,
2636 .card = CX88_BOARD_TEVII_S460,
2637 }, {
2638 .subvendor = 0xd464,
2639 .subdevice = 0x9022,
2640 .card = CX88_BOARD_TEVII_S464,
2641 }, {
2642 .subvendor = 0xA044,
2643 .subdevice = 0x2011,
2644 .card = CX88_BOARD_OMICOM_SS4_PCI,
2645 }, {
2646 .subvendor = 0x8910,
2647 .subdevice = 0x8888,
2648 .card = CX88_BOARD_TBS_8910,
2649 }, {
2650 .subvendor = 0x8920,
2651 .subdevice = 0x8888,
2652 .card = CX88_BOARD_TBS_8920,
2653 }, {
2654 .subvendor = 0xb022,
2655 .subdevice = 0x3022,
2656 .card = CX88_BOARD_PROF_6200,
2657 }, {
2658 .subvendor = 0xB033,
2659 .subdevice = 0x3033,
2660 .card = CX88_BOARD_PROF_7300,
2661 }, {
2662 .subvendor = 0xb200,
2663 .subdevice = 0x4200,
2664 .card = CX88_BOARD_SATTRADE_ST4200,
2665 }, {
2666 .subvendor = 0x153b,
2667 .subdevice = 0x1177,
2668 .card = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII,
2669 }, {
2670 .subvendor = 0x0070,
2671 .subdevice = 0x9290,
2672 .card = CX88_BOARD_HAUPPAUGE_IRONLY,
2673 }, {
2674 .subvendor = 0x107d,
2675 .subdevice = 0x6654,
2676 .card = CX88_BOARD_WINFAST_DTV1800H,
2677 }, {
2678 /* WinFast DTV1800 H with XC4000 tuner */
2679 .subvendor = 0x107d,
2680 .subdevice = 0x6f38,
2681 .card = CX88_BOARD_WINFAST_DTV1800H_XC4000,
2682 }, {
2683 .subvendor = 0x107d,
2684 .subdevice = 0x6f42,
2685 .card = CX88_BOARD_WINFAST_DTV2000H_PLUS,
2686 }, {
2687 /* PVR2000 PAL Model [107d:6630] */
2688 .subvendor = 0x107d,
2689 .subdevice = 0x6630,
2690 .card = CX88_BOARD_LEADTEK_PVR2000,
2691 }, {
2692 /* PVR2000 PAL Model [107d:6638] */
2693 .subvendor = 0x107d,
2694 .subdevice = 0x6638,
2695 .card = CX88_BOARD_LEADTEK_PVR2000,
2696 }, {
2697 /* PVR2000 NTSC Model [107d:6631] */
2698 .subvendor = 0x107d,
2699 .subdevice = 0x6631,
2700 .card = CX88_BOARD_LEADTEK_PVR2000,
2701 }, {
2702 /* PVR2000 NTSC Model [107d:6637] */
2703 .subvendor = 0x107d,
2704 .subdevice = 0x6637,
2705 .card = CX88_BOARD_LEADTEK_PVR2000,
2706 }, {
2707 /* PVR2000 NTSC Model [107d:663d] */
2708 .subvendor = 0x107d,
2709 .subdevice = 0x663d,
2710 .card = CX88_BOARD_LEADTEK_PVR2000,
2711 }, {
2712 /* DV2000 NTSC Model [107d:6621] */
2713 .subvendor = 0x107d,
2714 .subdevice = 0x6621,
2715 .card = CX88_BOARD_WINFAST_DV2000,
2716 }, {
2717 /* TV2000 XP Global [107d:6618] */
2718 .subvendor = 0x107d,
2719 .subdevice = 0x6618,
2720 .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
2721 }, {
2722 .subvendor = 0xb034,
2723 .subdevice = 0x3034,
2724 .card = CX88_BOARD_PROF_7301,
2725 }, {
2726 .subvendor = 0x1822,
2727 .subdevice = 0x0023,
2728 .card = CX88_BOARD_TWINHAN_VP1027_DVBS,
2729 },
2730};
2731
2732/* ----------------------------------------------------------------------- */
2733/* some leadtek specific stuff */
2734
2735static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
2736{
2737 if (eeprom_data[4] != 0x7d ||
2738 eeprom_data[5] != 0x10 ||
2739 eeprom_data[7] != 0x66) {
2740 warn_printk(core, "Leadtek eeprom invalid.\n");
2741 return;
2742 }
2743
2744 /* Terry Wu <terrywu2009@gmail.com> */
2745 switch (eeprom_data[6]) {
2746 case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */
2747 case 0x21: /* SSID 6621 for DV2000 NTSC Model */
2748 case 0x31: /* SSID 6631 for PVR2000 NTSC Model */
2749 case 0x37: /* SSID 6637 for PVR2000 NTSC Model */
2750 case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */
2751 core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3;
2752 break;
2753 default:
2754 core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
2755 break;
2756 }
2757
2758 info_printk(core, "Leadtek Winfast 2000XP Expert config: "
2759 "tuner=%d, eeprom[0]=0x%02x\n",
2760 core->board.tuner_type, eeprom_data[0]);
2761}
2762
2763static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
2764{
2765 struct tveeprom tv;
2766
2767 tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
2768 core->board.tuner_type = tv.tuner_type;
2769 core->tuner_formats = tv.tuner_formats;
2770 core->board.radio.type = tv.has_radio ? CX88_RADIO : 0;
2771
2772 /* Make sure we support the board model */
2773 switch (tv.model)
2774 {
2775 case 14009: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in) */
2776 case 14019: /* WinTV-HVR3000 (Retail, IR Blaster, b/panel video, 3.5mm audio in) */
2777 case 14029: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge) */
2778 case 14109: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - low profile) */
2779 case 14129: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge - LP) */
2780 case 14559: /* WinTV-HVR3000 (OEM, no IR, b/panel video, 3.5mm audio in) */
2781 case 14569: /* WinTV-HVR3000 (OEM, no IR, no back panel video) */
2782 case 14659: /* WinTV-HVR3000 (OEM, no IR, b/panel video, RCA audio in - Low profile) */
2783 case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */
2784 case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
2785 case 34519: /* WinTV-PCI-FM */
2786 case 69009:
2787 /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */
2788 case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */
2789 case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */
2790 case 69559:
2791 /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */
2792 case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */
2793 case 90002: /* Nova-T-PCI (9002) */
2794 case 92001: /* Nova-S-Plus (Video and IR) */
2795 case 92002: /* Nova-S-Plus (Video and IR) */
2796 case 90003: /* Nova-T-PCI (9002 No RF out) */
2797 case 90500: /* Nova-T-PCI (oem) */
2798 case 90501: /* Nova-T-PCI (oem/IR) */
2799 case 92000: /* Nova-SE2 (OEM, No Video or IR) */
2800 case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */
2801 case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
2802 case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
2803 case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */
2804 case 96019: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX/TX) */
2805 case 96559: /* WinTV-HVR1300 (PAL Video, MPEG Video no IR) */
2806 case 96569: /* WinTV-HVR1300 () */
2807 case 96659: /* WinTV-HVR1300 () */
2808 case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */
2809 /* known */
2810 break;
2811 case CX88_BOARD_SAMSUNG_SMT_7020:
2812 cx_set(MO_GP0_IO, 0x008989FF);
2813 break;
2814 default:
2815 warn_printk(core, "warning: unknown hauppauge model #%d\n",
2816 tv.model);
2817 break;
2818 }
2819
2820 info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
2821}
2822
2823/* ----------------------------------------------------------------------- */
2824/* some GDI (was: Modular Technology) specific stuff */
2825
2826static const struct {
2827 int id;
2828 int fm;
2829 const char *name;
2830} gdi_tuner[] = {
2831 [ 0x01 ] = { .id = TUNER_ABSENT,
2832 .name = "NTSC_M" },
2833 [ 0x02 ] = { .id = TUNER_ABSENT,
2834 .name = "PAL_B" },
2835 [ 0x03 ] = { .id = TUNER_ABSENT,
2836 .name = "PAL_I" },
2837 [ 0x04 ] = { .id = TUNER_ABSENT,
2838 .name = "PAL_D" },
2839 [ 0x05 ] = { .id = TUNER_ABSENT,
2840 .name = "SECAM" },
2841
2842 [ 0x10 ] = { .id = TUNER_ABSENT,
2843 .fm = 1,
2844 .name = "TEMIC_4049" },
2845 [ 0x11 ] = { .id = TUNER_TEMIC_4136FY5,
2846 .name = "TEMIC_4136" },
2847 [ 0x12 ] = { .id = TUNER_ABSENT,
2848 .name = "TEMIC_4146" },
2849
2850 [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME,
2851 .fm = 1,
2852 .name = "PHILIPS_FQ1216_MK3" },
2853 [ 0x21 ] = { .id = TUNER_ABSENT, .fm = 1,
2854 .name = "PHILIPS_FQ1236_MK3" },
2855 [ 0x22 ] = { .id = TUNER_ABSENT,
2856 .name = "PHILIPS_FI1236_MK3" },
2857 [ 0x23 ] = { .id = TUNER_ABSENT,
2858 .name = "PHILIPS_FI1216_MK3" },
2859};
2860
2861static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
2862{
2863 const char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
2864 ? gdi_tuner[eeprom_data[0x0d]].name : NULL;
2865
2866 info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
2867 if (NULL == name)
2868 return;
2869 core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
2870 core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ?
2871 CX88_RADIO : 0;
2872}
2873
2874/* ------------------------------------------------------------------- */
2875/* some Divco specific stuff */
2876static int cx88_dvico_xc2028_callback(struct cx88_core *core,
2877 int command, int arg)
2878{
2879 switch (command) {
2880 case XC2028_TUNER_RESET:
2881 switch (core->boardnr) {
2882 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
2883 /* GPIO-4 xc3028 tuner */
2884
2885 cx_set(MO_GP0_IO, 0x00001000);
2886 cx_clear(MO_GP0_IO, 0x00000010);
2887 msleep(100);
2888 cx_set(MO_GP0_IO, 0x00000010);
2889 msleep(100);
2890 break;
2891 default:
2892 cx_write(MO_GP0_IO, 0x101000);
2893 mdelay(5);
2894 cx_set(MO_GP0_IO, 0x101010);
2895 }
2896 break;
2897 default:
2898 return -EINVAL;
2899 }
2900
2901 return 0;
2902}
2903
2904
2905/* ----------------------------------------------------------------------- */
2906/* some Geniatech specific stuff */
2907
2908static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core,
2909 int command, int mode)
2910{
2911 switch (command) {
2912 case XC2028_TUNER_RESET:
2913 switch (INPUT(core->input).type) {
2914 case CX88_RADIO:
2915 break;
2916 case CX88_VMUX_DVB:
2917 cx_write(MO_GP1_IO, 0x030302);
2918 mdelay(50);
2919 break;
2920 default:
2921 cx_write(MO_GP1_IO, 0x030301);
2922 mdelay(50);
2923 }
2924 cx_write(MO_GP1_IO, 0x101010);
2925 mdelay(50);
2926 cx_write(MO_GP1_IO, 0x101000);
2927 mdelay(50);
2928 cx_write(MO_GP1_IO, 0x101010);
2929 mdelay(50);
2930 return 0;
2931 }
2932 return -EINVAL;
2933}
2934
2935static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
2936 int command, int arg)
2937{
2938 switch (command) {
2939 case XC2028_TUNER_RESET:
2940 /* GPIO 12 (xc3028 tuner reset) */
2941 cx_set(MO_GP1_IO, 0x1010);
2942 mdelay(50);
2943 cx_clear(MO_GP1_IO, 0x10);
2944 mdelay(50);
2945 cx_set(MO_GP1_IO, 0x10);
2946 mdelay(50);
2947 return 0;
2948 }
2949 return -EINVAL;
2950}
2951
2952static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core,
2953 int command, int arg)
2954{
2955 switch (command) {
2956 case XC4000_TUNER_RESET:
2957 /* GPIO 12 (xc4000 tuner reset) */
2958 cx_set(MO_GP1_IO, 0x1010);
2959 mdelay(50);
2960 cx_clear(MO_GP1_IO, 0x10);
2961 mdelay(75);
2962 cx_set(MO_GP1_IO, 0x10);
2963 mdelay(75);
2964 return 0;
2965 }
2966 return -EINVAL;
2967}
2968
2969/* ------------------------------------------------------------------- */
2970/* some Divco specific stuff */
2971static int cx88_pv_8000gt_callback(struct cx88_core *core,
2972 int command, int arg)
2973{
2974 switch (command) {
2975 case XC2028_TUNER_RESET:
2976 cx_write(MO_GP2_IO, 0xcf7);
2977 mdelay(50);
2978 cx_write(MO_GP2_IO, 0xef5);
2979 mdelay(50);
2980 cx_write(MO_GP2_IO, 0xcf7);
2981 break;
2982 default:
2983 return -EINVAL;
2984 }
2985
2986 return 0;
2987}
2988
2989/* ----------------------------------------------------------------------- */
2990/* some DViCO specific stuff */
2991
2992static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
2993{
2994 struct i2c_msg msg = { .addr = 0x45, .flags = 0 };
2995 int i, err;
2996 static u8 init_bufs[13][5] = {
2997 { 0x10, 0x00, 0x20, 0x01, 0x03 },
2998 { 0x10, 0x10, 0x01, 0x00, 0x21 },
2999 { 0x10, 0x10, 0x10, 0x00, 0xCA },
3000 { 0x10, 0x10, 0x12, 0x00, 0x08 },
3001 { 0x10, 0x10, 0x13, 0x00, 0x0A },
3002 { 0x10, 0x10, 0x16, 0x01, 0xC0 },
3003 { 0x10, 0x10, 0x22, 0x01, 0x3D },
3004 { 0x10, 0x10, 0x73, 0x01, 0x2E },
3005 { 0x10, 0x10, 0x72, 0x00, 0xC5 },
3006 { 0x10, 0x10, 0x71, 0x01, 0x97 },
3007 { 0x10, 0x10, 0x70, 0x00, 0x0F },
3008 { 0x10, 0x10, 0xB0, 0x00, 0x01 },
3009 { 0x03, 0x0C },
3010 };
3011
3012 for (i = 0; i < ARRAY_SIZE(init_bufs); i++) {
3013 msg.buf = init_bufs[i];
3014 msg.len = (i != 12 ? 5 : 2);
3015 err = i2c_transfer(&core->i2c_adap, &msg, 1);
3016 if (err != 1) {
3017 warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d "
3018 "failed (err = %d)!\n", i, err);
3019 return;
3020 }
3021 }
3022}
3023
3024static int cx88_xc2028_tuner_callback(struct cx88_core *core,
3025 int command, int arg)
3026{
3027 /* Board-specific callbacks */
3028 switch (core->boardnr) {
3029 case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
3030 case CX88_BOARD_GENIATECH_X8000_MT:
3031 case CX88_BOARD_KWORLD_ATSC_120:
3032 return cx88_xc3028_geniatech_tuner_callback(core,
3033 command, arg);
3034 case CX88_BOARD_PROLINK_PV_8000GT:
3035 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
3036 return cx88_pv_8000gt_callback(core, command, arg);
3037 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
3038 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
3039 return cx88_dvico_xc2028_callback(core, command, arg);
3040 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
3041 case CX88_BOARD_WINFAST_DTV1800H:
3042 return cx88_xc3028_winfast1800h_callback(core, command, arg);
3043 }
3044
3045 switch (command) {
3046 case XC2028_TUNER_RESET:
3047 switch (INPUT(core->input).type) {
3048 case CX88_RADIO:
3049 info_printk(core, "setting GPIO to radio!\n");
3050 cx_write(MO_GP0_IO, 0x4ff);
3051 mdelay(250);
3052 cx_write(MO_GP2_IO, 0xff);
3053 mdelay(250);
3054 break;
3055 case CX88_VMUX_DVB: /* Digital TV*/
3056 default: /* Analog TV */
3057 info_printk(core, "setting GPIO to TV!\n");
3058 break;
3059 }
3060 cx_write(MO_GP1_IO, 0x101010);
3061 mdelay(250);
3062 cx_write(MO_GP1_IO, 0x101000);
3063 mdelay(250);
3064 cx_write(MO_GP1_IO, 0x101010);
3065 mdelay(250);
3066 return 0;
3067 }
3068 return -EINVAL;
3069}
3070
3071static int cx88_xc4000_tuner_callback(struct cx88_core *core,
3072 int command, int arg)
3073{
3074 /* Board-specific callbacks */
3075 switch (core->boardnr) {
3076 case CX88_BOARD_WINFAST_DTV1800H_XC4000:
3077 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
3078 return cx88_xc4000_winfast2000h_plus_callback(core,
3079 command, arg);
3080 }
3081 return -EINVAL;
3082}
3083
3084/* ----------------------------------------------------------------------- */
3085/* Tuner callback function. Currently only needed for the Pinnacle *
3086 * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both *
3087 * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c) */
3088
3089static int cx88_xc5000_tuner_callback(struct cx88_core *core,
3090 int command, int arg)
3091{
3092 switch (core->boardnr) {
3093 case CX88_BOARD_PINNACLE_PCTV_HD_800i:
3094 if (command == 0) { /* This is the reset command from xc5000 */
3095
3096 /* djh - According to the engineer at PCTV Systems,
3097 the xc5000 reset pin is supposed to be on GPIO12.
3098 However, despite three nights of effort, pulling
3099 that GPIO low didn't reset the xc5000. While
3100 pulling MO_SRST_IO low does reset the xc5000, this
3101 also resets in the s5h1409 being reset as well.
3102 This causes tuning to always fail since the internal
3103 state of the s5h1409 does not match the driver's
3104 state. Given that the only two conditions in which
3105 the driver performs a reset is during firmware load
3106 and powering down the chip, I am taking out the
3107 reset. We know that the chip is being reset
3108 when the cx88 comes online, and not being able to
3109 do power management for this board is worse than
3110 not having any tuning at all. */
3111 return 0;
3112 } else {
3113 err_printk(core, "xc5000: unknown tuner "
3114 "callback command.\n");
3115 return -EINVAL;
3116 }
3117 break;
3118 case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
3119 if (command == 0) { /* This is the reset command from xc5000 */
3120 cx_clear(MO_GP0_IO, 0x00000010);
3121 msleep(10);
3122 cx_set(MO_GP0_IO, 0x00000010);
3123 return 0;
3124 } else {
3125 printk(KERN_ERR
3126 "xc5000: unknown tuner callback command.\n");
3127 return -EINVAL;
3128 }
3129 break;
3130 }
3131 return 0; /* Should never be here */
3132}
3133
3134int cx88_tuner_callback(void *priv, int component, int command, int arg)
3135{
3136 struct i2c_algo_bit_data *i2c_algo = priv;
3137 struct cx88_core *core;
3138
3139 if (!i2c_algo) {
3140 printk(KERN_ERR "cx88: Error - i2c private data undefined.\n");
3141 return -EINVAL;
3142 }
3143
3144 core = i2c_algo->data;
3145
3146 if (!core) {
3147 printk(KERN_ERR "cx88: Error - device struct undefined.\n");
3148 return -EINVAL;
3149 }
3150
3151 if (component != DVB_FRONTEND_COMPONENT_TUNER)
3152 return -EINVAL;
3153
3154 switch (core->board.tuner_type) {
3155 case TUNER_XC2028:
3156 info_printk(core, "Calling XC2028/3028 callback\n");
3157 return cx88_xc2028_tuner_callback(core, command, arg);
3158 case TUNER_XC4000:
3159 info_printk(core, "Calling XC4000 callback\n");
3160 return cx88_xc4000_tuner_callback(core, command, arg);
3161 case TUNER_XC5000:
3162 info_printk(core, "Calling XC5000 callback\n");
3163 return cx88_xc5000_tuner_callback(core, command, arg);
3164 }
3165 err_printk(core, "Error: Calling callback for tuner %d\n",
3166 core->board.tuner_type);
3167 return -EINVAL;
3168}
3169EXPORT_SYMBOL(cx88_tuner_callback);
3170
3171/* ----------------------------------------------------------------------- */
3172
3173static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
3174{
3175 int i;
3176
3177 if (0 == pci->subsystem_vendor &&
3178 0 == pci->subsystem_device) {
3179 printk(KERN_ERR
3180 "%s: Your board has no valid PCI Subsystem ID and thus can't\n"
3181 "%s: be autodetected. Please pass card=<n> insmod option to\n"
3182 "%s: workaround that. Redirect complaints to the vendor of\n"
3183 "%s: the TV card. Best regards,\n"
3184 "%s: -- tux\n",
3185 core->name,core->name,core->name,core->name,core->name);
3186 } else {
3187 printk(KERN_ERR
3188 "%s: Your board isn't known (yet) to the driver. You can\n"
3189 "%s: try to pick one of the existing card configs via\n"
3190 "%s: card=<n> insmod option. Updating to the latest\n"
3191 "%s: version might help as well.\n",
3192 core->name,core->name,core->name,core->name);
3193 }
3194 err_printk(core, "Here is a list of valid choices for the card=<n> "
3195 "insmod option:\n");
3196 for (i = 0; i < ARRAY_SIZE(cx88_boards); i++)
3197 printk(KERN_ERR "%s: card=%d -> %s\n",
3198 core->name, i, cx88_boards[i].name);
3199}
3200
3201static void cx88_card_setup_pre_i2c(struct cx88_core *core)
3202{
3203 switch (core->boardnr) {
3204 case CX88_BOARD_HAUPPAUGE_HVR1300:
3205 /*
3206 * Bring the 702 demod up before i2c scanning/attach or devices are hidden
3207 * We leave here with the 702 on the bus
3208 *
3209 * "reset the IR receiver on GPIO[3]"
3210 * Reported by Mike Crash <mike AT mikecrash.com>
3211 */
3212 cx_write(MO_GP0_IO, 0x0000ef88);
3213 udelay(1000);
3214 cx_clear(MO_GP0_IO, 0x00000088);
3215 udelay(50);
3216 cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */
3217 udelay(1000);
3218 break;
3219
3220 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
3221 case CX88_BOARD_PROLINK_PV_8000GT:
3222 cx_write(MO_GP2_IO, 0xcf7);
3223 mdelay(50);
3224 cx_write(MO_GP2_IO, 0xef5);
3225 mdelay(50);
3226 cx_write(MO_GP2_IO, 0xcf7);
3227 msleep(10);
3228 break;
3229
3230 case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
3231 /* Enable the xc5000 tuner */
3232 cx_set(MO_GP0_IO, 0x00001010);
3233 break;
3234
3235 case CX88_BOARD_HAUPPAUGE_HVR3000:
3236 case CX88_BOARD_HAUPPAUGE_HVR4000:
3237 /* Init GPIO */
3238 cx_write(MO_GP0_IO, core->board.input[0].gpio0);
3239 udelay(1000);
3240 cx_clear(MO_GP0_IO, 0x00000080);
3241 udelay(50);
3242 cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
3243 udelay(1000);
3244 break;
3245
3246 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
3247 case CX88_BOARD_WINFAST_DTV1800H:
3248 cx88_xc3028_winfast1800h_callback(core, XC2028_TUNER_RESET, 0);
3249 break;
3250
3251 case CX88_BOARD_WINFAST_DTV1800H_XC4000:
3252 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
3253 cx88_xc4000_winfast2000h_plus_callback(core,
3254 XC4000_TUNER_RESET, 0);
3255 break;
3256
3257 case CX88_BOARD_TWINHAN_VP1027_DVBS:
3258 cx_write(MO_GP0_IO, 0x00003230);
3259 cx_write(MO_GP0_IO, 0x00003210);
3260 msleep(1);
3261 cx_write(MO_GP0_IO, 0x00001230);
3262 break;
3263 }
3264}
3265
3266/*
3267 * Sets board-dependent xc3028 configuration
3268 */
3269void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
3270{
3271 memset(ctl, 0, sizeof(*ctl));
3272
3273 ctl->fname = XC2028_DEFAULT_FIRMWARE;
3274 ctl->max_len = 64;
3275
3276 switch (core->boardnr) {
3277 case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
3278 /* Now works with firmware version 2.7 */
3279 if (core->i2c_algo.udelay < 16)
3280 core->i2c_algo.udelay = 16;
3281 break;
3282 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
3283 case CX88_BOARD_WINFAST_DTV1800H:
3284 ctl->demod = XC3028_FE_ZARLINK456;
3285 break;
3286 case CX88_BOARD_KWORLD_ATSC_120:
3287 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
3288 ctl->demod = XC3028_FE_OREN538;
3289 break;
3290 case CX88_BOARD_GENIATECH_X8000_MT:
3291 /* FIXME: For this board, the xc3028 never recovers after being
3292 powered down (the reset GPIO probably is not set properly).
3293 We don't have access to the hardware so we cannot determine
3294 which GPIO is used for xc3028, so just disable power xc3028
3295 power management for now */
3296 ctl->disable_power_mgmt = 1;
3297 break;
3298 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
3299 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
3300 case CX88_BOARD_PROLINK_PV_8000GT:
3301 /*
3302 * Those boards uses non-MTS firmware
3303 */
3304 break;
3305 case CX88_BOARD_PINNACLE_HYBRID_PCTV:
3306 case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
3307 ctl->demod = XC3028_FE_ZARLINK456;
3308 ctl->mts = 1;
3309 break;
3310 default:
3311 ctl->demod = XC3028_FE_OREN538;
3312 ctl->mts = 1;
3313 }
3314}
3315EXPORT_SYMBOL_GPL(cx88_setup_xc3028);
3316
3317static void cx88_card_setup(struct cx88_core *core)
3318{
3319 static u8 eeprom[256];
3320 struct tuner_setup tun_setup;
3321 unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
3322
3323 memset(&tun_setup, 0, sizeof(tun_setup));
3324
3325 if (0 == core->i2c_rc) {
3326 core->i2c_client.addr = 0xa0 >> 1;
3327 tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom));
3328 }
3329
3330 switch (core->boardnr) {
3331 case CX88_BOARD_HAUPPAUGE:
3332 case CX88_BOARD_HAUPPAUGE_ROSLYN:
3333 if (0 == core->i2c_rc)
3334 hauppauge_eeprom(core, eeprom+8);
3335 break;
3336 case CX88_BOARD_GDI:
3337 if (0 == core->i2c_rc)
3338 gdi_eeprom(core, eeprom);
3339 break;
3340 case CX88_BOARD_LEADTEK_PVR2000:
3341 case CX88_BOARD_WINFAST_DV2000:
3342 case CX88_BOARD_WINFAST2000XP_EXPERT:
3343 if (0 == core->i2c_rc)
3344 leadtek_eeprom(core, eeprom);
3345 break;
3346 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
3347 case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
3348 case CX88_BOARD_HAUPPAUGE_DVB_T1:
3349 case CX88_BOARD_HAUPPAUGE_HVR1100:
3350 case CX88_BOARD_HAUPPAUGE_HVR1100LP:
3351 case CX88_BOARD_HAUPPAUGE_HVR3000:
3352 case CX88_BOARD_HAUPPAUGE_HVR1300:
3353 case CX88_BOARD_HAUPPAUGE_HVR4000:
3354 case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
3355 case CX88_BOARD_HAUPPAUGE_IRONLY:
3356 if (0 == core->i2c_rc)
3357 hauppauge_eeprom(core, eeprom);
3358 break;
3359 case CX88_BOARD_KWORLD_DVBS_100:
3360 cx_write(MO_GP0_IO, 0x000007f8);
3361 cx_write(MO_GP1_IO, 0x00000001);
3362 break;
3363 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
3364 /* GPIO0:0 is hooked to demod reset */
3365 /* GPIO0:4 is hooked to xc3028 reset */
3366 cx_write(MO_GP0_IO, 0x00111100);
3367 msleep(1);
3368 cx_write(MO_GP0_IO, 0x00111111);
3369 break;
3370 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
3371 /* GPIO0:6 is hooked to FX2 reset pin */
3372 cx_set(MO_GP0_IO, 0x00004040);
3373 cx_clear(MO_GP0_IO, 0x00000040);
3374 msleep(1000);
3375 cx_set(MO_GP0_IO, 0x00004040);
3376 /* FALLTHROUGH */
3377 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
3378 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
3379 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
3380 /* GPIO0:0 is hooked to mt352 reset pin */
3381 cx_set(MO_GP0_IO, 0x00000101);
3382 cx_clear(MO_GP0_IO, 0x00000001);
3383 msleep(1);
3384 cx_set(MO_GP0_IO, 0x00000101);
3385 if (0 == core->i2c_rc &&
3386 core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
3387 dvico_fusionhdtv_hybrid_init(core);
3388 break;
3389 case CX88_BOARD_KWORLD_DVB_T:
3390 case CX88_BOARD_DNTV_LIVE_DVB_T:
3391 cx_set(MO_GP0_IO, 0x00000707);
3392 cx_set(MO_GP2_IO, 0x00000101);
3393 cx_clear(MO_GP2_IO, 0x00000001);
3394 msleep(1);
3395 cx_clear(MO_GP0_IO, 0x00000007);
3396 cx_set(MO_GP2_IO, 0x00000101);
3397 break;
3398 case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
3399 cx_write(MO_GP0_IO, 0x00080808);
3400 break;
3401 case CX88_BOARD_ATI_HDTVWONDER:
3402 if (0 == core->i2c_rc) {
3403 /* enable tuner */
3404 int i;
3405 static const u8 buffer [][2] = {
3406 {0x10,0x12},
3407 {0x13,0x04},
3408 {0x16,0x00},
3409 {0x14,0x04},
3410 {0x17,0x00}
3411 };
3412 core->i2c_client.addr = 0x0a;
3413
3414 for (i = 0; i < ARRAY_SIZE(buffer); i++)
3415 if (2 != i2c_master_send(&core->i2c_client,
3416 buffer[i],2))
3417 warn_printk(core, "Unable to enable "
3418 "tuner(%i).\n", i);
3419 }
3420 break;
3421 case CX88_BOARD_MSI_TVANYWHERE_MASTER:
3422 {
3423 struct v4l2_priv_tun_config tea5767_cfg;
3424 struct tea5767_ctrl ctl;
3425
3426 memset(&ctl, 0, sizeof(ctl));
3427
3428 ctl.high_cut = 1;
3429 ctl.st_noise = 1;
3430 ctl.deemph_75 = 1;
3431 ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
3432
3433 tea5767_cfg.tuner = TUNER_TEA5767;
3434 tea5767_cfg.priv = &ctl;
3435
3436 call_all(core, tuner, s_config, &tea5767_cfg);
3437 break;
3438 }
3439 case CX88_BOARD_TEVII_S420:
3440 case CX88_BOARD_TEVII_S460:
3441 case CX88_BOARD_TEVII_S464:
3442 case CX88_BOARD_OMICOM_SS4_PCI:
3443 case CX88_BOARD_TBS_8910:
3444 case CX88_BOARD_TBS_8920:
3445 case CX88_BOARD_PROF_6200:
3446 case CX88_BOARD_PROF_7300:
3447 case CX88_BOARD_PROF_7301:
3448 case CX88_BOARD_SATTRADE_ST4200:
3449 cx_write(MO_GP0_IO, 0x8000);
3450 msleep(100);
3451 cx_write(MO_SRST_IO, 0);
3452 msleep(10);
3453 cx_write(MO_GP0_IO, 0x8080);
3454 msleep(100);
3455 cx_write(MO_SRST_IO, 1);
3456 msleep(100);
3457 break;
3458 } /*end switch() */
3459
3460
3461 /* Setup tuners */
3462 if ((core->board.radio_type != UNSET)) {
3463 tun_setup.mode_mask = T_RADIO;
3464 tun_setup.type = core->board.radio_type;
3465 tun_setup.addr = core->board.radio_addr;
3466 tun_setup.tuner_callback = cx88_tuner_callback;
3467 call_all(core, tuner, s_type_addr, &tun_setup);
3468 mode_mask &= ~T_RADIO;
3469 }
3470
3471 if (core->board.tuner_type != TUNER_ABSENT) {
3472 tun_setup.mode_mask = mode_mask;
3473 tun_setup.type = core->board.tuner_type;
3474 tun_setup.addr = core->board.tuner_addr;
3475 tun_setup.tuner_callback = cx88_tuner_callback;
3476
3477 call_all(core, tuner, s_type_addr, &tun_setup);
3478 }
3479
3480 if (core->board.tda9887_conf) {
3481 struct v4l2_priv_tun_config tda9887_cfg;
3482
3483 tda9887_cfg.tuner = TUNER_TDA9887;
3484 tda9887_cfg.priv = &core->board.tda9887_conf;
3485
3486 call_all(core, tuner, s_config, &tda9887_cfg);
3487 }
3488
3489 if (core->board.tuner_type == TUNER_XC2028) {
3490 struct v4l2_priv_tun_config xc2028_cfg;
3491 struct xc2028_ctrl ctl;
3492
3493 /* Fills device-dependent initialization parameters */
3494 cx88_setup_xc3028(core, &ctl);
3495
3496 /* Sends parameters to xc2028/3028 tuner */
3497 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
3498 xc2028_cfg.tuner = TUNER_XC2028;
3499 xc2028_cfg.priv = &ctl;
3500 info_printk(core, "Asking xc2028/3028 to load firmware %s\n",
3501 ctl.fname);
3502 call_all(core, tuner, s_config, &xc2028_cfg);
3503 }
3504 call_all(core, core, s_power, 0);
3505}
3506
3507/* ------------------------------------------------------------------ */
3508
3509static int cx88_pci_quirks(const char *name, struct pci_dev *pci)
3510{
3511 unsigned int lat = UNSET;
3512 u8 ctrl = 0;
3513 u8 value;
3514
3515 /* check pci quirks */
3516 if (pci_pci_problems & PCIPCI_TRITON) {
3517 printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
3518 name);
3519 ctrl |= CX88X_EN_TBFX;
3520 }
3521 if (pci_pci_problems & PCIPCI_NATOMA) {
3522 printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
3523 name);
3524 ctrl |= CX88X_EN_TBFX;
3525 }
3526 if (pci_pci_problems & PCIPCI_VIAETBF) {
3527 printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
3528 name);
3529 ctrl |= CX88X_EN_TBFX;
3530 }
3531 if (pci_pci_problems & PCIPCI_VSFX) {
3532 printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
3533 name);
3534 ctrl |= CX88X_EN_VSFX;
3535 }
3536#ifdef PCIPCI_ALIMAGIK
3537 if (pci_pci_problems & PCIPCI_ALIMAGIK) {
3538 printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
3539 name);
3540 lat = 0x0A;
3541 }
3542#endif
3543
3544 /* check insmod options */
3545 if (UNSET != latency)
3546 lat = latency;
3547
3548 /* apply stuff */
3549 if (ctrl) {
3550 pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
3551 value |= ctrl;
3552 pci_write_config_byte(pci, CX88X_DEVCTRL, value);
3553 }
3554 if (UNSET != lat) {
3555 printk(KERN_INFO "%s: setting pci latency timer to %d\n",
3556 name, latency);
3557 pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
3558 }
3559 return 0;
3560}
3561
3562int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci)
3563{
3564 if (request_mem_region(pci_resource_start(pci,0),
3565 pci_resource_len(pci,0),
3566 core->name))
3567 return 0;
3568 printk(KERN_ERR
3569 "%s/%d: Can't get MMIO memory @ 0x%llx, subsystem: %04x:%04x\n",
3570 core->name, PCI_FUNC(pci->devfn),
3571 (unsigned long long)pci_resource_start(pci, 0),
3572 pci->subsystem_vendor, pci->subsystem_device);
3573 return -EBUSY;
3574}
3575
3576/* Allocate and initialize the cx88 core struct. One should hold the
3577 * devlist mutex before calling this. */
3578struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
3579{
3580 struct cx88_core *core;
3581 int i;
3582
3583 core = kzalloc(sizeof(*core), GFP_KERNEL);
3584 if (core == NULL)
3585 return NULL;
3586
3587 atomic_inc(&core->refcount);
3588 core->pci_bus = pci->bus->number;
3589 core->pci_slot = PCI_SLOT(pci->devfn);
3590 core->pci_irqmask = PCI_INT_RISC_RD_BERRINT | PCI_INT_RISC_WR_BERRINT |
3591 PCI_INT_BRDG_BERRINT | PCI_INT_SRC_DMA_BERRINT |
3592 PCI_INT_DST_DMA_BERRINT | PCI_INT_IPB_DMA_BERRINT;
3593 mutex_init(&core->lock);
3594
3595 core->nr = nr;
3596 sprintf(core->name, "cx88[%d]", core->nr);
3597
3598 strcpy(core->v4l2_dev.name, core->name);
3599 if (v4l2_device_register(NULL, &core->v4l2_dev)) {
3600 kfree(core);
3601 return NULL;
3602 }
3603
3604 if (0 != cx88_get_resources(core, pci)) {
3605 v4l2_device_unregister(&core->v4l2_dev);
3606 kfree(core);
3607 return NULL;
3608 }
3609
3610 /* PCI stuff */
3611 cx88_pci_quirks(core->name, pci);
3612 core->lmmio = ioremap(pci_resource_start(pci, 0),
3613 pci_resource_len(pci, 0));
3614 core->bmmio = (u8 __iomem *)core->lmmio;
3615
3616 if (core->lmmio == NULL) {
3617 kfree(core);
3618 return NULL;
3619 }
3620
3621 /* board config */
3622 core->boardnr = UNSET;
3623 if (card[core->nr] < ARRAY_SIZE(cx88_boards))
3624 core->boardnr = card[core->nr];
3625 for (i = 0; UNSET == core->boardnr && i < ARRAY_SIZE(cx88_subids); i++)
3626 if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
3627 pci->subsystem_device == cx88_subids[i].subdevice)
3628 core->boardnr = cx88_subids[i].card;
3629 if (UNSET == core->boardnr) {
3630 core->boardnr = CX88_BOARD_UNKNOWN;
3631 cx88_card_list(core, pci);
3632 }
3633
3634 memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
3635
3636 if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB))
3637 core->board.num_frontends = 1;
3638
3639 info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
3640 pci->subsystem_vendor, pci->subsystem_device, core->board.name,
3641 core->boardnr, card[core->nr] == core->boardnr ?
3642 "insmod option" : "autodetected",
3643 core->board.num_frontends);
3644
3645 if (tuner[core->nr] != UNSET)
3646 core->board.tuner_type = tuner[core->nr];
3647 if (radio[core->nr] != UNSET)
3648 core->board.radio_type = radio[core->nr];
3649
3650 info_printk(core, "TV tuner type %d, Radio tuner type %d\n",
3651 core->board.tuner_type, core->board.radio_type);
3652
3653 /* init hardware */
3654 cx88_reset(core);
3655 cx88_card_setup_pre_i2c(core);
3656 cx88_i2c_init(core, pci);
3657
3658 /* load tuner module, if needed */
3659 if (TUNER_ABSENT != core->board.tuner_type) {
3660 /* Ignore 0x6b and 0x6f on cx88 boards.
3661 * FusionHDTV5 RT Gold has an ir receiver at 0x6b
3662 * and an RTC at 0x6f which can get corrupted if probed. */
3663 static const unsigned short tv_addrs[] = {
3664 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
3665 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
3666 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e,
3667 I2C_CLIENT_END
3668 };
3669 int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT);
3670
3671 /* I don't trust the radio_type as is stored in the card
3672 definitions, so we just probe for it.
3673 The radio_type is sometimes missing, or set to UNSET but
3674 later code configures a tea5767.
3675 */
3676 v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
3677 "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
3678 if (has_demod)
3679 v4l2_i2c_new_subdev(&core->v4l2_dev,
3680 &core->i2c_adap, "tuner",
3681 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
3682 if (core->board.tuner_addr == ADDR_UNSET) {
3683 v4l2_i2c_new_subdev(&core->v4l2_dev,
3684 &core->i2c_adap, "tuner",
3685 0, has_demod ? tv_addrs + 4 : tv_addrs);
3686 } else {
3687 v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
3688 "tuner", core->board.tuner_addr, NULL);
3689 }
3690 }
3691
3692 cx88_card_setup(core);
3693 if (!disable_ir) {
3694 cx88_i2c_init_ir(core);
3695 cx88_ir_init(core, pci);
3696 }
3697
3698 return core;
3699}
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
new file mode 100644
index 00000000000..fbcaa1c5b09
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -0,0 +1,1129 @@
1/*
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 * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
9 * - Multituner support
10 * - video_ioctl2 conversion
11 * - PAL/M fixes
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28#include <linux/init.h>
29#include <linux/list.h>
30#include <linux/module.h>
31#include <linux/kernel.h>
32#include <linux/slab.h>
33#include <linux/kmod.h>
34#include <linux/sound.h>
35#include <linux/interrupt.h>
36#include <linux/pci.h>
37#include <linux/delay.h>
38#include <linux/videodev2.h>
39#include <linux/mutex.h>
40
41#include "cx88.h"
42#include <media/v4l2-common.h>
43#include <media/v4l2-ioctl.h>
44
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
51static unsigned int core_debug;
52module_param(core_debug,int,0644);
53MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
54
55static unsigned int nicam;
56module_param(nicam,int,0644);
57MODULE_PARM_DESC(nicam,"tv audio is nicam");
58
59static unsigned int nocomb;
60module_param(nocomb,int,0644);
61MODULE_PARM_DESC(nocomb,"disable comb filter");
62
63#define dprintk(level,fmt, arg...) if (core_debug >= level) \
64 printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
65
66static unsigned int cx88_devcount;
67static LIST_HEAD(cx88_devlist);
68static DEFINE_MUTEX(devlist);
69
70#define NO_SYNC_LINE (-1U)
71
72/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
73 generated _after_ lpi lines are transferred. */
74static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
75 unsigned int offset, u32 sync_line,
76 unsigned int bpl, unsigned int padding,
77 unsigned int lines, unsigned int lpi)
78{
79 struct scatterlist *sg;
80 unsigned int line,todo,sol;
81
82 /* sync instruction */
83 if (sync_line != NO_SYNC_LINE)
84 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
85
86 /* scan lines */
87 sg = sglist;
88 for (line = 0; line < lines; line++) {
89 while (offset && offset >= sg_dma_len(sg)) {
90 offset -= sg_dma_len(sg);
91 sg++;
92 }
93 if (lpi && line>0 && !(line % lpi))
94 sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
95 else
96 sol = RISC_SOL;
97 if (bpl <= sg_dma_len(sg)-offset) {
98 /* fits into current chunk */
99 *(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
100 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
101 offset+=bpl;
102 } else {
103 /* scanline needs to be split */
104 todo = bpl;
105 *(rp++)=cpu_to_le32(RISC_WRITE|sol|
106 (sg_dma_len(sg)-offset));
107 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
108 todo -= (sg_dma_len(sg)-offset);
109 offset = 0;
110 sg++;
111 while (todo > sg_dma_len(sg)) {
112 *(rp++)=cpu_to_le32(RISC_WRITE|
113 sg_dma_len(sg));
114 *(rp++)=cpu_to_le32(sg_dma_address(sg));
115 todo -= sg_dma_len(sg);
116 sg++;
117 }
118 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
119 *(rp++)=cpu_to_le32(sg_dma_address(sg));
120 offset += todo;
121 }
122 offset += padding;
123 }
124
125 return rp;
126}
127
128int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
129 struct scatterlist *sglist,
130 unsigned int top_offset, unsigned int bottom_offset,
131 unsigned int bpl, unsigned int padding, unsigned int lines)
132{
133 u32 instructions,fields;
134 __le32 *rp;
135 int rc;
136
137 fields = 0;
138 if (UNSET != top_offset)
139 fields++;
140 if (UNSET != bottom_offset)
141 fields++;
142
143 /* estimate risc mem: worst case is one write per page border +
144 one write per scan line + syncs + jump (all 2 dwords). Padding
145 can cause next bpl to start close to a page border. First DMA
146 region may be smaller than PAGE_SIZE */
147 instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
148 instructions += 2;
149 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
150 return rc;
151
152 /* write risc instructions */
153 rp = risc->cpu;
154 if (UNSET != top_offset)
155 rp = cx88_risc_field(rp, sglist, top_offset, 0,
156 bpl, padding, lines, 0);
157 if (UNSET != bottom_offset)
158 rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
159 bpl, padding, lines, 0);
160
161 /* save pointer to jmp instruction address */
162 risc->jmp = rp;
163 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
164 return 0;
165}
166
167int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
168 struct scatterlist *sglist, unsigned int bpl,
169 unsigned int lines, unsigned int lpi)
170{
171 u32 instructions;
172 __le32 *rp;
173 int rc;
174
175 /* estimate risc mem: worst case is one write per page border +
176 one write per scan line + syncs + jump (all 2 dwords). Here
177 there is no padding and no sync. First DMA region may be smaller
178 than PAGE_SIZE */
179 instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
180 instructions += 1;
181 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
182 return rc;
183
184 /* write risc instructions */
185 rp = risc->cpu;
186 rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
187
188 /* save pointer to jmp instruction address */
189 risc->jmp = rp;
190 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
191 return 0;
192}
193
194int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
195 u32 reg, u32 mask, u32 value)
196{
197 __le32 *rp;
198 int rc;
199
200 if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
201 return rc;
202
203 /* write risc instructions */
204 rp = risc->cpu;
205 *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
206 *(rp++) = cpu_to_le32(reg);
207 *(rp++) = cpu_to_le32(value);
208 *(rp++) = cpu_to_le32(mask);
209 *(rp++) = cpu_to_le32(RISC_JUMP);
210 *(rp++) = cpu_to_le32(risc->dma);
211 return 0;
212}
213
214void
215cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
216{
217 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
218
219 BUG_ON(in_interrupt());
220 videobuf_waiton(q, &buf->vb, 0, 0);
221 videobuf_dma_unmap(q->dev, dma);
222 videobuf_dma_free(dma);
223 btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
224 buf->vb.state = VIDEOBUF_NEEDS_INIT;
225}
226
227/* ------------------------------------------------------------------ */
228/* our SRAM memory layout */
229
230/* we are going to put all thr risc programs into host memory, so we
231 * can use the whole SDRAM for the DMA fifos. To simplify things, we
232 * use a static memory layout. That surely will waste memory in case
233 * we don't use all DMA channels at the same time (which will be the
234 * case most of the time). But that still gives us enough FIFO space
235 * to be able to deal with insane long pci latencies ...
236 *
237 * FIFO space allocations:
238 * channel 21 (y video) - 10.0k
239 * channel 22 (u video) - 2.0k
240 * channel 23 (v video) - 2.0k
241 * channel 24 (vbi) - 4.0k
242 * channels 25+26 (audio) - 4.0k
243 * channel 28 (mpeg) - 4.0k
244 * channel 27 (audio rds)- 3.0k
245 * TOTAL = 29.0k
246 *
247 * Every channel has 160 bytes control data (64 bytes instruction
248 * queue and 6 CDT entries), which is close to 2k total.
249 *
250 * Address layout:
251 * 0x0000 - 0x03ff CMDs / reserved
252 * 0x0400 - 0x0bff instruction queues + CDs
253 * 0x0c00 - FIFOs
254 */
255
256const struct sram_channel const cx88_sram_channels[] = {
257 [SRAM_CH21] = {
258 .name = "video y / packed",
259 .cmds_start = 0x180040,
260 .ctrl_start = 0x180400,
261 .cdt = 0x180400 + 64,
262 .fifo_start = 0x180c00,
263 .fifo_size = 0x002800,
264 .ptr1_reg = MO_DMA21_PTR1,
265 .ptr2_reg = MO_DMA21_PTR2,
266 .cnt1_reg = MO_DMA21_CNT1,
267 .cnt2_reg = MO_DMA21_CNT2,
268 },
269 [SRAM_CH22] = {
270 .name = "video u",
271 .cmds_start = 0x180080,
272 .ctrl_start = 0x1804a0,
273 .cdt = 0x1804a0 + 64,
274 .fifo_start = 0x183400,
275 .fifo_size = 0x000800,
276 .ptr1_reg = MO_DMA22_PTR1,
277 .ptr2_reg = MO_DMA22_PTR2,
278 .cnt1_reg = MO_DMA22_CNT1,
279 .cnt2_reg = MO_DMA22_CNT2,
280 },
281 [SRAM_CH23] = {
282 .name = "video v",
283 .cmds_start = 0x1800c0,
284 .ctrl_start = 0x180540,
285 .cdt = 0x180540 + 64,
286 .fifo_start = 0x183c00,
287 .fifo_size = 0x000800,
288 .ptr1_reg = MO_DMA23_PTR1,
289 .ptr2_reg = MO_DMA23_PTR2,
290 .cnt1_reg = MO_DMA23_CNT1,
291 .cnt2_reg = MO_DMA23_CNT2,
292 },
293 [SRAM_CH24] = {
294 .name = "vbi",
295 .cmds_start = 0x180100,
296 .ctrl_start = 0x1805e0,
297 .cdt = 0x1805e0 + 64,
298 .fifo_start = 0x184400,
299 .fifo_size = 0x001000,
300 .ptr1_reg = MO_DMA24_PTR1,
301 .ptr2_reg = MO_DMA24_PTR2,
302 .cnt1_reg = MO_DMA24_CNT1,
303 .cnt2_reg = MO_DMA24_CNT2,
304 },
305 [SRAM_CH25] = {
306 .name = "audio from",
307 .cmds_start = 0x180140,
308 .ctrl_start = 0x180680,
309 .cdt = 0x180680 + 64,
310 .fifo_start = 0x185400,
311 .fifo_size = 0x001000,
312 .ptr1_reg = MO_DMA25_PTR1,
313 .ptr2_reg = MO_DMA25_PTR2,
314 .cnt1_reg = MO_DMA25_CNT1,
315 .cnt2_reg = MO_DMA25_CNT2,
316 },
317 [SRAM_CH26] = {
318 .name = "audio to",
319 .cmds_start = 0x180180,
320 .ctrl_start = 0x180720,
321 .cdt = 0x180680 + 64, /* same as audio IN */
322 .fifo_start = 0x185400, /* same as audio IN */
323 .fifo_size = 0x001000, /* same as audio IN */
324 .ptr1_reg = MO_DMA26_PTR1,
325 .ptr2_reg = MO_DMA26_PTR2,
326 .cnt1_reg = MO_DMA26_CNT1,
327 .cnt2_reg = MO_DMA26_CNT2,
328 },
329 [SRAM_CH28] = {
330 .name = "mpeg",
331 .cmds_start = 0x180200,
332 .ctrl_start = 0x1807C0,
333 .cdt = 0x1807C0 + 64,
334 .fifo_start = 0x186400,
335 .fifo_size = 0x001000,
336 .ptr1_reg = MO_DMA28_PTR1,
337 .ptr2_reg = MO_DMA28_PTR2,
338 .cnt1_reg = MO_DMA28_CNT1,
339 .cnt2_reg = MO_DMA28_CNT2,
340 },
341 [SRAM_CH27] = {
342 .name = "audio rds",
343 .cmds_start = 0x1801C0,
344 .ctrl_start = 0x180860,
345 .cdt = 0x180860 + 64,
346 .fifo_start = 0x187400,
347 .fifo_size = 0x000C00,
348 .ptr1_reg = MO_DMA27_PTR1,
349 .ptr2_reg = MO_DMA27_PTR2,
350 .cnt1_reg = MO_DMA27_CNT1,
351 .cnt2_reg = MO_DMA27_CNT2,
352 },
353};
354
355int cx88_sram_channel_setup(struct cx88_core *core,
356 const struct sram_channel *ch,
357 unsigned int bpl, u32 risc)
358{
359 unsigned int i,lines;
360 u32 cdt;
361
362 bpl = (bpl + 7) & ~7; /* alignment */
363 cdt = ch->cdt;
364 lines = ch->fifo_size / bpl;
365 if (lines > 6)
366 lines = 6;
367 BUG_ON(lines < 2);
368
369 /* write CDT */
370 for (i = 0; i < lines; i++)
371 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
372
373 /* write CMDS */
374 cx_write(ch->cmds_start + 0, risc);
375 cx_write(ch->cmds_start + 4, cdt);
376 cx_write(ch->cmds_start + 8, (lines*16) >> 3);
377 cx_write(ch->cmds_start + 12, ch->ctrl_start);
378 cx_write(ch->cmds_start + 16, 64 >> 2);
379 for (i = 20; i < 64; i += 4)
380 cx_write(ch->cmds_start + i, 0);
381
382 /* fill registers */
383 cx_write(ch->ptr1_reg, ch->fifo_start);
384 cx_write(ch->ptr2_reg, cdt);
385 cx_write(ch->cnt1_reg, (bpl >> 3) -1);
386 cx_write(ch->cnt2_reg, (lines*16) >> 3);
387
388 dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
389 return 0;
390}
391
392/* ------------------------------------------------------------------ */
393/* debug helper code */
394
395static int cx88_risc_decode(u32 risc)
396{
397 static const char * const instr[16] = {
398 [ RISC_SYNC >> 28 ] = "sync",
399 [ RISC_WRITE >> 28 ] = "write",
400 [ RISC_WRITEC >> 28 ] = "writec",
401 [ RISC_READ >> 28 ] = "read",
402 [ RISC_READC >> 28 ] = "readc",
403 [ RISC_JUMP >> 28 ] = "jump",
404 [ RISC_SKIP >> 28 ] = "skip",
405 [ RISC_WRITERM >> 28 ] = "writerm",
406 [ RISC_WRITECM >> 28 ] = "writecm",
407 [ RISC_WRITECR >> 28 ] = "writecr",
408 };
409 static int const incr[16] = {
410 [ RISC_WRITE >> 28 ] = 2,
411 [ RISC_JUMP >> 28 ] = 2,
412 [ RISC_WRITERM >> 28 ] = 3,
413 [ RISC_WRITECM >> 28 ] = 3,
414 [ RISC_WRITECR >> 28 ] = 4,
415 };
416 static const char * const bits[] = {
417 "12", "13", "14", "resync",
418 "cnt0", "cnt1", "18", "19",
419 "20", "21", "22", "23",
420 "irq1", "irq2", "eol", "sol",
421 };
422 int i;
423
424 printk("0x%08x [ %s", risc,
425 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
426 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
427 if (risc & (1 << (i + 12)))
428 printk(" %s",bits[i]);
429 printk(" count=%d ]\n", risc & 0xfff);
430 return incr[risc >> 28] ? incr[risc >> 28] : 1;
431}
432
433
434void cx88_sram_channel_dump(struct cx88_core *core,
435 const struct sram_channel *ch)
436{
437 static const char * const name[] = {
438 "initial risc",
439 "cdt base",
440 "cdt size",
441 "iq base",
442 "iq size",
443 "risc pc",
444 "iq wr ptr",
445 "iq rd ptr",
446 "cdt current",
447 "pci target",
448 "line / byte",
449 };
450 u32 risc;
451 unsigned int i,j,n;
452
453 printk("%s: %s - dma channel status dump\n",
454 core->name,ch->name);
455 for (i = 0; i < ARRAY_SIZE(name); i++)
456 printk("%s: cmds: %-12s: 0x%08x\n",
457 core->name,name[i],
458 cx_read(ch->cmds_start + 4*i));
459 for (n = 1, i = 0; i < 4; i++) {
460 risc = cx_read(ch->cmds_start + 4 * (i+11));
461 printk("%s: risc%d: ", core->name, i);
462 if (--n)
463 printk("0x%08x [ arg #%d ]\n", risc, n);
464 else
465 n = cx88_risc_decode(risc);
466 }
467 for (i = 0; i < 16; i += n) {
468 risc = cx_read(ch->ctrl_start + 4 * i);
469 printk("%s: iq %x: ", core->name, i);
470 n = cx88_risc_decode(risc);
471 for (j = 1; j < n; j++) {
472 risc = cx_read(ch->ctrl_start + 4 * (i+j));
473 printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
474 core->name, i+j, risc, j);
475 }
476 }
477
478 printk("%s: fifo: 0x%08x -> 0x%x\n",
479 core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
480 printk("%s: ctrl: 0x%08x -> 0x%x\n",
481 core->name, ch->ctrl_start, ch->ctrl_start+6*16);
482 printk("%s: ptr1_reg: 0x%08x\n",
483 core->name,cx_read(ch->ptr1_reg));
484 printk("%s: ptr2_reg: 0x%08x\n",
485 core->name,cx_read(ch->ptr2_reg));
486 printk("%s: cnt1_reg: 0x%08x\n",
487 core->name,cx_read(ch->cnt1_reg));
488 printk("%s: cnt2_reg: 0x%08x\n",
489 core->name,cx_read(ch->cnt2_reg));
490}
491
492static const char *cx88_pci_irqs[32] = {
493 "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
494 "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
495 "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
496 "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
497};
498
499void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
500 int len, u32 bits, u32 mask)
501{
502 unsigned int i;
503
504 printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
505 for (i = 0; i < len; i++) {
506 if (!(bits & (1 << i)))
507 continue;
508 if (strings[i])
509 printk(" %s", strings[i]);
510 else
511 printk(" %d", i);
512 if (!(mask & (1 << i)))
513 continue;
514 printk("*");
515 }
516 printk("\n");
517}
518
519/* ------------------------------------------------------------------ */
520
521int cx88_core_irq(struct cx88_core *core, u32 status)
522{
523 int handled = 0;
524
525 if (status & PCI_INT_IR_SMPINT) {
526 cx88_ir_irq(core);
527 handled++;
528 }
529 if (!handled)
530 cx88_print_irqbits(core->name, "irq pci",
531 cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
532 status, core->pci_irqmask);
533 return handled;
534}
535
536void cx88_wakeup(struct cx88_core *core,
537 struct cx88_dmaqueue *q, u32 count)
538{
539 struct cx88_buffer *buf;
540 int bc;
541
542 for (bc = 0;; bc++) {
543 if (list_empty(&q->active))
544 break;
545 buf = list_entry(q->active.next,
546 struct cx88_buffer, vb.queue);
547 /* count comes from the hw and is is 16bit wide --
548 * this trick handles wrap-arounds correctly for
549 * up to 32767 buffers in flight... */
550 if ((s16) (count - buf->count) < 0)
551 break;
552 do_gettimeofday(&buf->vb.ts);
553 dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
554 count, buf->count);
555 buf->vb.state = VIDEOBUF_DONE;
556 list_del(&buf->vb.queue);
557 wake_up(&buf->vb.done);
558 }
559 if (list_empty(&q->active)) {
560 del_timer(&q->timeout);
561 } else {
562 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
563 }
564 if (bc != 1)
565 dprintk(2, "%s: %d buffers handled (should be 1)\n",
566 __func__, bc);
567}
568
569void cx88_shutdown(struct cx88_core *core)
570{
571 /* disable RISC controller + IRQs */
572 cx_write(MO_DEV_CNTRL2, 0);
573
574 /* stop dma transfers */
575 cx_write(MO_VID_DMACNTRL, 0x0);
576 cx_write(MO_AUD_DMACNTRL, 0x0);
577 cx_write(MO_TS_DMACNTRL, 0x0);
578 cx_write(MO_VIP_DMACNTRL, 0x0);
579 cx_write(MO_GPHST_DMACNTRL, 0x0);
580
581 /* stop interrupts */
582 cx_write(MO_PCI_INTMSK, 0x0);
583 cx_write(MO_VID_INTMSK, 0x0);
584 cx_write(MO_AUD_INTMSK, 0x0);
585 cx_write(MO_TS_INTMSK, 0x0);
586 cx_write(MO_VIP_INTMSK, 0x0);
587 cx_write(MO_GPHST_INTMSK, 0x0);
588
589 /* stop capturing */
590 cx_write(VID_CAPTURE_CONTROL, 0);
591}
592
593int cx88_reset(struct cx88_core *core)
594{
595 dprintk(1,"%s\n",__func__);
596 cx88_shutdown(core);
597
598 /* clear irq status */
599 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
600 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
601 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
602
603 /* wait a bit */
604 msleep(100);
605
606 /* init sram */
607 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
608 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
609 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
610 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
611 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
612 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
613 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
614 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
615
616 /* misc init ... */
617 cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
618 (1 << 12) | // agc gain
619 (1 << 11) | // adaptibe agc
620 (0 << 10) | // chroma agc
621 (0 << 9) | // ckillen
622 (7)));
623
624 /* setup image format */
625 cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
626
627 /* setup FIFO Thresholds */
628 cx_write(MO_PDMA_STHRSH, 0x0807);
629 cx_write(MO_PDMA_DTHRSH, 0x0807);
630
631 /* fixes flashing of image */
632 cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
633 cx_write(MO_AGC_BACK_VBI, 0x00E00555);
634
635 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
636 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
637 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
638
639 /* set default notch filter */
640 cx_andor(MO_HTOTAL, 0x1800, (HLNotchFilter4xFsc << 11));
641
642 /* Reset on-board parts */
643 cx_write(MO_SRST_IO, 0);
644 msleep(10);
645 cx_write(MO_SRST_IO, 1);
646
647 return 0;
648}
649
650/* ------------------------------------------------------------------ */
651
652static unsigned int inline norm_swidth(v4l2_std_id norm)
653{
654 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
655}
656
657static unsigned int inline norm_hdelay(v4l2_std_id norm)
658{
659 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
660}
661
662static unsigned int inline norm_vdelay(v4l2_std_id norm)
663{
664 return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
665}
666
667static unsigned int inline norm_fsc8(v4l2_std_id norm)
668{
669 if (norm & V4L2_STD_PAL_M)
670 return 28604892; // 3.575611 MHz
671
672 if (norm & (V4L2_STD_PAL_Nc))
673 return 28656448; // 3.582056 MHz
674
675 if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
676 return 28636360; // 3.57954545 MHz +/- 10 Hz
677
678 /* SECAM have also different sub carrier for chroma,
679 but step_db and step_dr, at cx88_set_tvnorm already handles that.
680
681 The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
682 */
683
684 return 35468950; // 4.43361875 MHz +/- 5 Hz
685}
686
687static unsigned int inline norm_htotal(v4l2_std_id norm)
688{
689
690 unsigned int fsc4=norm_fsc8(norm)/2;
691
692 /* returns 4*FSC / vtotal / frames per seconds */
693 return (norm & V4L2_STD_625_50) ?
694 ((fsc4+312)/625+12)/25 :
695 ((fsc4+262)/525*1001+15000)/30000;
696}
697
698static unsigned int inline norm_vbipack(v4l2_std_id norm)
699{
700 return (norm & V4L2_STD_625_50) ? 511 : 400;
701}
702
703int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
704 enum v4l2_field field)
705{
706 unsigned int swidth = norm_swidth(core->tvnorm);
707 unsigned int sheight = norm_maxh(core->tvnorm);
708 u32 value;
709
710 dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
711 V4L2_FIELD_HAS_TOP(field) ? "T" : "",
712 V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
713 v4l2_norm_to_name(core->tvnorm));
714 if (!V4L2_FIELD_HAS_BOTH(field))
715 height *= 2;
716
717 // recalc H delay and scale registers
718 value = (width * norm_hdelay(core->tvnorm)) / swidth;
719 value &= 0x3fe;
720 cx_write(MO_HDELAY_EVEN, value);
721 cx_write(MO_HDELAY_ODD, value);
722 dprintk(1,"set_scale: hdelay 0x%04x (width %d)\n", value,swidth);
723
724 value = (swidth * 4096 / width) - 4096;
725 cx_write(MO_HSCALE_EVEN, value);
726 cx_write(MO_HSCALE_ODD, value);
727 dprintk(1,"set_scale: hscale 0x%04x\n", value);
728
729 cx_write(MO_HACTIVE_EVEN, width);
730 cx_write(MO_HACTIVE_ODD, width);
731 dprintk(1,"set_scale: hactive 0x%04x\n", width);
732
733 // recalc V scale Register (delay is constant)
734 cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
735 cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
736 dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
737
738 value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
739 cx_write(MO_VSCALE_EVEN, value);
740 cx_write(MO_VSCALE_ODD, value);
741 dprintk(1,"set_scale: vscale 0x%04x\n", value);
742
743 cx_write(MO_VACTIVE_EVEN, sheight);
744 cx_write(MO_VACTIVE_ODD, sheight);
745 dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
746
747 // setup filters
748 value = 0;
749 value |= (1 << 19); // CFILT (default)
750 if (core->tvnorm & V4L2_STD_SECAM) {
751 value |= (1 << 15);
752 value |= (1 << 16);
753 }
754 if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
755 value |= (1 << 13) | (1 << 5);
756 if (V4L2_FIELD_INTERLACED == field)
757 value |= (1 << 3); // VINT (interlaced vertical scaling)
758 if (width < 385)
759 value |= (1 << 0); // 3-tap interpolation
760 if (width < 193)
761 value |= (1 << 1); // 5-tap interpolation
762 if (nocomb)
763 value |= (3 << 5); // disable comb filter
764
765 cx_andor(MO_FILTER_EVEN, 0x7ffc7f, value); /* preserve PEAKEN, PSEL */
766 cx_andor(MO_FILTER_ODD, 0x7ffc7f, value);
767 dprintk(1,"set_scale: filter 0x%04x\n", value);
768
769 return 0;
770}
771
772static const u32 xtal = 28636363;
773
774static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
775{
776 static const u32 pre[] = { 0, 0, 0, 3, 2, 1 };
777 u64 pll;
778 u32 reg;
779 int i;
780
781 if (prescale < 2)
782 prescale = 2;
783 if (prescale > 5)
784 prescale = 5;
785
786 pll = ofreq * 8 * prescale * (u64)(1 << 20);
787 do_div(pll,xtal);
788 reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
789 if (((reg >> 20) & 0x3f) < 14) {
790 printk("%s/0: pll out of range\n",core->name);
791 return -1;
792 }
793
794 dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
795 reg, cx_read(MO_PLL_REG), ofreq);
796 cx_write(MO_PLL_REG, reg);
797 for (i = 0; i < 100; i++) {
798 reg = cx_read(MO_DEVICE_STATUS);
799 if (reg & (1<<2)) {
800 dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
801 prescale,ofreq);
802 return 0;
803 }
804 dprintk(1,"pll not locked yet, waiting ...\n");
805 msleep(10);
806 }
807 dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
808 return -1;
809}
810
811int cx88_start_audio_dma(struct cx88_core *core)
812{
813 /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
814 int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
815
816 int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
817
818 /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
819 if (cx_read(MO_AUD_DMACNTRL) & 0x10)
820 return 0;
821
822 /* setup fifo + format */
823 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
824 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
825 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
826 rds_bpl, 0);
827
828 cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
829 cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
830
831 /* enable Up, Down and Audio RDS fifo */
832 cx_write(MO_AUD_DMACNTRL, 0x0007);
833
834 return 0;
835}
836
837int cx88_stop_audio_dma(struct cx88_core *core)
838{
839 /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
840 if (cx_read(MO_AUD_DMACNTRL) & 0x10)
841 return 0;
842
843 /* stop dma */
844 cx_write(MO_AUD_DMACNTRL, 0x0000);
845
846 return 0;
847}
848
849static int set_tvaudio(struct cx88_core *core)
850{
851 v4l2_std_id norm = core->tvnorm;
852
853 if (CX88_VMUX_TELEVISION != INPUT(core->input).type &&
854 CX88_VMUX_CABLE != INPUT(core->input).type)
855 return 0;
856
857 if (V4L2_STD_PAL_BG & norm) {
858 core->tvaudio = WW_BG;
859
860 } else if (V4L2_STD_PAL_DK & norm) {
861 core->tvaudio = WW_DK;
862
863 } else if (V4L2_STD_PAL_I & norm) {
864 core->tvaudio = WW_I;
865
866 } else if (V4L2_STD_SECAM_L & norm) {
867 core->tvaudio = WW_L;
868
869 } else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
870 core->tvaudio = WW_BG;
871
872 } else if (V4L2_STD_SECAM_DK & norm) {
873 core->tvaudio = WW_DK;
874
875 } else if ((V4L2_STD_NTSC_M & norm) ||
876 (V4L2_STD_PAL_M & norm)) {
877 core->tvaudio = WW_BTSC;
878
879 } else if (V4L2_STD_NTSC_M_JP & norm) {
880 core->tvaudio = WW_EIAJ;
881
882 } else {
883 printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
884 core->name, v4l2_norm_to_name(core->tvnorm));
885 core->tvaudio = WW_NONE;
886 return 0;
887 }
888
889 cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
890 cx88_set_tvaudio(core);
891 /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
892
893/*
894 This should be needed only on cx88-alsa. It seems that some cx88 chips have
895 bugs and does require DMA enabled for it to work.
896 */
897 cx88_start_audio_dma(core);
898 return 0;
899}
900
901
902
903int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
904{
905 u32 fsc8;
906 u32 adc_clock;
907 u32 vdec_clock;
908 u32 step_db,step_dr;
909 u64 tmp64;
910 u32 bdelay,agcdelay,htotal;
911 u32 cxiformat, cxoformat;
912
913 core->tvnorm = norm;
914 fsc8 = norm_fsc8(norm);
915 adc_clock = xtal;
916 vdec_clock = fsc8;
917 step_db = fsc8;
918 step_dr = fsc8;
919
920 if (norm & V4L2_STD_NTSC_M_JP) {
921 cxiformat = VideoFormatNTSCJapan;
922 cxoformat = 0x181f0008;
923 } else if (norm & V4L2_STD_NTSC_443) {
924 cxiformat = VideoFormatNTSC443;
925 cxoformat = 0x181f0008;
926 } else if (norm & V4L2_STD_PAL_M) {
927 cxiformat = VideoFormatPALM;
928 cxoformat = 0x1c1f0008;
929 } else if (norm & V4L2_STD_PAL_N) {
930 cxiformat = VideoFormatPALN;
931 cxoformat = 0x1c1f0008;
932 } else if (norm & V4L2_STD_PAL_Nc) {
933 cxiformat = VideoFormatPALNC;
934 cxoformat = 0x1c1f0008;
935 } else if (norm & V4L2_STD_PAL_60) {
936 cxiformat = VideoFormatPAL60;
937 cxoformat = 0x181f0008;
938 } else if (norm & V4L2_STD_NTSC) {
939 cxiformat = VideoFormatNTSC;
940 cxoformat = 0x181f0008;
941 } else if (norm & V4L2_STD_SECAM) {
942 step_db = 4250000 * 8;
943 step_dr = 4406250 * 8;
944
945 cxiformat = VideoFormatSECAM;
946 cxoformat = 0x181f0008;
947 } else { /* PAL */
948 cxiformat = VideoFormatPAL;
949 cxoformat = 0x181f0008;
950 }
951
952 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
953 v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
954 step_db, step_dr);
955 set_pll(core,2,vdec_clock);
956
957 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
958 cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
959 /* Chroma AGC must be disabled if SECAM is used, we enable it
960 by default on PAL and NTSC */
961 cx_andor(MO_INPUT_FORMAT, 0x40f,
962 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
963
964 // FIXME: as-is from DScaler
965 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
966 cxoformat, cx_read(MO_OUTPUT_FORMAT));
967 cx_write(MO_OUTPUT_FORMAT, cxoformat);
968
969 // MO_SCONV_REG = adc clock / video dec clock * 2^17
970 tmp64 = adc_clock * (u64)(1 << 17);
971 do_div(tmp64, vdec_clock);
972 dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
973 (u32)tmp64, cx_read(MO_SCONV_REG));
974 cx_write(MO_SCONV_REG, (u32)tmp64);
975
976 // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
977 tmp64 = step_db * (u64)(1 << 22);
978 do_div(tmp64, vdec_clock);
979 dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
980 (u32)tmp64, cx_read(MO_SUB_STEP));
981 cx_write(MO_SUB_STEP, (u32)tmp64);
982
983 // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
984 tmp64 = step_dr * (u64)(1 << 22);
985 do_div(tmp64, vdec_clock);
986 dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
987 (u32)tmp64, cx_read(MO_SUB_STEP_DR));
988 cx_write(MO_SUB_STEP_DR, (u32)tmp64);
989
990 // bdelay + agcdelay
991 bdelay = vdec_clock * 65 / 20000000 + 21;
992 agcdelay = vdec_clock * 68 / 20000000 + 15;
993 dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
994 (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
995 cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
996
997 // htotal
998 tmp64 = norm_htotal(norm) * (u64)vdec_clock;
999 do_div(tmp64, fsc8);
1000 htotal = (u32)tmp64;
1001 dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
1002 htotal, cx_read(MO_HTOTAL), (u32)tmp64);
1003 cx_andor(MO_HTOTAL, 0x07ff, htotal);
1004
1005 // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
1006 // the effective vbi offset ~244 samples, the same as the Bt8x8
1007 cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
1008
1009 // this is needed as well to set all tvnorm parameter
1010 cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
1011
1012 // audio
1013 set_tvaudio(core);
1014
1015 // tell i2c chips
1016 call_all(core, core, s_std, norm);
1017
1018 // done
1019 return 0;
1020}
1021
1022/* ------------------------------------------------------------------ */
1023
1024struct video_device *cx88_vdev_init(struct cx88_core *core,
1025 struct pci_dev *pci,
1026 const struct video_device *template_,
1027 const char *type)
1028{
1029 struct video_device *vfd;
1030
1031 vfd = video_device_alloc();
1032 if (NULL == vfd)
1033 return NULL;
1034 *vfd = *template_;
1035 vfd->v4l2_dev = &core->v4l2_dev;
1036 vfd->parent = &pci->dev;
1037 vfd->release = video_device_release;
1038 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1039 core->name, type, core->board.name);
1040 return vfd;
1041}
1042
1043struct cx88_core* cx88_core_get(struct pci_dev *pci)
1044{
1045 struct cx88_core *core;
1046
1047 mutex_lock(&devlist);
1048 list_for_each_entry(core, &cx88_devlist, devlist) {
1049 if (pci->bus->number != core->pci_bus)
1050 continue;
1051 if (PCI_SLOT(pci->devfn) != core->pci_slot)
1052 continue;
1053
1054 if (0 != cx88_get_resources(core, pci)) {
1055 mutex_unlock(&devlist);
1056 return NULL;
1057 }
1058 atomic_inc(&core->refcount);
1059 mutex_unlock(&devlist);
1060 return core;
1061 }
1062
1063 core = cx88_core_create(pci, cx88_devcount);
1064 if (NULL != core) {
1065 cx88_devcount++;
1066 list_add_tail(&core->devlist, &cx88_devlist);
1067 }
1068
1069 mutex_unlock(&devlist);
1070 return core;
1071}
1072
1073void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1074{
1075 release_mem_region(pci_resource_start(pci,0),
1076 pci_resource_len(pci,0));
1077
1078 if (!atomic_dec_and_test(&core->refcount))
1079 return;
1080
1081 mutex_lock(&devlist);
1082 cx88_ir_fini(core);
1083 if (0 == core->i2c_rc) {
1084 if (core->i2c_rtc)
1085 i2c_unregister_device(core->i2c_rtc);
1086 i2c_del_adapter(&core->i2c_adap);
1087 }
1088 list_del(&core->devlist);
1089 iounmap(core->lmmio);
1090 cx88_devcount--;
1091 mutex_unlock(&devlist);
1092 v4l2_device_unregister(&core->v4l2_dev);
1093 kfree(core);
1094}
1095
1096/* ------------------------------------------------------------------ */
1097
1098EXPORT_SYMBOL(cx88_print_irqbits);
1099
1100EXPORT_SYMBOL(cx88_core_irq);
1101EXPORT_SYMBOL(cx88_wakeup);
1102EXPORT_SYMBOL(cx88_reset);
1103EXPORT_SYMBOL(cx88_shutdown);
1104
1105EXPORT_SYMBOL(cx88_risc_buffer);
1106EXPORT_SYMBOL(cx88_risc_databuffer);
1107EXPORT_SYMBOL(cx88_risc_stopper);
1108EXPORT_SYMBOL(cx88_free_buffer);
1109
1110EXPORT_SYMBOL(cx88_sram_channels);
1111EXPORT_SYMBOL(cx88_sram_channel_setup);
1112EXPORT_SYMBOL(cx88_sram_channel_dump);
1113
1114EXPORT_SYMBOL(cx88_set_tvnorm);
1115EXPORT_SYMBOL(cx88_set_scale);
1116
1117EXPORT_SYMBOL(cx88_vdev_init);
1118EXPORT_SYMBOL(cx88_core_get);
1119EXPORT_SYMBOL(cx88_core_put);
1120
1121EXPORT_SYMBOL(cx88_ir_start);
1122EXPORT_SYMBOL(cx88_ir_stop);
1123
1124/*
1125 * Local variables:
1126 * c-basic-offset: 8
1127 * End:
1128 * 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
1129 */
diff --git a/drivers/media/video/cx88/cx88-dsp.c b/drivers/media/video/cx88/cx88-dsp.c
new file mode 100644
index 00000000000..a9907265ff6
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-dsp.c
@@ -0,0 +1,322 @@
1/*
2 *
3 * Stereo and SAP detection for cx88
4 *
5 * Copyright (c) 2009 Marton Balint <cus@fazekas.hu>
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/slab.h>
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/jiffies.h>
26#include <asm/div64.h>
27
28#include "cx88.h"
29#include "cx88-reg.h"
30
31#define INT_PI ((s32)(3.141592653589 * 32768.0))
32
33#define compat_remainder(a, b) \
34 ((float)(((s32)((a)*100))%((s32)((b)*100)))/100.0)
35
36#define baseband_freq(carrier, srate, tone) ((s32)( \
37 (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI))
38
39/* We calculate the baseband frequencies of the carrier and the pilot tones
40 * based on the the sampling rate of the audio rds fifo. */
41
42#define FREQ_A2_CARRIER baseband_freq(54687.5, 2689.36, 0.0)
43#define FREQ_A2_DUAL baseband_freq(54687.5, 2689.36, 274.1)
44#define FREQ_A2_STEREO baseband_freq(54687.5, 2689.36, 117.5)
45
46/* The frequencies below are from the reference driver. They probably need
47 * further adjustments, because they are not tested at all. You may even need
48 * to play a bit with the registers of the chip to select the proper signal
49 * for the input of the audio rds fifo, and measure it's sampling rate to
50 * calculate the proper baseband frequencies... */
51
52#define FREQ_A2M_CARRIER ((s32)(2.114516 * 32768.0))
53#define FREQ_A2M_DUAL ((s32)(2.754916 * 32768.0))
54#define FREQ_A2M_STEREO ((s32)(2.462326 * 32768.0))
55
56#define FREQ_EIAJ_CARRIER ((s32)(1.963495 * 32768.0)) /* 5pi/8 */
57#define FREQ_EIAJ_DUAL ((s32)(2.562118 * 32768.0))
58#define FREQ_EIAJ_STEREO ((s32)(2.601053 * 32768.0))
59
60#define FREQ_BTSC_DUAL ((s32)(1.963495 * 32768.0)) /* 5pi/8 */
61#define FREQ_BTSC_DUAL_REF ((s32)(1.374446 * 32768.0)) /* 7pi/16 */
62
63#define FREQ_BTSC_SAP ((s32)(2.471532 * 32768.0))
64#define FREQ_BTSC_SAP_REF ((s32)(1.730072 * 32768.0))
65
66/* The spectrum of the signal should be empty between these frequencies. */
67#define FREQ_NOISE_START ((s32)(0.100000 * 32768.0))
68#define FREQ_NOISE_END ((s32)(1.200000 * 32768.0))
69
70static unsigned int dsp_debug;
71module_param(dsp_debug, int, 0644);
72MODULE_PARM_DESC(dsp_debug, "enable audio dsp debug messages");
73
74#define dprintk(level, fmt, arg...) if (dsp_debug >= level) \
75 printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
76
77static s32 int_cos(u32 x)
78{
79 u32 t2, t4, t6, t8;
80 s32 ret;
81 u16 period = x / INT_PI;
82 if (period % 2)
83 return -int_cos(x - INT_PI);
84 x = x % INT_PI;
85 if (x > INT_PI/2)
86 return -int_cos(INT_PI/2 - (x % (INT_PI/2)));
87 /* Now x is between 0 and INT_PI/2.
88 * To calculate cos(x) we use it's Taylor polinom. */
89 t2 = x*x/32768/2;
90 t4 = t2*x/32768*x/32768/3/4;
91 t6 = t4*x/32768*x/32768/5/6;
92 t8 = t6*x/32768*x/32768/7/8;
93 ret = 32768-t2+t4-t6+t8;
94 return ret;
95}
96
97static u32 int_goertzel(s16 x[], u32 N, u32 freq)
98{
99 /* We use the Goertzel algorithm to determine the power of the
100 * given frequency in the signal */
101 s32 s_prev = 0;
102 s32 s_prev2 = 0;
103 s32 coeff = 2*int_cos(freq);
104 u32 i;
105
106 u64 tmp;
107 u32 divisor;
108
109 for (i = 0; i < N; i++) {
110 s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2;
111 s_prev2 = s_prev;
112 s_prev = s;
113 }
114
115 tmp = (s64)s_prev2 * s_prev2 + (s64)s_prev * s_prev -
116 (s64)coeff * s_prev2 * s_prev / 32768;
117
118 /* XXX: N must be low enough so that N*N fits in s32.
119 * Else we need two divisions. */
120 divisor = N * N;
121 do_div(tmp, divisor);
122
123 return (u32) tmp;
124}
125
126static u32 freq_magnitude(s16 x[], u32 N, u32 freq)
127{
128 u32 sum = int_goertzel(x, N, freq);
129 return (u32)int_sqrt(sum);
130}
131
132static u32 noise_magnitude(s16 x[], u32 N, u32 freq_start, u32 freq_end)
133{
134 int i;
135 u32 sum = 0;
136 u32 freq_step;
137 int samples = 5;
138
139 if (N > 192) {
140 /* The last 192 samples are enough for noise detection */
141 x += (N-192);
142 N = 192;
143 }
144
145 freq_step = (freq_end - freq_start) / (samples - 1);
146
147 for (i = 0; i < samples; i++) {
148 sum += int_goertzel(x, N, freq_start);
149 freq_start += freq_step;
150 }
151
152 return (u32)int_sqrt(sum / samples);
153}
154
155static s32 detect_a2_a2m_eiaj(struct cx88_core *core, s16 x[], u32 N)
156{
157 s32 carrier, stereo, dual, noise;
158 s32 carrier_freq, stereo_freq, dual_freq;
159 s32 ret;
160
161 switch (core->tvaudio) {
162 case WW_BG:
163 case WW_DK:
164 carrier_freq = FREQ_A2_CARRIER;
165 stereo_freq = FREQ_A2_STEREO;
166 dual_freq = FREQ_A2_DUAL;
167 break;
168 case WW_M:
169 carrier_freq = FREQ_A2M_CARRIER;
170 stereo_freq = FREQ_A2M_STEREO;
171 dual_freq = FREQ_A2M_DUAL;
172 break;
173 case WW_EIAJ:
174 carrier_freq = FREQ_EIAJ_CARRIER;
175 stereo_freq = FREQ_EIAJ_STEREO;
176 dual_freq = FREQ_EIAJ_DUAL;
177 break;
178 default:
179 printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n",
180 core->name, core->tvaudio, __func__);
181 return UNSET;
182 }
183
184 carrier = freq_magnitude(x, N, carrier_freq);
185 stereo = freq_magnitude(x, N, stereo_freq);
186 dual = freq_magnitude(x, N, dual_freq);
187 noise = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END);
188
189 dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, "
190 "noise=%d\n", carrier, stereo, dual, noise);
191
192 if (stereo > dual)
193 ret = V4L2_TUNER_SUB_STEREO;
194 else
195 ret = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
196
197 if (core->tvaudio == WW_EIAJ) {
198 /* EIAJ checks may need adjustments */
199 if ((carrier > max(stereo, dual)*2) &&
200 (carrier < max(stereo, dual)*6) &&
201 (carrier > 20 && carrier < 200) &&
202 (max(stereo, dual) > min(stereo, dual))) {
203 /* For EIAJ the carrier is always present,
204 so we probably don't need noise detection */
205 return ret;
206 }
207 } else {
208 if ((carrier > max(stereo, dual)*2) &&
209 (carrier < max(stereo, dual)*8) &&
210 (carrier > 20 && carrier < 200) &&
211 (noise < 10) &&
212 (max(stereo, dual) > min(stereo, dual)*2)) {
213 return ret;
214 }
215 }
216 return V4L2_TUNER_SUB_MONO;
217}
218
219static s32 detect_btsc(struct cx88_core *core, s16 x[], u32 N)
220{
221 s32 sap_ref = freq_magnitude(x, N, FREQ_BTSC_SAP_REF);
222 s32 sap = freq_magnitude(x, N, FREQ_BTSC_SAP);
223 s32 dual_ref = freq_magnitude(x, N, FREQ_BTSC_DUAL_REF);
224 s32 dual = freq_magnitude(x, N, FREQ_BTSC_DUAL);
225 dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d"
226 "\n", dual_ref, dual, sap_ref, sap);
227 /* FIXME: Currently not supported */
228 return UNSET;
229}
230
231static s16 *read_rds_samples(struct cx88_core *core, u32 *N)
232{
233 const struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27];
234 s16 *samples;
235
236 unsigned int i;
237 unsigned int bpl = srch->fifo_size/AUD_RDS_LINES;
238 unsigned int spl = bpl/4;
239 unsigned int sample_count = spl*(AUD_RDS_LINES-1);
240
241 u32 current_address = cx_read(srch->ptr1_reg);
242 u32 offset = (current_address - srch->fifo_start + bpl);
243
244 dprintk(1, "read RDS samples: current_address=%08x (offset=%08x), "
245 "sample_count=%d, aud_intstat=%08x\n", current_address,
246 current_address - srch->fifo_start, sample_count,
247 cx_read(MO_AUD_INTSTAT));
248
249 samples = kmalloc(sizeof(s16)*sample_count, GFP_KERNEL);
250 if (!samples)
251 return NULL;
252
253 *N = sample_count;
254
255 for (i = 0; i < sample_count; i++) {
256 offset = offset % (AUD_RDS_LINES*bpl);
257 samples[i] = cx_read(srch->fifo_start + offset);
258 offset += 4;
259 }
260
261 if (dsp_debug >= 2) {
262 dprintk(2, "RDS samples dump: ");
263 for (i = 0; i < sample_count; i++)
264 printk("%hd ", samples[i]);
265 printk(".\n");
266 }
267
268 return samples;
269}
270
271s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core)
272{
273 s16 *samples;
274 u32 N = 0;
275 s32 ret = UNSET;
276
277 /* If audio RDS fifo is disabled, we can't read the samples */
278 if (!(cx_read(MO_AUD_DMACNTRL) & 0x04))
279 return ret;
280 if (!(cx_read(AUD_CTL) & EN_FMRADIO_EN_RDS))
281 return ret;
282
283 /* Wait at least 500 ms after an audio standard change */
284 if (time_before(jiffies, core->last_change + msecs_to_jiffies(500)))
285 return ret;
286
287 samples = read_rds_samples(core, &N);
288
289 if (!samples)
290 return ret;
291
292 switch (core->tvaudio) {
293 case WW_BG:
294 case WW_DK:
295 case WW_EIAJ:
296 case WW_M:
297 ret = detect_a2_a2m_eiaj(core, samples, N);
298 break;
299 case WW_BTSC:
300 ret = detect_btsc(core, samples, N);
301 break;
302 case WW_NONE:
303 case WW_I:
304 case WW_L:
305 case WW_I2SPT:
306 case WW_FM:
307 case WW_I2SADC:
308 break;
309 }
310
311 kfree(samples);
312
313 if (UNSET != ret)
314 dprintk(1, "stereo/sap detection result:%s%s%s\n",
315 (ret & V4L2_TUNER_SUB_MONO) ? " mono" : "",
316 (ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
317 (ret & V4L2_TUNER_SUB_LANG2) ? " dual" : "");
318
319 return ret;
320}
321EXPORT_SYMBOL(cx88_dsp_detect_stereo_sap);
322
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
new file mode 100644
index 00000000000..cf3d33ab541
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -0,0 +1,1764 @@
1/*
2 *
3 * device driver for Conexant 2388x based TV cards
4 * MPEG Transport Stream (DVB) routines
5 *
6 * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
7 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/device.h>
27#include <linux/fs.h>
28#include <linux/kthread.h>
29#include <linux/file.h>
30#include <linux/suspend.h>
31
32#include "cx88.h"
33#include "dvb-pll.h"
34#include <media/v4l2-common.h>
35
36#include "mt352.h"
37#include "mt352_priv.h"
38#include "cx88-vp3054-i2c.h"
39#include "zl10353.h"
40#include "cx22702.h"
41#include "or51132.h"
42#include "lgdt330x.h"
43#include "s5h1409.h"
44#include "xc4000.h"
45#include "xc5000.h"
46#include "nxt200x.h"
47#include "cx24123.h"
48#include "isl6421.h"
49#include "tuner-simple.h"
50#include "tda9887.h"
51#include "s5h1411.h"
52#include "stv0299.h"
53#include "z0194a.h"
54#include "stv0288.h"
55#include "stb6000.h"
56#include "cx24116.h"
57#include "stv0900.h"
58#include "stb6100.h"
59#include "stb6100_proc.h"
60#include "mb86a16.h"
61#include "ds3000.h"
62
63MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
64MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
65MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
66MODULE_LICENSE("GPL");
67MODULE_VERSION(CX88_VERSION);
68
69static unsigned int debug;
70module_param(debug, int, 0644);
71MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
72
73static unsigned int dvb_buf_tscnt = 32;
74module_param(dvb_buf_tscnt, int, 0644);
75MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]");
76
77DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
78
79#define dprintk(level,fmt, arg...) if (debug >= level) \
80 printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
81
82/* ------------------------------------------------------------------ */
83
84static int dvb_buf_setup(struct videobuf_queue *q,
85 unsigned int *count, unsigned int *size)
86{
87 struct cx8802_dev *dev = q->priv_data;
88
89 dev->ts_packet_size = 188 * 4;
90 dev->ts_packet_count = dvb_buf_tscnt;
91
92 *size = dev->ts_packet_size * dev->ts_packet_count;
93 *count = dvb_buf_tscnt;
94 return 0;
95}
96
97static int dvb_buf_prepare(struct videobuf_queue *q,
98 struct videobuf_buffer *vb, enum v4l2_field field)
99{
100 struct cx8802_dev *dev = q->priv_data;
101 return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
102}
103
104static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
105{
106 struct cx8802_dev *dev = q->priv_data;
107 cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
108}
109
110static void dvb_buf_release(struct videobuf_queue *q,
111 struct videobuf_buffer *vb)
112{
113 cx88_free_buffer(q, (struct cx88_buffer*)vb);
114}
115
116static const struct videobuf_queue_ops dvb_qops = {
117 .buf_setup = dvb_buf_setup,
118 .buf_prepare = dvb_buf_prepare,
119 .buf_queue = dvb_buf_queue,
120 .buf_release = dvb_buf_release,
121};
122
123/* ------------------------------------------------------------------ */
124
125static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
126{
127 struct cx8802_dev *dev= fe->dvb->priv;
128 struct cx8802_driver *drv = NULL;
129 int ret = 0;
130 int fe_id;
131
132 fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
133 if (!fe_id) {
134 printk(KERN_ERR "%s() No frontend found\n", __func__);
135 return -EINVAL;
136 }
137
138 mutex_lock(&dev->core->lock);
139 drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
140 if (drv) {
141 if (acquire){
142 dev->frontends.active_fe_id = fe_id;
143 ret = drv->request_acquire(drv);
144 } else {
145 ret = drv->request_release(drv);
146 dev->frontends.active_fe_id = 0;
147 }
148 }
149 mutex_unlock(&dev->core->lock);
150
151 return ret;
152}
153
154static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open)
155{
156 struct videobuf_dvb_frontends *f;
157 struct videobuf_dvb_frontend *fe;
158
159 if (!core->dvbdev)
160 return;
161
162 f = &core->dvbdev->frontends;
163
164 if (!f)
165 return;
166
167 if (f->gate <= 1) /* undefined or fe0 */
168 fe = videobuf_dvb_get_frontend(f, 1);
169 else
170 fe = videobuf_dvb_get_frontend(f, f->gate);
171
172 if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
173 fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
174}
175
176/* ------------------------------------------------------------------ */
177
178static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
179{
180 static const u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
181 static const u8 reset [] = { RESET, 0x80 };
182 static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
183 static const u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 };
184 static const u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
185 static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
186
187 mt352_write(fe, clock_config, sizeof(clock_config));
188 udelay(200);
189 mt352_write(fe, reset, sizeof(reset));
190 mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
191
192 mt352_write(fe, agc_cfg, sizeof(agc_cfg));
193 mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
194 mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
195 return 0;
196}
197
198static int dvico_dual_demod_init(struct dvb_frontend *fe)
199{
200 static const u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
201 static const u8 reset [] = { RESET, 0x80 };
202 static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
203 static const u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
204 static const u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
205 static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
206
207 mt352_write(fe, clock_config, sizeof(clock_config));
208 udelay(200);
209 mt352_write(fe, reset, sizeof(reset));
210 mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
211
212 mt352_write(fe, agc_cfg, sizeof(agc_cfg));
213 mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
214 mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
215
216 return 0;
217}
218
219static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
220{
221 static const u8 clock_config [] = { 0x89, 0x38, 0x39 };
222 static const u8 reset [] = { 0x50, 0x80 };
223 static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
224 static const u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
225 0x00, 0xFF, 0x00, 0x40, 0x40 };
226 static const u8 dntv_extra[] = { 0xB5, 0x7A };
227 static const u8 capt_range_cfg[] = { 0x75, 0x32 };
228
229 mt352_write(fe, clock_config, sizeof(clock_config));
230 udelay(2000);
231 mt352_write(fe, reset, sizeof(reset));
232 mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
233
234 mt352_write(fe, agc_cfg, sizeof(agc_cfg));
235 udelay(2000);
236 mt352_write(fe, dntv_extra, sizeof(dntv_extra));
237 mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
238
239 return 0;
240}
241
242static const struct mt352_config dvico_fusionhdtv = {
243 .demod_address = 0x0f,
244 .demod_init = dvico_fusionhdtv_demod_init,
245};
246
247static const struct mt352_config dntv_live_dvbt_config = {
248 .demod_address = 0x0f,
249 .demod_init = dntv_live_dvbt_demod_init,
250};
251
252static const struct mt352_config dvico_fusionhdtv_dual = {
253 .demod_address = 0x0f,
254 .demod_init = dvico_dual_demod_init,
255};
256
257static const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = {
258 .demod_address = (0x1e >> 1),
259 .no_tuner = 1,
260 .if2 = 45600,
261};
262
263static struct mb86a16_config twinhan_vp1027 = {
264 .demod_address = 0x08,
265};
266
267#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
268static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
269{
270 static const u8 clock_config [] = { 0x89, 0x38, 0x38 };
271 static const u8 reset [] = { 0x50, 0x80 };
272 static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
273 static const u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
274 0x00, 0xFF, 0x00, 0x40, 0x40 };
275 static const u8 dntv_extra[] = { 0xB5, 0x7A };
276 static const u8 capt_range_cfg[] = { 0x75, 0x32 };
277
278 mt352_write(fe, clock_config, sizeof(clock_config));
279 udelay(2000);
280 mt352_write(fe, reset, sizeof(reset));
281 mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
282
283 mt352_write(fe, agc_cfg, sizeof(agc_cfg));
284 udelay(2000);
285 mt352_write(fe, dntv_extra, sizeof(dntv_extra));
286 mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
287
288 return 0;
289}
290
291static const struct mt352_config dntv_live_dvbt_pro_config = {
292 .demod_address = 0x0f,
293 .no_tuner = 1,
294 .demod_init = dntv_live_dvbt_pro_demod_init,
295};
296#endif
297
298static const struct zl10353_config dvico_fusionhdtv_hybrid = {
299 .demod_address = 0x0f,
300 .no_tuner = 1,
301};
302
303static const struct zl10353_config dvico_fusionhdtv_xc3028 = {
304 .demod_address = 0x0f,
305 .if2 = 45600,
306 .no_tuner = 1,
307};
308
309static const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
310 .demod_address = 0x0f,
311 .if2 = 4560,
312 .no_tuner = 1,
313 .demod_init = dvico_fusionhdtv_demod_init,
314};
315
316static const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
317 .demod_address = 0x0f,
318};
319
320static const struct cx22702_config connexant_refboard_config = {
321 .demod_address = 0x43,
322 .output_mode = CX22702_SERIAL_OUTPUT,
323};
324
325static const struct cx22702_config hauppauge_hvr_config = {
326 .demod_address = 0x63,
327 .output_mode = CX22702_SERIAL_OUTPUT,
328};
329
330static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured)
331{
332 struct cx8802_dev *dev= fe->dvb->priv;
333 dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
334 return 0;
335}
336
337static const struct or51132_config pchdtv_hd3000 = {
338 .demod_address = 0x15,
339 .set_ts_params = or51132_set_ts_param,
340};
341
342static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
343{
344 struct cx8802_dev *dev= fe->dvb->priv;
345 struct cx88_core *core = dev->core;
346
347 dprintk(1, "%s: index = %d\n", __func__, index);
348 if (index == 0)
349 cx_clear(MO_GP0_IO, 8);
350 else
351 cx_set(MO_GP0_IO, 8);
352 return 0;
353}
354
355static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
356{
357 struct cx8802_dev *dev= fe->dvb->priv;
358 if (is_punctured)
359 dev->ts_gen_cntrl |= 0x04;
360 else
361 dev->ts_gen_cntrl &= ~0x04;
362 return 0;
363}
364
365static struct lgdt330x_config fusionhdtv_3_gold = {
366 .demod_address = 0x0e,
367 .demod_chip = LGDT3302,
368 .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
369 .set_ts_params = lgdt330x_set_ts_param,
370};
371
372static const struct lgdt330x_config fusionhdtv_5_gold = {
373 .demod_address = 0x0e,
374 .demod_chip = LGDT3303,
375 .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
376 .set_ts_params = lgdt330x_set_ts_param,
377};
378
379static const struct lgdt330x_config pchdtv_hd5500 = {
380 .demod_address = 0x59,
381 .demod_chip = LGDT3303,
382 .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
383 .set_ts_params = lgdt330x_set_ts_param,
384};
385
386static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
387{
388 struct cx8802_dev *dev= fe->dvb->priv;
389 dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
390 return 0;
391}
392
393static const struct nxt200x_config ati_hdtvwonder = {
394 .demod_address = 0x0a,
395 .set_ts_params = nxt200x_set_ts_param,
396};
397
398static int cx24123_set_ts_param(struct dvb_frontend* fe,
399 int is_punctured)
400{
401 struct cx8802_dev *dev= fe->dvb->priv;
402 dev->ts_gen_cntrl = 0x02;
403 return 0;
404}
405
406static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
407 fe_sec_voltage_t voltage)
408{
409 struct cx8802_dev *dev= fe->dvb->priv;
410 struct cx88_core *core = dev->core;
411
412 if (voltage == SEC_VOLTAGE_OFF)
413 cx_write(MO_GP0_IO, 0x000006fb);
414 else
415 cx_write(MO_GP0_IO, 0x000006f9);
416
417 if (core->prev_set_voltage)
418 return core->prev_set_voltage(fe, voltage);
419 return 0;
420}
421
422static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
423 fe_sec_voltage_t voltage)
424{
425 struct cx8802_dev *dev= fe->dvb->priv;
426 struct cx88_core *core = dev->core;
427
428 if (voltage == SEC_VOLTAGE_OFF) {
429 dprintk(1,"LNB Voltage OFF\n");
430 cx_write(MO_GP0_IO, 0x0000efff);
431 }
432
433 if (core->prev_set_voltage)
434 return core->prev_set_voltage(fe, voltage);
435 return 0;
436}
437
438static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
439 fe_sec_voltage_t voltage)
440{
441 struct cx8802_dev *dev= fe->dvb->priv;
442 struct cx88_core *core = dev->core;
443
444 cx_set(MO_GP0_IO, 0x6040);
445 switch (voltage) {
446 case SEC_VOLTAGE_13:
447 cx_clear(MO_GP0_IO, 0x20);
448 break;
449 case SEC_VOLTAGE_18:
450 cx_set(MO_GP0_IO, 0x20);
451 break;
452 case SEC_VOLTAGE_OFF:
453 cx_clear(MO_GP0_IO, 0x20);
454 break;
455 }
456
457 if (core->prev_set_voltage)
458 return core->prev_set_voltage(fe, voltage);
459 return 0;
460}
461
462static int vp1027_set_voltage(struct dvb_frontend *fe,
463 fe_sec_voltage_t voltage)
464{
465 struct cx8802_dev *dev = fe->dvb->priv;
466 struct cx88_core *core = dev->core;
467
468 switch (voltage) {
469 case SEC_VOLTAGE_13:
470 dprintk(1, "LNB SEC Voltage=13\n");
471 cx_write(MO_GP0_IO, 0x00001220);
472 break;
473 case SEC_VOLTAGE_18:
474 dprintk(1, "LNB SEC Voltage=18\n");
475 cx_write(MO_GP0_IO, 0x00001222);
476 break;
477 case SEC_VOLTAGE_OFF:
478 dprintk(1, "LNB Voltage OFF\n");
479 cx_write(MO_GP0_IO, 0x00001230);
480 break;
481 }
482
483 if (core->prev_set_voltage)
484 return core->prev_set_voltage(fe, voltage);
485 return 0;
486}
487
488static const struct cx24123_config geniatech_dvbs_config = {
489 .demod_address = 0x55,
490 .set_ts_params = cx24123_set_ts_param,
491};
492
493static const struct cx24123_config hauppauge_novas_config = {
494 .demod_address = 0x55,
495 .set_ts_params = cx24123_set_ts_param,
496};
497
498static const struct cx24123_config kworld_dvbs_100_config = {
499 .demod_address = 0x15,
500 .set_ts_params = cx24123_set_ts_param,
501 .lnb_polarity = 1,
502};
503
504static const struct s5h1409_config pinnacle_pctv_hd_800i_config = {
505 .demod_address = 0x32 >> 1,
506 .output_mode = S5H1409_PARALLEL_OUTPUT,
507 .gpio = S5H1409_GPIO_ON,
508 .qam_if = 44000,
509 .inversion = S5H1409_INVERSION_OFF,
510 .status_mode = S5H1409_DEMODLOCKING,
511 .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
512};
513
514static const struct s5h1409_config dvico_hdtv5_pci_nano_config = {
515 .demod_address = 0x32 >> 1,
516 .output_mode = S5H1409_SERIAL_OUTPUT,
517 .gpio = S5H1409_GPIO_OFF,
518 .inversion = S5H1409_INVERSION_OFF,
519 .status_mode = S5H1409_DEMODLOCKING,
520 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
521};
522
523static const struct s5h1409_config kworld_atsc_120_config = {
524 .demod_address = 0x32 >> 1,
525 .output_mode = S5H1409_SERIAL_OUTPUT,
526 .gpio = S5H1409_GPIO_OFF,
527 .inversion = S5H1409_INVERSION_OFF,
528 .status_mode = S5H1409_DEMODLOCKING,
529 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
530};
531
532static const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
533 .i2c_address = 0x64,
534 .if_khz = 5380,
535};
536
537static const struct zl10353_config cx88_pinnacle_hybrid_pctv = {
538 .demod_address = (0x1e >> 1),
539 .no_tuner = 1,
540 .if2 = 45600,
541};
542
543static const struct zl10353_config cx88_geniatech_x8000_mt = {
544 .demod_address = (0x1e >> 1),
545 .no_tuner = 1,
546 .disable_i2c_gate_ctrl = 1,
547};
548
549static const struct s5h1411_config dvico_fusionhdtv7_config = {
550 .output_mode = S5H1411_SERIAL_OUTPUT,
551 .gpio = S5H1411_GPIO_ON,
552 .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
553 .qam_if = S5H1411_IF_44000,
554 .vsb_if = S5H1411_IF_44000,
555 .inversion = S5H1411_INVERSION_OFF,
556 .status_mode = S5H1411_DEMODLOCKING
557};
558
559static const struct xc5000_config dvico_fusionhdtv7_tuner_config = {
560 .i2c_address = 0xc2 >> 1,
561 .if_khz = 5380,
562};
563
564static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
565{
566 struct dvb_frontend *fe;
567 struct videobuf_dvb_frontend *fe0 = NULL;
568 struct xc2028_ctrl ctl;
569 struct xc2028_config cfg = {
570 .i2c_adap = &dev->core->i2c_adap,
571 .i2c_addr = addr,
572 .ctrl = &ctl,
573 };
574
575 /* Get the first frontend */
576 fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
577 if (!fe0)
578 return -EINVAL;
579
580 if (!fe0->dvb.frontend) {
581 printk(KERN_ERR "%s/2: dvb frontend not attached. "
582 "Can't attach xc3028\n",
583 dev->core->name);
584 return -EINVAL;
585 }
586
587 /*
588 * Some xc3028 devices may be hidden by an I2C gate. This is known
589 * to happen with some s5h1409-based devices.
590 * Now that I2C gate is open, sets up xc3028 configuration
591 */
592 cx88_setup_xc3028(dev->core, &ctl);
593
594 fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
595 if (!fe) {
596 printk(KERN_ERR "%s/2: xc3028 attach failed\n",
597 dev->core->name);
598 dvb_frontend_detach(fe0->dvb.frontend);
599 dvb_unregister_frontend(fe0->dvb.frontend);
600 fe0->dvb.frontend = NULL;
601 return -EINVAL;
602 }
603
604 printk(KERN_INFO "%s/2: xc3028 attached\n",
605 dev->core->name);
606
607 return 0;
608}
609
610static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
611{
612 struct dvb_frontend *fe;
613 struct videobuf_dvb_frontend *fe0 = NULL;
614
615 /* Get the first frontend */
616 fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
617 if (!fe0)
618 return -EINVAL;
619
620 if (!fe0->dvb.frontend) {
621 printk(KERN_ERR "%s/2: dvb frontend not attached. "
622 "Can't attach xc4000\n",
623 dev->core->name);
624 return -EINVAL;
625 }
626
627 fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
628 cfg);
629 if (!fe) {
630 printk(KERN_ERR "%s/2: xc4000 attach failed\n",
631 dev->core->name);
632 dvb_frontend_detach(fe0->dvb.frontend);
633 dvb_unregister_frontend(fe0->dvb.frontend);
634 fe0->dvb.frontend = NULL;
635 return -EINVAL;
636 }
637
638 printk(KERN_INFO "%s/2: xc4000 attached\n", dev->core->name);
639
640 return 0;
641}
642
643static int cx24116_set_ts_param(struct dvb_frontend *fe,
644 int is_punctured)
645{
646 struct cx8802_dev *dev = fe->dvb->priv;
647 dev->ts_gen_cntrl = 0x2;
648
649 return 0;
650}
651
652static int stv0900_set_ts_param(struct dvb_frontend *fe,
653 int is_punctured)
654{
655 struct cx8802_dev *dev = fe->dvb->priv;
656 dev->ts_gen_cntrl = 0;
657
658 return 0;
659}
660
661static int cx24116_reset_device(struct dvb_frontend *fe)
662{
663 struct cx8802_dev *dev = fe->dvb->priv;
664 struct cx88_core *core = dev->core;
665
666 /* Reset the part */
667 /* Put the cx24116 into reset */
668 cx_write(MO_SRST_IO, 0);
669 msleep(10);
670 /* Take the cx24116 out of reset */
671 cx_write(MO_SRST_IO, 1);
672 msleep(10);
673
674 return 0;
675}
676
677static const struct cx24116_config hauppauge_hvr4000_config = {
678 .demod_address = 0x05,
679 .set_ts_params = cx24116_set_ts_param,
680 .reset_device = cx24116_reset_device,
681};
682
683static const struct cx24116_config tevii_s460_config = {
684 .demod_address = 0x55,
685 .set_ts_params = cx24116_set_ts_param,
686 .reset_device = cx24116_reset_device,
687};
688
689static int ds3000_set_ts_param(struct dvb_frontend *fe,
690 int is_punctured)
691{
692 struct cx8802_dev *dev = fe->dvb->priv;
693 dev->ts_gen_cntrl = 4;
694
695 return 0;
696}
697
698static struct ds3000_config tevii_ds3000_config = {
699 .demod_address = 0x68,
700 .set_ts_params = ds3000_set_ts_param,
701};
702
703static const struct stv0900_config prof_7301_stv0900_config = {
704 .demod_address = 0x6a,
705/* demod_mode = 0,*/
706 .xtal = 27000000,
707 .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
708 .diseqc_mode = 2,/* 2/3 PWM */
709 .tun1_maddress = 0,/* 0x60 */
710 .tun1_adc = 0,/* 2 Vpp */
711 .path1_mode = 3,
712 .set_ts_params = stv0900_set_ts_param,
713};
714
715static const struct stb6100_config prof_7301_stb6100_config = {
716 .tuner_address = 0x60,
717 .refclock = 27000000,
718};
719
720static const struct stv0299_config tevii_tuner_sharp_config = {
721 .demod_address = 0x68,
722 .inittab = sharp_z0194a_inittab,
723 .mclk = 88000000UL,
724 .invert = 1,
725 .skip_reinit = 0,
726 .lock_output = 1,
727 .volt13_op0_op1 = STV0299_VOLT13_OP1,
728 .min_delay_ms = 100,
729 .set_symbol_rate = sharp_z0194a_set_symbol_rate,
730 .set_ts_params = cx24116_set_ts_param,
731};
732
733static const struct stv0288_config tevii_tuner_earda_config = {
734 .demod_address = 0x68,
735 .min_delay_ms = 100,
736 .set_ts_params = cx24116_set_ts_param,
737};
738
739static int cx8802_alloc_frontends(struct cx8802_dev *dev)
740{
741 struct cx88_core *core = dev->core;
742 struct videobuf_dvb_frontend *fe = NULL;
743 int i;
744
745 mutex_init(&dev->frontends.lock);
746 INIT_LIST_HEAD(&dev->frontends.felist);
747
748 if (!core->board.num_frontends)
749 return -ENODEV;
750
751 printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
752 core->board.num_frontends);
753 for (i = 1; i <= core->board.num_frontends; i++) {
754 fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
755 if (!fe) {
756 printk(KERN_ERR "%s() failed to alloc\n", __func__);
757 videobuf_dvb_dealloc_frontends(&dev->frontends);
758 return -ENOMEM;
759 }
760 }
761 return 0;
762}
763
764
765
766static const u8 samsung_smt_7020_inittab[] = {
767 0x01, 0x15,
768 0x02, 0x00,
769 0x03, 0x00,
770 0x04, 0x7D,
771 0x05, 0x0F,
772 0x06, 0x02,
773 0x07, 0x00,
774 0x08, 0x60,
775
776 0x0A, 0xC2,
777 0x0B, 0x00,
778 0x0C, 0x01,
779 0x0D, 0x81,
780 0x0E, 0x44,
781 0x0F, 0x09,
782 0x10, 0x3C,
783 0x11, 0x84,
784 0x12, 0xDA,
785 0x13, 0x99,
786 0x14, 0x8D,
787 0x15, 0xCE,
788 0x16, 0xE8,
789 0x17, 0x43,
790 0x18, 0x1C,
791 0x19, 0x1B,
792 0x1A, 0x1D,
793
794 0x1C, 0x12,
795 0x1D, 0x00,
796 0x1E, 0x00,
797 0x1F, 0x00,
798 0x20, 0x00,
799 0x21, 0x00,
800 0x22, 0x00,
801 0x23, 0x00,
802
803 0x28, 0x02,
804 0x29, 0x28,
805 0x2A, 0x14,
806 0x2B, 0x0F,
807 0x2C, 0x09,
808 0x2D, 0x05,
809
810 0x31, 0x1F,
811 0x32, 0x19,
812 0x33, 0xFC,
813 0x34, 0x13,
814 0xff, 0xff,
815};
816
817
818static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe,
819 struct dvb_frontend_parameters *params)
820{
821 struct cx8802_dev *dev = fe->dvb->priv;
822 u8 buf[4];
823 u32 div;
824 struct i2c_msg msg = {
825 .addr = 0x61,
826 .flags = 0,
827 .buf = buf,
828 .len = sizeof(buf) };
829
830 div = params->frequency / 125;
831
832 buf[0] = (div >> 8) & 0x7f;
833 buf[1] = div & 0xff;
834 buf[2] = 0x84; /* 0xC4 */
835 buf[3] = 0x00;
836
837 if (params->frequency < 1500000)
838 buf[3] |= 0x10;
839
840 if (fe->ops.i2c_gate_ctrl)
841 fe->ops.i2c_gate_ctrl(fe, 1);
842
843 if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1)
844 return -EIO;
845
846 return 0;
847}
848
849static int samsung_smt_7020_set_tone(struct dvb_frontend *fe,
850 fe_sec_tone_mode_t tone)
851{
852 struct cx8802_dev *dev = fe->dvb->priv;
853 struct cx88_core *core = dev->core;
854
855 cx_set(MO_GP0_IO, 0x0800);
856
857 switch (tone) {
858 case SEC_TONE_ON:
859 cx_set(MO_GP0_IO, 0x08);
860 break;
861 case SEC_TONE_OFF:
862 cx_clear(MO_GP0_IO, 0x08);
863 break;
864 default:
865 return -EINVAL;
866 }
867
868 return 0;
869}
870
871static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
872 fe_sec_voltage_t voltage)
873{
874 struct cx8802_dev *dev = fe->dvb->priv;
875 struct cx88_core *core = dev->core;
876
877 u8 data;
878 struct i2c_msg msg = {
879 .addr = 8,
880 .flags = 0,
881 .buf = &data,
882 .len = sizeof(data) };
883
884 cx_set(MO_GP0_IO, 0x8000);
885
886 switch (voltage) {
887 case SEC_VOLTAGE_OFF:
888 break;
889 case SEC_VOLTAGE_13:
890 data = ISL6421_EN1 | ISL6421_LLC1;
891 cx_clear(MO_GP0_IO, 0x80);
892 break;
893 case SEC_VOLTAGE_18:
894 data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1;
895 cx_clear(MO_GP0_IO, 0x80);
896 break;
897 default:
898 return -EINVAL;
899 };
900
901 return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO;
902}
903
904static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe,
905 u32 srate, u32 ratio)
906{
907 u8 aclk = 0;
908 u8 bclk = 0;
909
910 if (srate < 1500000) {
911 aclk = 0xb7;
912 bclk = 0x47;
913 } else if (srate < 3000000) {
914 aclk = 0xb7;
915 bclk = 0x4b;
916 } else if (srate < 7000000) {
917 aclk = 0xb7;
918 bclk = 0x4f;
919 } else if (srate < 14000000) {
920 aclk = 0xb7;
921 bclk = 0x53;
922 } else if (srate < 30000000) {
923 aclk = 0xb6;
924 bclk = 0x53;
925 } else if (srate < 45000000) {
926 aclk = 0xb4;
927 bclk = 0x51;
928 }
929
930 stv0299_writereg(fe, 0x13, aclk);
931 stv0299_writereg(fe, 0x14, bclk);
932 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
933 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
934 stv0299_writereg(fe, 0x21, ratio & 0xf0);
935
936 return 0;
937}
938
939
940static const struct stv0299_config samsung_stv0299_config = {
941 .demod_address = 0x68,
942 .inittab = samsung_smt_7020_inittab,
943 .mclk = 88000000UL,
944 .invert = 0,
945 .skip_reinit = 0,
946 .lock_output = STV0299_LOCKOUTPUT_LK,
947 .volt13_op0_op1 = STV0299_VOLT13_OP1,
948 .min_delay_ms = 100,
949 .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate,
950};
951
952static int dvb_register(struct cx8802_dev *dev)
953{
954 struct cx88_core *core = dev->core;
955 struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
956 int mfe_shared = 0; /* bus not shared by default */
957
958 if (0 != core->i2c_rc) {
959 printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
960 goto frontend_detach;
961 }
962
963 /* Get the first frontend */
964 fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
965 if (!fe0)
966 goto frontend_detach;
967
968 /* multi-frontend gate control is undefined or defaults to fe0 */
969 dev->frontends.gate = 0;
970
971 /* Sets the gate control callback to be used by i2c command calls */
972 core->gate_ctrl = cx88_dvb_gate_ctrl;
973
974 /* init frontend(s) */
975 switch (core->boardnr) {
976 case CX88_BOARD_HAUPPAUGE_DVB_T1:
977 fe0->dvb.frontend = dvb_attach(cx22702_attach,
978 &connexant_refboard_config,
979 &core->i2c_adap);
980 if (fe0->dvb.frontend != NULL) {
981 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
982 0x61, &core->i2c_adap,
983 DVB_PLL_THOMSON_DTT759X))
984 goto frontend_detach;
985 }
986 break;
987 case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
988 case CX88_BOARD_CONEXANT_DVB_T1:
989 case CX88_BOARD_KWORLD_DVB_T_CX22702:
990 case CX88_BOARD_WINFAST_DTV1000:
991 fe0->dvb.frontend = dvb_attach(cx22702_attach,
992 &connexant_refboard_config,
993 &core->i2c_adap);
994 if (fe0->dvb.frontend != NULL) {
995 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
996 0x60, &core->i2c_adap,
997 DVB_PLL_THOMSON_DTT7579))
998 goto frontend_detach;
999 }
1000 break;
1001 case CX88_BOARD_WINFAST_DTV2000H:
1002 case CX88_BOARD_WINFAST_DTV2000H_J:
1003 case CX88_BOARD_HAUPPAUGE_HVR1100:
1004 case CX88_BOARD_HAUPPAUGE_HVR1100LP:
1005 case CX88_BOARD_HAUPPAUGE_HVR1300:
1006 fe0->dvb.frontend = dvb_attach(cx22702_attach,
1007 &hauppauge_hvr_config,
1008 &core->i2c_adap);
1009 if (fe0->dvb.frontend != NULL) {
1010 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1011 &core->i2c_adap, 0x61,
1012 TUNER_PHILIPS_FMD1216ME_MK3))
1013 goto frontend_detach;
1014 }
1015 break;
1016 case CX88_BOARD_HAUPPAUGE_HVR3000:
1017 /* MFE frontend 1 */
1018 mfe_shared = 1;
1019 dev->frontends.gate = 2;
1020 /* DVB-S init */
1021 fe0->dvb.frontend = dvb_attach(cx24123_attach,
1022 &hauppauge_novas_config,
1023 &dev->core->i2c_adap);
1024 if (fe0->dvb.frontend) {
1025 if (!dvb_attach(isl6421_attach,
1026 fe0->dvb.frontend,
1027 &dev->core->i2c_adap,
1028 0x08, ISL6421_DCL, 0x00))
1029 goto frontend_detach;
1030 }
1031 /* MFE frontend 2 */
1032 fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
1033 if (!fe1)
1034 goto frontend_detach;
1035 /* DVB-T init */
1036 fe1->dvb.frontend = dvb_attach(cx22702_attach,
1037 &hauppauge_hvr_config,
1038 &dev->core->i2c_adap);
1039 if (fe1->dvb.frontend) {
1040 fe1->dvb.frontend->id = 1;
1041 if (!dvb_attach(simple_tuner_attach,
1042 fe1->dvb.frontend,
1043 &dev->core->i2c_adap,
1044 0x61, TUNER_PHILIPS_FMD1216ME_MK3))
1045 goto frontend_detach;
1046 }
1047 break;
1048 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
1049 fe0->dvb.frontend = dvb_attach(mt352_attach,
1050 &dvico_fusionhdtv,
1051 &core->i2c_adap);
1052 if (fe0->dvb.frontend != NULL) {
1053 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1054 0x60, NULL, DVB_PLL_THOMSON_DTT7579))
1055 goto frontend_detach;
1056 break;
1057 }
1058 /* ZL10353 replaces MT352 on later cards */
1059 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1060 &dvico_fusionhdtv_plus_v1_1,
1061 &core->i2c_adap);
1062 if (fe0->dvb.frontend != NULL) {
1063 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1064 0x60, NULL, DVB_PLL_THOMSON_DTT7579))
1065 goto frontend_detach;
1066 }
1067 break;
1068 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
1069 /* The tin box says DEE1601, but it seems to be DTT7579
1070 * compatible, with a slightly different MT352 AGC gain. */
1071 fe0->dvb.frontend = dvb_attach(mt352_attach,
1072 &dvico_fusionhdtv_dual,
1073 &core->i2c_adap);
1074 if (fe0->dvb.frontend != NULL) {
1075 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1076 0x61, NULL, DVB_PLL_THOMSON_DTT7579))
1077 goto frontend_detach;
1078 break;
1079 }
1080 /* ZL10353 replaces MT352 on later cards */
1081 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1082 &dvico_fusionhdtv_plus_v1_1,
1083 &core->i2c_adap);
1084 if (fe0->dvb.frontend != NULL) {
1085 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1086 0x61, NULL, DVB_PLL_THOMSON_DTT7579))
1087 goto frontend_detach;
1088 }
1089 break;
1090 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
1091 fe0->dvb.frontend = dvb_attach(mt352_attach,
1092 &dvico_fusionhdtv,
1093 &core->i2c_adap);
1094 if (fe0->dvb.frontend != NULL) {
1095 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1096 0x61, NULL, DVB_PLL_LG_Z201))
1097 goto frontend_detach;
1098 }
1099 break;
1100 case CX88_BOARD_KWORLD_DVB_T:
1101 case CX88_BOARD_DNTV_LIVE_DVB_T:
1102 case CX88_BOARD_ADSTECH_DVB_T_PCI:
1103 fe0->dvb.frontend = dvb_attach(mt352_attach,
1104 &dntv_live_dvbt_config,
1105 &core->i2c_adap);
1106 if (fe0->dvb.frontend != NULL) {
1107 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1108 0x61, NULL, DVB_PLL_UNKNOWN_1))
1109 goto frontend_detach;
1110 }
1111 break;
1112 case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
1113#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
1114 /* MT352 is on a secondary I2C bus made from some GPIO lines */
1115 fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
1116 &dev->vp3054->adap);
1117 if (fe0->dvb.frontend != NULL) {
1118 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1119 &core->i2c_adap, 0x61,
1120 TUNER_PHILIPS_FMD1216ME_MK3))
1121 goto frontend_detach;
1122 }
1123#else
1124 printk(KERN_ERR "%s/2: built without vp3054 support\n",
1125 core->name);
1126#endif
1127 break;
1128 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
1129 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1130 &dvico_fusionhdtv_hybrid,
1131 &core->i2c_adap);
1132 if (fe0->dvb.frontend != NULL) {
1133 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1134 &core->i2c_adap, 0x61,
1135 TUNER_THOMSON_FE6600))
1136 goto frontend_detach;
1137 }
1138 break;
1139 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
1140 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1141 &dvico_fusionhdtv_xc3028,
1142 &core->i2c_adap);
1143 if (fe0->dvb.frontend == NULL)
1144 fe0->dvb.frontend = dvb_attach(mt352_attach,
1145 &dvico_fusionhdtv_mt352_xc3028,
1146 &core->i2c_adap);
1147 /*
1148 * On this board, the demod provides the I2C bus pullup.
1149 * We must not permit gate_ctrl to be performed, or
1150 * the xc3028 cannot communicate on the bus.
1151 */
1152 if (fe0->dvb.frontend)
1153 fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1154 if (attach_xc3028(0x61, dev) < 0)
1155 goto frontend_detach;
1156 break;
1157 case CX88_BOARD_PCHDTV_HD3000:
1158 fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
1159 &core->i2c_adap);
1160 if (fe0->dvb.frontend != NULL) {
1161 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1162 &core->i2c_adap, 0x61,
1163 TUNER_THOMSON_DTT761X))
1164 goto frontend_detach;
1165 }
1166 break;
1167 case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
1168 dev->ts_gen_cntrl = 0x08;
1169
1170 /* Do a hardware reset of chip before using it. */
1171 cx_clear(MO_GP0_IO, 1);
1172 mdelay(100);
1173 cx_set(MO_GP0_IO, 1);
1174 mdelay(200);
1175
1176 /* Select RF connector callback */
1177 fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
1178 fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1179 &fusionhdtv_3_gold,
1180 &core->i2c_adap);
1181 if (fe0->dvb.frontend != NULL) {
1182 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1183 &core->i2c_adap, 0x61,
1184 TUNER_MICROTUNE_4042FI5))
1185 goto frontend_detach;
1186 }
1187 break;
1188 case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
1189 dev->ts_gen_cntrl = 0x08;
1190
1191 /* Do a hardware reset of chip before using it. */
1192 cx_clear(MO_GP0_IO, 1);
1193 mdelay(100);
1194 cx_set(MO_GP0_IO, 9);
1195 mdelay(200);
1196 fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1197 &fusionhdtv_3_gold,
1198 &core->i2c_adap);
1199 if (fe0->dvb.frontend != NULL) {
1200 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1201 &core->i2c_adap, 0x61,
1202 TUNER_THOMSON_DTT761X))
1203 goto frontend_detach;
1204 }
1205 break;
1206 case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
1207 dev->ts_gen_cntrl = 0x08;
1208
1209 /* Do a hardware reset of chip before using it. */
1210 cx_clear(MO_GP0_IO, 1);
1211 mdelay(100);
1212 cx_set(MO_GP0_IO, 1);
1213 mdelay(200);
1214 fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1215 &fusionhdtv_5_gold,
1216 &core->i2c_adap);
1217 if (fe0->dvb.frontend != NULL) {
1218 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1219 &core->i2c_adap, 0x61,
1220 TUNER_LG_TDVS_H06XF))
1221 goto frontend_detach;
1222 if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
1223 &core->i2c_adap, 0x43))
1224 goto frontend_detach;
1225 }
1226 break;
1227 case CX88_BOARD_PCHDTV_HD5500:
1228 dev->ts_gen_cntrl = 0x08;
1229
1230 /* Do a hardware reset of chip before using it. */
1231 cx_clear(MO_GP0_IO, 1);
1232 mdelay(100);
1233 cx_set(MO_GP0_IO, 1);
1234 mdelay(200);
1235 fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1236 &pchdtv_hd5500,
1237 &core->i2c_adap);
1238 if (fe0->dvb.frontend != NULL) {
1239 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1240 &core->i2c_adap, 0x61,
1241 TUNER_LG_TDVS_H06XF))
1242 goto frontend_detach;
1243 if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
1244 &core->i2c_adap, 0x43))
1245 goto frontend_detach;
1246 }
1247 break;
1248 case CX88_BOARD_ATI_HDTVWONDER:
1249 fe0->dvb.frontend = dvb_attach(nxt200x_attach,
1250 &ati_hdtvwonder,
1251 &core->i2c_adap);
1252 if (fe0->dvb.frontend != NULL) {
1253 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1254 &core->i2c_adap, 0x61,
1255 TUNER_PHILIPS_TUV1236D))
1256 goto frontend_detach;
1257 }
1258 break;
1259 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
1260 case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
1261 fe0->dvb.frontend = dvb_attach(cx24123_attach,
1262 &hauppauge_novas_config,
1263 &core->i2c_adap);
1264 if (fe0->dvb.frontend) {
1265 if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
1266 &core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
1267 goto frontend_detach;
1268 }
1269 break;
1270 case CX88_BOARD_KWORLD_DVBS_100:
1271 fe0->dvb.frontend = dvb_attach(cx24123_attach,
1272 &kworld_dvbs_100_config,
1273 &core->i2c_adap);
1274 if (fe0->dvb.frontend) {
1275 core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1276 fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
1277 }
1278 break;
1279 case CX88_BOARD_GENIATECH_DVBS:
1280 fe0->dvb.frontend = dvb_attach(cx24123_attach,
1281 &geniatech_dvbs_config,
1282 &core->i2c_adap);
1283 if (fe0->dvb.frontend) {
1284 core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1285 fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
1286 }
1287 break;
1288 case CX88_BOARD_PINNACLE_PCTV_HD_800i:
1289 fe0->dvb.frontend = dvb_attach(s5h1409_attach,
1290 &pinnacle_pctv_hd_800i_config,
1291 &core->i2c_adap);
1292 if (fe0->dvb.frontend != NULL) {
1293 if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
1294 &core->i2c_adap,
1295 &pinnacle_pctv_hd_800i_tuner_config))
1296 goto frontend_detach;
1297 }
1298 break;
1299 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
1300 fe0->dvb.frontend = dvb_attach(s5h1409_attach,
1301 &dvico_hdtv5_pci_nano_config,
1302 &core->i2c_adap);
1303 if (fe0->dvb.frontend != NULL) {
1304 struct dvb_frontend *fe;
1305 struct xc2028_config cfg = {
1306 .i2c_adap = &core->i2c_adap,
1307 .i2c_addr = 0x61,
1308 };
1309 static struct xc2028_ctrl ctl = {
1310 .fname = XC2028_DEFAULT_FIRMWARE,
1311 .max_len = 64,
1312 .scode_table = XC3028_FE_OREN538,
1313 };
1314
1315 fe = dvb_attach(xc2028_attach,
1316 fe0->dvb.frontend, &cfg);
1317 if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
1318 fe->ops.tuner_ops.set_config(fe, &ctl);
1319 }
1320 break;
1321 case CX88_BOARD_PINNACLE_HYBRID_PCTV:
1322 case CX88_BOARD_WINFAST_DTV1800H:
1323 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1324 &cx88_pinnacle_hybrid_pctv,
1325 &core->i2c_adap);
1326 if (fe0->dvb.frontend) {
1327 fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1328 if (attach_xc3028(0x61, dev) < 0)
1329 goto frontend_detach;
1330 }
1331 break;
1332 case CX88_BOARD_WINFAST_DTV1800H_XC4000:
1333 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
1334 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1335 &cx88_pinnacle_hybrid_pctv,
1336 &core->i2c_adap);
1337 if (fe0->dvb.frontend) {
1338 struct xc4000_config cfg = {
1339 .i2c_address = 0x61,
1340 .default_pm = 0,
1341 .dvb_amplitude = 134,
1342 .set_smoothedcvbs = 1,
1343 .if_khz = 4560
1344 };
1345 fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1346 if (attach_xc4000(dev, &cfg) < 0)
1347 goto frontend_detach;
1348 }
1349 break;
1350 case CX88_BOARD_GENIATECH_X8000_MT:
1351 dev->ts_gen_cntrl = 0x00;
1352
1353 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1354 &cx88_geniatech_x8000_mt,
1355 &core->i2c_adap);
1356 if (attach_xc3028(0x61, dev) < 0)
1357 goto frontend_detach;
1358 break;
1359 case CX88_BOARD_KWORLD_ATSC_120:
1360 fe0->dvb.frontend = dvb_attach(s5h1409_attach,
1361 &kworld_atsc_120_config,
1362 &core->i2c_adap);
1363 if (attach_xc3028(0x61, dev) < 0)
1364 goto frontend_detach;
1365 break;
1366 case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
1367 fe0->dvb.frontend = dvb_attach(s5h1411_attach,
1368 &dvico_fusionhdtv7_config,
1369 &core->i2c_adap);
1370 if (fe0->dvb.frontend != NULL) {
1371 if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
1372 &core->i2c_adap,
1373 &dvico_fusionhdtv7_tuner_config))
1374 goto frontend_detach;
1375 }
1376 break;
1377 case CX88_BOARD_HAUPPAUGE_HVR4000:
1378 /* MFE frontend 1 */
1379 mfe_shared = 1;
1380 dev->frontends.gate = 2;
1381 /* DVB-S/S2 Init */
1382 fe0->dvb.frontend = dvb_attach(cx24116_attach,
1383 &hauppauge_hvr4000_config,
1384 &dev->core->i2c_adap);
1385 if (fe0->dvb.frontend) {
1386 if (!dvb_attach(isl6421_attach,
1387 fe0->dvb.frontend,
1388 &dev->core->i2c_adap,
1389 0x08, ISL6421_DCL, 0x00))
1390 goto frontend_detach;
1391 }
1392 /* MFE frontend 2 */
1393 fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
1394 if (!fe1)
1395 goto frontend_detach;
1396 /* DVB-T Init */
1397 fe1->dvb.frontend = dvb_attach(cx22702_attach,
1398 &hauppauge_hvr_config,
1399 &dev->core->i2c_adap);
1400 if (fe1->dvb.frontend) {
1401 fe1->dvb.frontend->id = 1;
1402 if (!dvb_attach(simple_tuner_attach,
1403 fe1->dvb.frontend,
1404 &dev->core->i2c_adap,
1405 0x61, TUNER_PHILIPS_FMD1216ME_MK3))
1406 goto frontend_detach;
1407 }
1408 break;
1409 case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
1410 fe0->dvb.frontend = dvb_attach(cx24116_attach,
1411 &hauppauge_hvr4000_config,
1412 &dev->core->i2c_adap);
1413 if (fe0->dvb.frontend) {
1414 if (!dvb_attach(isl6421_attach,
1415 fe0->dvb.frontend,
1416 &dev->core->i2c_adap,
1417 0x08, ISL6421_DCL, 0x00))
1418 goto frontend_detach;
1419 }
1420 break;
1421 case CX88_BOARD_PROF_6200:
1422 case CX88_BOARD_TBS_8910:
1423 case CX88_BOARD_TEVII_S420:
1424 fe0->dvb.frontend = dvb_attach(stv0299_attach,
1425 &tevii_tuner_sharp_config,
1426 &core->i2c_adap);
1427 if (fe0->dvb.frontend != NULL) {
1428 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
1429 &core->i2c_adap, DVB_PLL_OPERA1))
1430 goto frontend_detach;
1431 core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1432 fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1433
1434 } else {
1435 fe0->dvb.frontend = dvb_attach(stv0288_attach,
1436 &tevii_tuner_earda_config,
1437 &core->i2c_adap);
1438 if (fe0->dvb.frontend != NULL) {
1439 if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
1440 &core->i2c_adap))
1441 goto frontend_detach;
1442 core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1443 fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1444 }
1445 }
1446 break;
1447 case CX88_BOARD_TEVII_S460:
1448 fe0->dvb.frontend = dvb_attach(cx24116_attach,
1449 &tevii_s460_config,
1450 &core->i2c_adap);
1451 if (fe0->dvb.frontend != NULL)
1452 fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1453 break;
1454 case CX88_BOARD_TEVII_S464:
1455 fe0->dvb.frontend = dvb_attach(ds3000_attach,
1456 &tevii_ds3000_config,
1457 &core->i2c_adap);
1458 if (fe0->dvb.frontend != NULL)
1459 fe0->dvb.frontend->ops.set_voltage =
1460 tevii_dvbs_set_voltage;
1461 break;
1462 case CX88_BOARD_OMICOM_SS4_PCI:
1463 case CX88_BOARD_TBS_8920:
1464 case CX88_BOARD_PROF_7300:
1465 case CX88_BOARD_SATTRADE_ST4200:
1466 fe0->dvb.frontend = dvb_attach(cx24116_attach,
1467 &hauppauge_hvr4000_config,
1468 &core->i2c_adap);
1469 if (fe0->dvb.frontend != NULL)
1470 fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1471 break;
1472 case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
1473 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1474 &cx88_terratec_cinergy_ht_pci_mkii_config,
1475 &core->i2c_adap);
1476 if (fe0->dvb.frontend) {
1477 fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1478 if (attach_xc3028(0x61, dev) < 0)
1479 goto frontend_detach;
1480 }
1481 break;
1482 case CX88_BOARD_PROF_7301:{
1483 struct dvb_tuner_ops *tuner_ops = NULL;
1484
1485 fe0->dvb.frontend = dvb_attach(stv0900_attach,
1486 &prof_7301_stv0900_config,
1487 &core->i2c_adap, 0);
1488 if (fe0->dvb.frontend != NULL) {
1489 if (!dvb_attach(stb6100_attach, fe0->dvb.frontend,
1490 &prof_7301_stb6100_config,
1491 &core->i2c_adap))
1492 goto frontend_detach;
1493
1494 tuner_ops = &fe0->dvb.frontend->ops.tuner_ops;
1495 tuner_ops->set_frequency = stb6100_set_freq;
1496 tuner_ops->get_frequency = stb6100_get_freq;
1497 tuner_ops->set_bandwidth = stb6100_set_bandw;
1498 tuner_ops->get_bandwidth = stb6100_get_bandw;
1499
1500 core->prev_set_voltage =
1501 fe0->dvb.frontend->ops.set_voltage;
1502 fe0->dvb.frontend->ops.set_voltage =
1503 tevii_dvbs_set_voltage;
1504 }
1505 break;
1506 }
1507 case CX88_BOARD_SAMSUNG_SMT_7020:
1508 dev->ts_gen_cntrl = 0x08;
1509
1510 cx_set(MO_GP0_IO, 0x0101);
1511
1512 cx_clear(MO_GP0_IO, 0x01);
1513 mdelay(100);
1514 cx_set(MO_GP0_IO, 0x01);
1515 mdelay(200);
1516
1517 fe0->dvb.frontend = dvb_attach(stv0299_attach,
1518 &samsung_stv0299_config,
1519 &dev->core->i2c_adap);
1520 if (fe0->dvb.frontend) {
1521 fe0->dvb.frontend->ops.tuner_ops.set_params =
1522 samsung_smt_7020_tuner_set_params;
1523 fe0->dvb.frontend->tuner_priv =
1524 &dev->core->i2c_adap;
1525 fe0->dvb.frontend->ops.set_voltage =
1526 samsung_smt_7020_set_voltage;
1527 fe0->dvb.frontend->ops.set_tone =
1528 samsung_smt_7020_set_tone;
1529 }
1530
1531 break;
1532 case CX88_BOARD_TWINHAN_VP1027_DVBS:
1533 dev->ts_gen_cntrl = 0x00;
1534 fe0->dvb.frontend = dvb_attach(mb86a16_attach,
1535 &twinhan_vp1027,
1536 &core->i2c_adap);
1537 if (fe0->dvb.frontend) {
1538 core->prev_set_voltage =
1539 fe0->dvb.frontend->ops.set_voltage;
1540 fe0->dvb.frontend->ops.set_voltage =
1541 vp1027_set_voltage;
1542 }
1543 break;
1544
1545 default:
1546 printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
1547 core->name);
1548 break;
1549 }
1550
1551 if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) {
1552 printk(KERN_ERR
1553 "%s/2: frontend initialization failed\n",
1554 core->name);
1555 goto frontend_detach;
1556 }
1557 /* define general-purpose callback pointer */
1558 fe0->dvb.frontend->callback = cx88_tuner_callback;
1559
1560 /* Ensure all frontends negotiate bus access */
1561 fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
1562 if (fe1)
1563 fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
1564
1565 /* Put the analog decoder in standby to keep it quiet */
1566 call_all(core, core, s_power, 0);
1567
1568 /* register everything */
1569 return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
1570 &dev->pci->dev, adapter_nr, mfe_shared, NULL);
1571
1572frontend_detach:
1573 core->gate_ctrl = NULL;
1574 videobuf_dvb_dealloc_frontends(&dev->frontends);
1575 return -EINVAL;
1576}
1577
1578/* ----------------------------------------------------------- */
1579
1580/* CX8802 MPEG -> mini driver - We have been given the hardware */
1581static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
1582{
1583 struct cx88_core *core = drv->core;
1584 int err = 0;
1585 dprintk( 1, "%s\n", __func__);
1586
1587 switch (core->boardnr) {
1588 case CX88_BOARD_HAUPPAUGE_HVR1300:
1589 /* We arrive here with either the cx23416 or the cx22702
1590 * on the bus. Take the bus from the cx23416 and enable the
1591 * cx22702 demod
1592 */
1593 /* Toggle reset on cx22702 leaving i2c active */
1594 cx_set(MO_GP0_IO, 0x00000080);
1595 udelay(1000);
1596 cx_clear(MO_GP0_IO, 0x00000080);
1597 udelay(50);
1598 cx_set(MO_GP0_IO, 0x00000080);
1599 udelay(1000);
1600 /* enable the cx22702 pins */
1601 cx_clear(MO_GP0_IO, 0x00000004);
1602 udelay(1000);
1603 break;
1604
1605 case CX88_BOARD_HAUPPAUGE_HVR3000:
1606 case CX88_BOARD_HAUPPAUGE_HVR4000:
1607 /* Toggle reset on cx22702 leaving i2c active */
1608 cx_set(MO_GP0_IO, 0x00000080);
1609 udelay(1000);
1610 cx_clear(MO_GP0_IO, 0x00000080);
1611 udelay(50);
1612 cx_set(MO_GP0_IO, 0x00000080);
1613 udelay(1000);
1614 switch (core->dvbdev->frontends.active_fe_id) {
1615 case 1: /* DVB-S/S2 Enabled */
1616 /* tri-state the cx22702 pins */
1617 cx_set(MO_GP0_IO, 0x00000004);
1618 /* Take the cx24116/cx24123 out of reset */
1619 cx_write(MO_SRST_IO, 1);
1620 core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
1621 break;
1622 case 2: /* DVB-T Enabled */
1623 /* Put the cx24116/cx24123 into reset */
1624 cx_write(MO_SRST_IO, 0);
1625 /* enable the cx22702 pins */
1626 cx_clear(MO_GP0_IO, 0x00000004);
1627 core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
1628 break;
1629 }
1630 udelay(1000);
1631 break;
1632
1633 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
1634 /* set RF input to AIR for DVB-T (GPIO 16) */
1635 cx_write(MO_GP2_IO, 0x0101);
1636 break;
1637
1638 default:
1639 err = -ENODEV;
1640 }
1641 return err;
1642}
1643
1644/* CX8802 MPEG -> mini driver - We no longer have the hardware */
1645static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
1646{
1647 struct cx88_core *core = drv->core;
1648 int err = 0;
1649 dprintk( 1, "%s\n", __func__);
1650
1651 switch (core->boardnr) {
1652 case CX88_BOARD_HAUPPAUGE_HVR1300:
1653 /* Do Nothing, leave the cx22702 on the bus. */
1654 break;
1655 case CX88_BOARD_HAUPPAUGE_HVR3000:
1656 case CX88_BOARD_HAUPPAUGE_HVR4000:
1657 break;
1658 default:
1659 err = -ENODEV;
1660 }
1661 return err;
1662}
1663
1664static int cx8802_dvb_probe(struct cx8802_driver *drv)
1665{
1666 struct cx88_core *core = drv->core;
1667 struct cx8802_dev *dev = drv->core->dvbdev;
1668 int err;
1669 struct videobuf_dvb_frontend *fe;
1670 int i;
1671
1672 dprintk( 1, "%s\n", __func__);
1673 dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
1674 core->boardnr,
1675 core->name,
1676 core->pci_bus,
1677 core->pci_slot);
1678
1679 err = -ENODEV;
1680 if (!(core->board.mpeg & CX88_MPEG_DVB))
1681 goto fail_core;
1682
1683 /* If vp3054 isn't enabled, a stub will just return 0 */
1684 err = vp3054_i2c_probe(dev);
1685 if (0 != err)
1686 goto fail_core;
1687
1688 /* dvb stuff */
1689 printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
1690 dev->ts_gen_cntrl = 0x0c;
1691
1692 err = cx8802_alloc_frontends(dev);
1693 if (err)
1694 goto fail_core;
1695
1696 err = -ENODEV;
1697 for (i = 1; i <= core->board.num_frontends; i++) {
1698 fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
1699 if (fe == NULL) {
1700 printk(KERN_ERR "%s() failed to get frontend(%d)\n",
1701 __func__, i);
1702 goto fail_probe;
1703 }
1704 videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
1705 &dev->pci->dev, &dev->slock,
1706 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1707 V4L2_FIELD_TOP,
1708 sizeof(struct cx88_buffer),
1709 dev, NULL);
1710 /* init struct videobuf_dvb */
1711 fe->dvb.name = dev->core->name;
1712 }
1713
1714 err = dvb_register(dev);
1715 if (err)
1716 /* frontends/adapter de-allocated in dvb_register */
1717 printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
1718 core->name, err);
1719 return err;
1720fail_probe:
1721 videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends);
1722fail_core:
1723 return err;
1724}
1725
1726static int cx8802_dvb_remove(struct cx8802_driver *drv)
1727{
1728 struct cx88_core *core = drv->core;
1729 struct cx8802_dev *dev = drv->core->dvbdev;
1730
1731 dprintk( 1, "%s\n", __func__);
1732
1733 videobuf_dvb_unregister_bus(&dev->frontends);
1734
1735 vp3054_i2c_remove(dev);
1736
1737 core->gate_ctrl = NULL;
1738
1739 return 0;
1740}
1741
1742static struct cx8802_driver cx8802_dvb_driver = {
1743 .type_id = CX88_MPEG_DVB,
1744 .hw_access = CX8802_DRVCTL_SHARED,
1745 .probe = cx8802_dvb_probe,
1746 .remove = cx8802_dvb_remove,
1747 .advise_acquire = cx8802_dvb_advise_acquire,
1748 .advise_release = cx8802_dvb_advise_release,
1749};
1750
1751static int __init dvb_init(void)
1752{
1753 printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n",
1754 CX88_VERSION);
1755 return cx8802_register_driver(&cx8802_dvb_driver);
1756}
1757
1758static void __exit dvb_fini(void)
1759{
1760 cx8802_unregister_driver(&cx8802_dvb_driver);
1761}
1762
1763module_init(dvb_init);
1764module_exit(dvb_fini);
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
new file mode 100644
index 00000000000..a1fe0abb6e4
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -0,0 +1,184 @@
1
2/*
3
4 cx88-i2c.c -- all the i2c code is here
5
6 Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
7 & Marcus Metzler (mocm@thp.uni-koeln.de)
8 (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
9 (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
10
11 (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
12 - Multituner support and i2c address binding
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27
28*/
29
30#include <linux/module.h>
31#include <linux/init.h>
32
33#include <asm/io.h>
34
35#include "cx88.h"
36#include <media/v4l2-common.h>
37
38static unsigned int i2c_debug;
39module_param(i2c_debug, int, 0644);
40MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
41
42static unsigned int i2c_scan;
43module_param(i2c_scan, int, 0444);
44MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
45
46static unsigned int i2c_udelay = 5;
47module_param(i2c_udelay, int, 0644);
48MODULE_PARM_DESC(i2c_udelay,"i2c delay at insmod time, in usecs "
49 "(should be 5 or higher). Lower value means higher bus speed.");
50
51#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \
52 printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
53
54/* ----------------------------------------------------------------------- */
55
56static void cx8800_bit_setscl(void *data, int state)
57{
58 struct cx88_core *core = data;
59
60 if (state)
61 core->i2c_state |= 0x02;
62 else
63 core->i2c_state &= ~0x02;
64 cx_write(MO_I2C, core->i2c_state);
65 cx_read(MO_I2C);
66}
67
68static void cx8800_bit_setsda(void *data, int state)
69{
70 struct cx88_core *core = data;
71
72 if (state)
73 core->i2c_state |= 0x01;
74 else
75 core->i2c_state &= ~0x01;
76 cx_write(MO_I2C, core->i2c_state);
77 cx_read(MO_I2C);
78}
79
80static int cx8800_bit_getscl(void *data)
81{
82 struct cx88_core *core = data;
83 u32 state;
84
85 state = cx_read(MO_I2C);
86 return state & 0x02 ? 1 : 0;
87}
88
89static int cx8800_bit_getsda(void *data)
90{
91 struct cx88_core *core = data;
92 u32 state;
93
94 state = cx_read(MO_I2C);
95 return state & 0x01;
96}
97
98/* ----------------------------------------------------------------------- */
99
100static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {
101 .setsda = cx8800_bit_setsda,
102 .setscl = cx8800_bit_setscl,
103 .getsda = cx8800_bit_getsda,
104 .getscl = cx8800_bit_getscl,
105 .udelay = 16,
106 .timeout = 200,
107};
108
109/* ----------------------------------------------------------------------- */
110
111static const char * const i2c_devs[128] = {
112 [ 0x1c >> 1 ] = "lgdt330x",
113 [ 0x86 >> 1 ] = "tda9887/cx22702",
114 [ 0xa0 >> 1 ] = "eeprom",
115 [ 0xc0 >> 1 ] = "tuner (analog)",
116 [ 0xc2 >> 1 ] = "tuner (analog/dvb)",
117 [ 0xc8 >> 1 ] = "xc5000",
118};
119
120static void do_i2c_scan(const char *name, struct i2c_client *c)
121{
122 unsigned char buf;
123 int i,rc;
124
125 for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
126 c->addr = i;
127 rc = i2c_master_recv(c,&buf,0);
128 if (rc < 0)
129 continue;
130 printk("%s: i2c scan: found device @ 0x%x [%s]\n",
131 name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
132 }
133}
134
135/* init + register i2c algo-bit adapter */
136int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
137{
138 /* Prevents usage of invalid delay values */
139 if (i2c_udelay<5)
140 i2c_udelay=5;
141
142 memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
143 sizeof(core->i2c_algo));
144
145
146 core->i2c_adap.dev.parent = &pci->dev;
147 strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name));
148 core->i2c_adap.owner = THIS_MODULE;
149 core->i2c_algo.udelay = i2c_udelay;
150 core->i2c_algo.data = core;
151 i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev);
152 core->i2c_adap.algo_data = &core->i2c_algo;
153 core->i2c_client.adapter = &core->i2c_adap;
154 strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE);
155
156 cx8800_bit_setscl(core,1);
157 cx8800_bit_setsda(core,1);
158
159 core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);
160 if (0 == core->i2c_rc) {
161 static u8 tuner_data[] =
162 { 0x0b, 0xdc, 0x86, 0x52 };
163 static struct i2c_msg tuner_msg =
164 { .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 };
165
166 dprintk(1, "i2c register ok\n");
167 switch( core->boardnr ) {
168 case CX88_BOARD_HAUPPAUGE_HVR1300:
169 case CX88_BOARD_HAUPPAUGE_HVR3000:
170 case CX88_BOARD_HAUPPAUGE_HVR4000:
171 printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n",
172 core->name);
173 i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1);
174 break;
175 default:
176 break;
177 }
178 if (i2c_scan)
179 do_i2c_scan(core->name,&core->i2c_client);
180 } else
181 printk("%s: i2c register FAILED\n", core->name);
182
183 return core->i2c_rc;
184}
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
new file mode 100644
index 00000000000..e614201b5ed
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -0,0 +1,631 @@
1/*
2 *
3 * Device driver for GPIO attached remote control interfaces
4 * on Conexant 2388x based TV/DVB cards.
5 *
6 * Copyright (c) 2003 Pavel Machek
7 * Copyright (c) 2004 Gerd Knorr
8 * Copyright (c) 2004, 2005 Chris Pascoe
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <linux/init.h>
26#include <linux/hrtimer.h>
27#include <linux/pci.h>
28#include <linux/slab.h>
29#include <linux/module.h>
30
31#include "cx88.h"
32#include <media/rc-core.h>
33
34#define MODULE_NAME "cx88xx"
35
36/* ---------------------------------------------------------------------- */
37
38struct cx88_IR {
39 struct cx88_core *core;
40 struct rc_dev *dev;
41
42 int users;
43
44 char name[32];
45 char phys[32];
46
47 /* sample from gpio pin 16 */
48 u32 sampling;
49
50 /* poll external decoder */
51 int polling;
52 struct hrtimer timer;
53 u32 gpio_addr;
54 u32 last_gpio;
55 u32 mask_keycode;
56 u32 mask_keydown;
57 u32 mask_keyup;
58};
59
60static unsigned ir_samplerate = 4;
61module_param(ir_samplerate, uint, 0444);
62MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4");
63
64static int ir_debug;
65module_param(ir_debug, int, 0644); /* debug level [IR] */
66MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
67
68#define ir_dprintk(fmt, arg...) if (ir_debug) \
69 printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
70
71#define dprintk(fmt, arg...) if (ir_debug) \
72 printk(KERN_DEBUG "cx88 IR: " fmt , ##arg)
73
74/* ---------------------------------------------------------------------- */
75
76static void cx88_ir_handle_key(struct cx88_IR *ir)
77{
78 struct cx88_core *core = ir->core;
79 u32 gpio, data, auxgpio;
80
81 /* read gpio value */
82 gpio = cx_read(ir->gpio_addr);
83 switch (core->boardnr) {
84 case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
85 /* This board apparently uses a combination of 2 GPIO
86 to represent the keys. Additionally, the second GPIO
87 can be used for parity.
88
89 Example:
90
91 for key "5"
92 gpio = 0x758, auxgpio = 0xe5 or 0xf5
93 for key "Power"
94 gpio = 0x758, auxgpio = 0xed or 0xfd
95 */
96
97 auxgpio = cx_read(MO_GP1_IO);
98 /* Take out the parity part */
99 gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
100 break;
101 case CX88_BOARD_WINFAST_DTV1000:
102 case CX88_BOARD_WINFAST_DTV1800H:
103 case CX88_BOARD_WINFAST_DTV1800H_XC4000:
104 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
105 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
106 gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
107 auxgpio = gpio;
108 break;
109 default:
110 auxgpio = gpio;
111 }
112 if (ir->polling) {
113 if (ir->last_gpio == auxgpio)
114 return;
115 ir->last_gpio = auxgpio;
116 }
117
118 /* extract data */
119 data = ir_extract_bits(gpio, ir->mask_keycode);
120 ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
121 gpio, data,
122 ir->polling ? "poll" : "irq",
123 (gpio & ir->mask_keydown) ? " down" : "",
124 (gpio & ir->mask_keyup) ? " up" : "");
125
126 if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) {
127 u32 gpio_key = cx_read(MO_GP0_IO);
128
129 data = (data << 4) | ((gpio_key & 0xf0) >> 4);
130
131 rc_keydown(ir->dev, data, 0);
132
133 } else if (ir->mask_keydown) {
134 /* bit set on keydown */
135 if (gpio & ir->mask_keydown)
136 rc_keydown_notimeout(ir->dev, data, 0);
137 else
138 rc_keyup(ir->dev);
139
140 } else if (ir->mask_keyup) {
141 /* bit cleared on keydown */
142 if (0 == (gpio & ir->mask_keyup))
143 rc_keydown_notimeout(ir->dev, data, 0);
144 else
145 rc_keyup(ir->dev);
146
147 } else {
148 /* can't distinguish keydown/up :-/ */
149 rc_keydown_notimeout(ir->dev, data, 0);
150 rc_keyup(ir->dev);
151 }
152}
153
154static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer)
155{
156 unsigned long missed;
157 struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);
158
159 cx88_ir_handle_key(ir);
160 missed = hrtimer_forward_now(&ir->timer,
161 ktime_set(0, ir->polling * 1000000));
162 if (missed > 1)
163 ir_dprintk("Missed ticks %ld\n", missed - 1);
164
165 return HRTIMER_RESTART;
166}
167
168static int __cx88_ir_start(void *priv)
169{
170 struct cx88_core *core = priv;
171 struct cx88_IR *ir;
172
173 if (!core || !core->ir)
174 return -EINVAL;
175
176 ir = core->ir;
177
178 if (ir->polling) {
179 hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
180 ir->timer.function = cx88_ir_work;
181 hrtimer_start(&ir->timer,
182 ktime_set(0, ir->polling * 1000000),
183 HRTIMER_MODE_REL);
184 }
185 if (ir->sampling) {
186 core->pci_irqmask |= PCI_INT_IR_SMPINT;
187 cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */
188 cx_write(MO_DDSCFG_IO, 0x5); /* enable */
189 }
190 return 0;
191}
192
193static void __cx88_ir_stop(void *priv)
194{
195 struct cx88_core *core = priv;
196 struct cx88_IR *ir;
197
198 if (!core || !core->ir)
199 return;
200
201 ir = core->ir;
202 if (ir->sampling) {
203 cx_write(MO_DDSCFG_IO, 0x0);
204 core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
205 }
206
207 if (ir->polling)
208 hrtimer_cancel(&ir->timer);
209}
210
211int cx88_ir_start(struct cx88_core *core)
212{
213 if (core->ir->users)
214 return __cx88_ir_start(core);
215
216 return 0;
217}
218
219void cx88_ir_stop(struct cx88_core *core)
220{
221 if (core->ir->users)
222 __cx88_ir_stop(core);
223}
224
225static int cx88_ir_open(struct rc_dev *rc)
226{
227 struct cx88_core *core = rc->priv;
228
229 core->ir->users++;
230 return __cx88_ir_start(core);
231}
232
233static void cx88_ir_close(struct rc_dev *rc)
234{
235 struct cx88_core *core = rc->priv;
236
237 core->ir->users--;
238 if (!core->ir->users)
239 __cx88_ir_stop(core);
240}
241
242/* ---------------------------------------------------------------------- */
243
244int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
245{
246 struct cx88_IR *ir;
247 struct rc_dev *dev;
248 char *ir_codes = NULL;
249 u64 rc_type = RC_TYPE_OTHER;
250 int err = -ENOMEM;
251 u32 hardware_mask = 0; /* For devices with a hardware mask, when
252 * used with a full-code IR table
253 */
254
255 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
256 dev = rc_allocate_device();
257 if (!ir || !dev)
258 goto err_out_free;
259
260 ir->dev = dev;
261
262 /* detect & configure */
263 switch (core->boardnr) {
264 case CX88_BOARD_DNTV_LIVE_DVB_T:
265 case CX88_BOARD_KWORLD_DVB_T:
266 case CX88_BOARD_KWORLD_DVB_T_CX22702:
267 ir_codes = RC_MAP_DNTV_LIVE_DVB_T;
268 ir->gpio_addr = MO_GP1_IO;
269 ir->mask_keycode = 0x1f;
270 ir->mask_keyup = 0x60;
271 ir->polling = 50; /* ms */
272 break;
273 case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
274 ir_codes = RC_MAP_CINERGY_1400;
275 ir->sampling = 0xeb04; /* address */
276 break;
277 case CX88_BOARD_HAUPPAUGE:
278 case CX88_BOARD_HAUPPAUGE_DVB_T1:
279 case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
280 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
281 case CX88_BOARD_HAUPPAUGE_HVR1100:
282 case CX88_BOARD_HAUPPAUGE_HVR3000:
283 case CX88_BOARD_HAUPPAUGE_HVR4000:
284 case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
285 case CX88_BOARD_PCHDTV_HD3000:
286 case CX88_BOARD_PCHDTV_HD5500:
287 case CX88_BOARD_HAUPPAUGE_IRONLY:
288 ir_codes = RC_MAP_HAUPPAUGE;
289 ir->sampling = 1;
290 break;
291 case CX88_BOARD_WINFAST_DTV2000H:
292 case CX88_BOARD_WINFAST_DTV2000H_J:
293 case CX88_BOARD_WINFAST_DTV1800H:
294 case CX88_BOARD_WINFAST_DTV1800H_XC4000:
295 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
296 ir_codes = RC_MAP_WINFAST;
297 ir->gpio_addr = MO_GP0_IO;
298 ir->mask_keycode = 0x8f8;
299 ir->mask_keyup = 0x100;
300 ir->polling = 50; /* ms */
301 break;
302 case CX88_BOARD_WINFAST2000XP_EXPERT:
303 case CX88_BOARD_WINFAST_DTV1000:
304 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
305 ir_codes = RC_MAP_WINFAST;
306 ir->gpio_addr = MO_GP0_IO;
307 ir->mask_keycode = 0x8f8;
308 ir->mask_keyup = 0x100;
309 ir->polling = 1; /* ms */
310 break;
311 case CX88_BOARD_IODATA_GVBCTV7E:
312 ir_codes = RC_MAP_IODATA_BCTV7E;
313 ir->gpio_addr = MO_GP0_IO;
314 ir->mask_keycode = 0xfd;
315 ir->mask_keydown = 0x02;
316 ir->polling = 5; /* ms */
317 break;
318 case CX88_BOARD_PROLINK_PLAYTVPVR:
319 case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
320 /*
321 * It seems that this hardware is paired with NEC extended
322 * address 0x866b. So, unfortunately, its usage with other
323 * IR's with different address won't work. Still, there are
324 * other IR's from the same manufacturer that works, like the
325 * 002-T mini RC, provided with newer PV hardware
326 */
327 ir_codes = RC_MAP_PIXELVIEW_MK12;
328 ir->gpio_addr = MO_GP1_IO;
329 ir->mask_keyup = 0x80;
330 ir->polling = 10; /* ms */
331 hardware_mask = 0x3f; /* Hardware returns only 6 bits from command part */
332 break;
333 case CX88_BOARD_PROLINK_PV_8000GT:
334 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
335 ir_codes = RC_MAP_PIXELVIEW_NEW;
336 ir->gpio_addr = MO_GP1_IO;
337 ir->mask_keycode = 0x3f;
338 ir->mask_keyup = 0x80;
339 ir->polling = 1; /* ms */
340 break;
341 case CX88_BOARD_KWORLD_LTV883:
342 ir_codes = RC_MAP_PIXELVIEW;
343 ir->gpio_addr = MO_GP1_IO;
344 ir->mask_keycode = 0x1f;
345 ir->mask_keyup = 0x60;
346 ir->polling = 1; /* ms */
347 break;
348 case CX88_BOARD_ADSTECH_DVB_T_PCI:
349 ir_codes = RC_MAP_ADSTECH_DVB_T_PCI;
350 ir->gpio_addr = MO_GP1_IO;
351 ir->mask_keycode = 0xbf;
352 ir->mask_keyup = 0x40;
353 ir->polling = 50; /* ms */
354 break;
355 case CX88_BOARD_MSI_TVANYWHERE_MASTER:
356 ir_codes = RC_MAP_MSI_TVANYWHERE;
357 ir->gpio_addr = MO_GP1_IO;
358 ir->mask_keycode = 0x1f;
359 ir->mask_keyup = 0x40;
360 ir->polling = 1; /* ms */
361 break;
362 case CX88_BOARD_AVERTV_303:
363 case CX88_BOARD_AVERTV_STUDIO_303:
364 ir_codes = RC_MAP_AVERTV_303;
365 ir->gpio_addr = MO_GP2_IO;
366 ir->mask_keycode = 0xfb;
367 ir->mask_keydown = 0x02;
368 ir->polling = 50; /* ms */
369 break;
370 case CX88_BOARD_OMICOM_SS4_PCI:
371 case CX88_BOARD_SATTRADE_ST4200:
372 case CX88_BOARD_TBS_8920:
373 case CX88_BOARD_TBS_8910:
374 case CX88_BOARD_PROF_7300:
375 case CX88_BOARD_PROF_7301:
376 case CX88_BOARD_PROF_6200:
377 ir_codes = RC_MAP_TBS_NEC;
378 ir->sampling = 0xff00; /* address */
379 break;
380 case CX88_BOARD_TEVII_S464:
381 case CX88_BOARD_TEVII_S460:
382 case CX88_BOARD_TEVII_S420:
383 ir_codes = RC_MAP_TEVII_NEC;
384 ir->sampling = 0xff00; /* address */
385 break;
386 case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
387 ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO;
388 ir->sampling = 0xff00; /* address */
389 break;
390 case CX88_BOARD_NORWOOD_MICRO:
391 ir_codes = RC_MAP_NORWOOD;
392 ir->gpio_addr = MO_GP1_IO;
393 ir->mask_keycode = 0x0e;
394 ir->mask_keyup = 0x80;
395 ir->polling = 50; /* ms */
396 break;
397 case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
398 ir_codes = RC_MAP_NPGTECH;
399 ir->gpio_addr = MO_GP0_IO;
400 ir->mask_keycode = 0xfa;
401 ir->polling = 50; /* ms */
402 break;
403 case CX88_BOARD_PINNACLE_PCTV_HD_800i:
404 ir_codes = RC_MAP_PINNACLE_PCTV_HD;
405 ir->sampling = 1;
406 break;
407 case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
408 ir_codes = RC_MAP_POWERCOLOR_REAL_ANGEL;
409 ir->gpio_addr = MO_GP2_IO;
410 ir->mask_keycode = 0x7e;
411 ir->polling = 100; /* ms */
412 break;
413 case CX88_BOARD_TWINHAN_VP1027_DVBS:
414 ir_codes = RC_MAP_TWINHAN_VP1027_DVBS;
415 rc_type = RC_TYPE_NEC;
416 ir->sampling = 0xff00; /* address */
417 break;
418 }
419
420 if (!ir_codes) {
421 err = -ENODEV;
422 goto err_out_free;
423 }
424
425 /*
426 * The usage of mask_keycode were very convenient, due to several
427 * reasons. Among others, the scancode tables were using the scancode
428 * as the index elements. So, the less bits it was used, the smaller
429 * the table were stored. After the input changes, the better is to use
430 * the full scancodes, since it allows replacing the IR remote by
431 * another one. Unfortunately, there are still some hardware, like
432 * Pixelview Ultra Pro, where only part of the scancode is sent via
433 * GPIO. So, there's no way to get the full scancode. Due to that,
434 * hardware_mask were introduced here: it represents those hardware
435 * that has such limits.
436 */
437 if (hardware_mask && !ir->mask_keycode)
438 ir->mask_keycode = hardware_mask;
439
440 /* init input device */
441 snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
442 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
443
444 dev->input_name = ir->name;
445 dev->input_phys = ir->phys;
446 dev->input_id.bustype = BUS_PCI;
447 dev->input_id.version = 1;
448 if (pci->subsystem_vendor) {
449 dev->input_id.vendor = pci->subsystem_vendor;
450 dev->input_id.product = pci->subsystem_device;
451 } else {
452 dev->input_id.vendor = pci->vendor;
453 dev->input_id.product = pci->device;
454 }
455 dev->dev.parent = &pci->dev;
456 dev->map_name = ir_codes;
457 dev->driver_name = MODULE_NAME;
458 dev->priv = core;
459 dev->open = cx88_ir_open;
460 dev->close = cx88_ir_close;
461 dev->scanmask = hardware_mask;
462
463 if (ir->sampling) {
464 dev->driver_type = RC_DRIVER_IR_RAW;
465 dev->timeout = 10 * 1000 * 1000; /* 10 ms */
466 } else {
467 dev->driver_type = RC_DRIVER_SCANCODE;
468 dev->allowed_protos = rc_type;
469 }
470
471 ir->core = core;
472 core->ir = ir;
473
474 /* all done */
475 err = rc_register_device(dev);
476 if (err)
477 goto err_out_free;
478
479 return 0;
480
481err_out_free:
482 rc_free_device(dev);
483 core->ir = NULL;
484 kfree(ir);
485 return err;
486}
487
488int cx88_ir_fini(struct cx88_core *core)
489{
490 struct cx88_IR *ir = core->ir;
491
492 /* skip detach on non attached boards */
493 if (NULL == ir)
494 return 0;
495
496 cx88_ir_stop(core);
497 rc_unregister_device(ir->dev);
498 kfree(ir);
499
500 /* done */
501 core->ir = NULL;
502 return 0;
503}
504
505/* ---------------------------------------------------------------------- */
506
507void cx88_ir_irq(struct cx88_core *core)
508{
509 struct cx88_IR *ir = core->ir;
510 u32 samples;
511 unsigned todo, bits;
512 struct ir_raw_event ev;
513
514 if (!ir || !ir->sampling)
515 return;
516
517 /*
518 * Samples are stored in a 32 bit register, oldest sample in
519 * the msb. A set bit represents space and an unset bit
520 * represents a pulse.
521 */
522 samples = cx_read(MO_SAMPLE_IO);
523
524 if (samples == 0xff && ir->dev->idle)
525 return;
526
527 init_ir_raw_event(&ev);
528 for (todo = 32; todo > 0; todo -= bits) {
529 ev.pulse = samples & 0x80000000 ? false : true;
530 bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
531 ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
532 ir_raw_event_store_with_filter(ir->dev, &ev);
533 samples <<= bits;
534 }
535 ir_raw_event_handle(ir->dev);
536}
537
538static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
539{
540 int flags, code;
541
542 /* poll IR chip */
543 flags = i2c_smbus_read_byte_data(ir->c, 0x10);
544 if (flags < 0) {
545 dprintk("read error\n");
546 return 0;
547 }
548 /* key pressed ? */
549 if (0 == (flags & 0x80))
550 return 0;
551
552 /* read actual key code */
553 code = i2c_smbus_read_byte_data(ir->c, 0x00);
554 if (code < 0) {
555 dprintk("read error\n");
556 return 0;
557 }
558
559 dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
560 code & 0xff, flags & 0xff);
561
562 *ir_key = code & 0xff;
563 *ir_raw = code;
564 return 1;
565}
566
567void cx88_i2c_init_ir(struct cx88_core *core)
568{
569 struct i2c_board_info info;
570 const unsigned short default_addr_list[] = {
571 0x18, 0x6b, 0x71,
572 I2C_CLIENT_END
573 };
574 const unsigned short pvr2000_addr_list[] = {
575 0x18, 0x1a,
576 I2C_CLIENT_END
577 };
578 const unsigned short *addr_list = default_addr_list;
579 const unsigned short *addrp;
580 /* Instantiate the IR receiver device, if present */
581 if (0 != core->i2c_rc)
582 return;
583
584 memset(&info, 0, sizeof(struct i2c_board_info));
585 strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
586
587 switch (core->boardnr) {
588 case CX88_BOARD_LEADTEK_PVR2000:
589 addr_list = pvr2000_addr_list;
590 core->init_data.name = "cx88 Leadtek PVR 2000 remote";
591 core->init_data.type = RC_TYPE_UNKNOWN;
592 core->init_data.get_key = get_key_pvr2000;
593 core->init_data.ir_codes = RC_MAP_EMPTY;
594 break;
595 }
596
597 /*
598 * We can't call i2c_new_probed_device() because it uses
599 * quick writes for probing and at least some RC receiver
600 * devices only reply to reads.
601 * Also, Hauppauge XVR needs to be specified, as address 0x71
602 * conflicts with another remote type used with saa7134
603 */
604 for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
605 info.platform_data = NULL;
606 memset(&core->init_data, 0, sizeof(core->init_data));
607
608 if (*addrp == 0x71) {
609 /* Hauppauge XVR */
610 core->init_data.name = "cx88 Hauppauge XVR remote";
611 core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
612 core->init_data.type = RC_TYPE_RC5;
613 core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
614
615 info.platform_data = &core->init_data;
616 }
617 if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
618 I2C_SMBUS_READ, 0,
619 I2C_SMBUS_QUICK, NULL) >= 0) {
620 info.addr = *addrp;
621 i2c_new_device(&core->i2c_adap, &info);
622 break;
623 }
624 }
625}
626
627/* ---------------------------------------------------------------------- */
628
629MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
630MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
631MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
new file mode 100644
index 00000000000..cd5386ee210
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -0,0 +1,929 @@
1/*
2 *
3 * Support for the mpeg transport stream transfers
4 * PCI function #2 of the cx2388x.
5 *
6 * (c) 2004 Jelle Foks <jelle@foks.us>
7 * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
8 * (c) 2004 Gerd Knorr <kraxel@bytesex.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/module.h>
26#include <linux/slab.h>
27#include <linux/init.h>
28#include <linux/device.h>
29#include <linux/dma-mapping.h>
30#include <linux/interrupt.h>
31#include <asm/delay.h>
32
33#include "cx88.h"
34
35/* ------------------------------------------------------------------ */
36
37MODULE_DESCRIPTION("mpeg driver for cx2388x based TV cards");
38MODULE_AUTHOR("Jelle Foks <jelle@foks.us>");
39MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
40MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
41MODULE_LICENSE("GPL");
42MODULE_VERSION(CX88_VERSION);
43
44static unsigned int debug;
45module_param(debug,int,0644);
46MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
47
48#define dprintk(level,fmt, arg...) if (debug >= level) \
49 printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
50
51#define mpeg_dbg(level,fmt, arg...) if (debug >= level) \
52 printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
53
54#if defined(CONFIG_MODULES) && defined(MODULE)
55static void request_module_async(struct work_struct *work)
56{
57 struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk);
58
59 if (dev->core->board.mpeg & CX88_MPEG_DVB)
60 request_module("cx88-dvb");
61 if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD)
62 request_module("cx88-blackbird");
63}
64
65static void request_modules(struct cx8802_dev *dev)
66{
67 INIT_WORK(&dev->request_module_wk, request_module_async);
68 schedule_work(&dev->request_module_wk);
69}
70
71static void flush_request_modules(struct cx8802_dev *dev)
72{
73 flush_work_sync(&dev->request_module_wk);
74}
75#else
76#define request_modules(dev)
77#define flush_request_modules(dev)
78#endif /* CONFIG_MODULES */
79
80
81static LIST_HEAD(cx8802_devlist);
82static DEFINE_MUTEX(cx8802_mutex);
83/* ------------------------------------------------------------------ */
84
85static int cx8802_start_dma(struct cx8802_dev *dev,
86 struct cx88_dmaqueue *q,
87 struct cx88_buffer *buf)
88{
89 struct cx88_core *core = dev->core;
90
91 dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
92 buf->vb.width, buf->vb.height, buf->vb.field);
93
94 /* setup fifo + format */
95 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
96 dev->ts_packet_size, buf->risc.dma);
97
98 /* write TS length to chip */
99 cx_write(MO_TS_LNGTH, buf->vb.width);
100
101 /* FIXME: this needs a review.
102 * also: move to cx88-blackbird + cx88-dvb source files? */
103
104 dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
105
106 if ( (core->active_type_id == CX88_MPEG_DVB) &&
107 (core->board.mpeg & CX88_MPEG_DVB) ) {
108
109 dprintk( 1, "cx8802_start_dma doing .dvb\n");
110 /* negedge driven & software reset */
111 cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
112 udelay(100);
113 cx_write(MO_PINMUX_IO, 0x00);
114 cx_write(TS_HW_SOP_CNTRL, 0x47<<16|188<<4|0x01);
115 switch (core->boardnr) {
116 case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
117 case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
118 case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
119 case CX88_BOARD_PCHDTV_HD5500:
120 cx_write(TS_SOP_STAT, 1<<13);
121 break;
122 case CX88_BOARD_SAMSUNG_SMT_7020:
123 cx_write(TS_SOP_STAT, 0x00);
124 break;
125 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
126 case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
127 cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
128 udelay(100);
129 break;
130 case CX88_BOARD_HAUPPAUGE_HVR1300:
131 /* Enable MPEG parallel IO and video signal pins */
132 cx_write(MO_PINMUX_IO, 0x88);
133 cx_write(TS_SOP_STAT, 0);
134 cx_write(TS_VALERR_CNTRL, 0);
135 break;
136 case CX88_BOARD_PINNACLE_PCTV_HD_800i:
137 /* Enable MPEG parallel IO and video signal pins */
138 cx_write(MO_PINMUX_IO, 0x88);
139 cx_write(TS_HW_SOP_CNTRL, (0x47 << 16) | (188 << 4));
140 dev->ts_gen_cntrl = 5;
141 cx_write(TS_SOP_STAT, 0);
142 cx_write(TS_VALERR_CNTRL, 0);
143 udelay(100);
144 break;
145 default:
146 cx_write(TS_SOP_STAT, 0x00);
147 break;
148 }
149 cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
150 udelay(100);
151 } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
152 (core->board.mpeg & CX88_MPEG_BLACKBIRD) ) {
153 dprintk( 1, "cx8802_start_dma doing .blackbird\n");
154 cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
155
156 cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
157 udelay(100);
158
159 cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
160 cx_write(TS_VALERR_CNTRL, 0x2000);
161
162 cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
163 udelay(100);
164 } else {
165 printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
166 core->board.mpeg );
167 return -EINVAL;
168 }
169
170 /* reset counter */
171 cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
172 q->count = 1;
173
174 /* enable irqs */
175 dprintk( 1, "setting the interrupt mask\n" );
176 cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT);
177 cx_set(MO_TS_INTMSK, 0x1f0011);
178
179 /* start dma */
180 cx_set(MO_DEV_CNTRL2, (1<<5));
181 cx_set(MO_TS_DMACNTRL, 0x11);
182 return 0;
183}
184
185static int cx8802_stop_dma(struct cx8802_dev *dev)
186{
187 struct cx88_core *core = dev->core;
188 dprintk( 1, "cx8802_stop_dma\n" );
189
190 /* stop dma */
191 cx_clear(MO_TS_DMACNTRL, 0x11);
192
193 /* disable irqs */
194 cx_clear(MO_PCI_INTMSK, PCI_INT_TSINT);
195 cx_clear(MO_TS_INTMSK, 0x1f0011);
196
197 /* Reset the controller */
198 cx_write(TS_GEN_CNTRL, 0xcd);
199 return 0;
200}
201
202static int cx8802_restart_queue(struct cx8802_dev *dev,
203 struct cx88_dmaqueue *q)
204{
205 struct cx88_buffer *buf;
206
207 dprintk( 1, "cx8802_restart_queue\n" );
208 if (list_empty(&q->active))
209 {
210 struct cx88_buffer *prev;
211 prev = NULL;
212
213 dprintk(1, "cx8802_restart_queue: queue is empty\n" );
214
215 for (;;) {
216 if (list_empty(&q->queued))
217 return 0;
218 buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
219 if (NULL == prev) {
220 list_del(&buf->vb.queue);
221 list_add_tail(&buf->vb.queue,&q->active);
222 cx8802_start_dma(dev, q, buf);
223 buf->vb.state = VIDEOBUF_ACTIVE;
224 buf->count = q->count++;
225 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
226 dprintk(1,"[%p/%d] restart_queue - first active\n",
227 buf,buf->vb.i);
228
229 } else if (prev->vb.width == buf->vb.width &&
230 prev->vb.height == buf->vb.height &&
231 prev->fmt == buf->fmt) {
232 list_del(&buf->vb.queue);
233 list_add_tail(&buf->vb.queue,&q->active);
234 buf->vb.state = VIDEOBUF_ACTIVE;
235 buf->count = q->count++;
236 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
237 dprintk(1,"[%p/%d] restart_queue - move to active\n",
238 buf,buf->vb.i);
239 } else {
240 return 0;
241 }
242 prev = buf;
243 }
244 return 0;
245 }
246
247 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
248 dprintk(2,"restart_queue [%p/%d]: restart dma\n",
249 buf, buf->vb.i);
250 cx8802_start_dma(dev, q, buf);
251 list_for_each_entry(buf, &q->active, vb.queue)
252 buf->count = q->count++;
253 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
254 return 0;
255}
256
257/* ------------------------------------------------------------------ */
258
259int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
260 struct cx88_buffer *buf, enum v4l2_field field)
261{
262 int size = dev->ts_packet_size * dev->ts_packet_count;
263 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
264 int rc;
265
266 dprintk(1, "%s: %p\n", __func__, buf);
267 if (0 != buf->vb.baddr && buf->vb.bsize < size)
268 return -EINVAL;
269
270 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
271 buf->vb.width = dev->ts_packet_size;
272 buf->vb.height = dev->ts_packet_count;
273 buf->vb.size = size;
274 buf->vb.field = field /*V4L2_FIELD_TOP*/;
275
276 if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
277 goto fail;
278 cx88_risc_databuffer(dev->pci, &buf->risc,
279 dma->sglist,
280 buf->vb.width, buf->vb.height, 0);
281 }
282 buf->vb.state = VIDEOBUF_PREPARED;
283 return 0;
284
285 fail:
286 cx88_free_buffer(q,buf);
287 return rc;
288}
289
290void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
291{
292 struct cx88_buffer *prev;
293 struct cx88_dmaqueue *cx88q = &dev->mpegq;
294
295 dprintk( 1, "cx8802_buf_queue\n" );
296 /* add jump to stopper */
297 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
298 buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
299
300 if (list_empty(&cx88q->active)) {
301 dprintk( 1, "queue is empty - first active\n" );
302 list_add_tail(&buf->vb.queue,&cx88q->active);
303 cx8802_start_dma(dev, cx88q, buf);
304 buf->vb.state = VIDEOBUF_ACTIVE;
305 buf->count = cx88q->count++;
306 mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
307 dprintk(1,"[%p/%d] %s - first active\n",
308 buf, buf->vb.i, __func__);
309
310 } else {
311 dprintk( 1, "queue is not empty - append to active\n" );
312 prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
313 list_add_tail(&buf->vb.queue,&cx88q->active);
314 buf->vb.state = VIDEOBUF_ACTIVE;
315 buf->count = cx88q->count++;
316 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
317 dprintk( 1, "[%p/%d] %s - append to active\n",
318 buf, buf->vb.i, __func__);
319 }
320}
321
322/* ----------------------------------------------------------- */
323
324static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart)
325{
326 struct cx88_dmaqueue *q = &dev->mpegq;
327 struct cx88_buffer *buf;
328 unsigned long flags;
329
330 spin_lock_irqsave(&dev->slock,flags);
331 while (!list_empty(&q->active)) {
332 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
333 list_del(&buf->vb.queue);
334 buf->vb.state = VIDEOBUF_ERROR;
335 wake_up(&buf->vb.done);
336 dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
337 buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
338 }
339 if (restart)
340 {
341 dprintk(1, "restarting queue\n" );
342 cx8802_restart_queue(dev,q);
343 }
344 spin_unlock_irqrestore(&dev->slock,flags);
345}
346
347void cx8802_cancel_buffers(struct cx8802_dev *dev)
348{
349 struct cx88_dmaqueue *q = &dev->mpegq;
350
351 dprintk( 1, "cx8802_cancel_buffers" );
352 del_timer_sync(&q->timeout);
353 cx8802_stop_dma(dev);
354 do_cancel_buffers(dev,"cancel",0);
355}
356
357static void cx8802_timeout(unsigned long data)
358{
359 struct cx8802_dev *dev = (struct cx8802_dev*)data;
360
361 dprintk(1, "%s\n",__func__);
362
363 if (debug)
364 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
365 cx8802_stop_dma(dev);
366 do_cancel_buffers(dev,"timeout",1);
367}
368
369static const char * cx88_mpeg_irqs[32] = {
370 "ts_risci1", NULL, NULL, NULL,
371 "ts_risci2", NULL, NULL, NULL,
372 "ts_oflow", NULL, NULL, NULL,
373 "ts_sync", NULL, NULL, NULL,
374 "opc_err", "par_err", "rip_err", "pci_abort",
375 "ts_err?",
376};
377
378static void cx8802_mpeg_irq(struct cx8802_dev *dev)
379{
380 struct cx88_core *core = dev->core;
381 u32 status, mask, count;
382
383 dprintk( 1, "cx8802_mpeg_irq\n" );
384 status = cx_read(MO_TS_INTSTAT);
385 mask = cx_read(MO_TS_INTMSK);
386 if (0 == (status & mask))
387 return;
388
389 cx_write(MO_TS_INTSTAT, status);
390
391 if (debug || (status & mask & ~0xff))
392 cx88_print_irqbits(core->name, "irq mpeg ",
393 cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs),
394 status, mask);
395
396 /* risc op code error */
397 if (status & (1 << 16)) {
398 printk(KERN_WARNING "%s: mpeg risc op code error\n",core->name);
399 cx_clear(MO_TS_DMACNTRL, 0x11);
400 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
401 }
402
403 /* risc1 y */
404 if (status & 0x01) {
405 dprintk( 1, "wake up\n" );
406 spin_lock(&dev->slock);
407 count = cx_read(MO_TS_GPCNT);
408 cx88_wakeup(dev->core, &dev->mpegq, count);
409 spin_unlock(&dev->slock);
410 }
411
412 /* risc2 y */
413 if (status & 0x10) {
414 spin_lock(&dev->slock);
415 cx8802_restart_queue(dev,&dev->mpegq);
416 spin_unlock(&dev->slock);
417 }
418
419 /* other general errors */
420 if (status & 0x1f0100) {
421 dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
422 spin_lock(&dev->slock);
423 cx8802_stop_dma(dev);
424 cx8802_restart_queue(dev,&dev->mpegq);
425 spin_unlock(&dev->slock);
426 }
427}
428
429#define MAX_IRQ_LOOP 10
430
431static irqreturn_t cx8802_irq(int irq, void *dev_id)
432{
433 struct cx8802_dev *dev = dev_id;
434 struct cx88_core *core = dev->core;
435 u32 status;
436 int loop, handled = 0;
437
438 for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
439 status = cx_read(MO_PCI_INTSTAT) &
440 (core->pci_irqmask | PCI_INT_TSINT);
441 if (0 == status)
442 goto out;
443 dprintk( 1, "cx8802_irq\n" );
444 dprintk( 1, " loop: %d/%d\n", loop, MAX_IRQ_LOOP );
445 dprintk( 1, " status: %d\n", status );
446 handled = 1;
447 cx_write(MO_PCI_INTSTAT, status);
448
449 if (status & core->pci_irqmask)
450 cx88_core_irq(core,status);
451 if (status & PCI_INT_TSINT)
452 cx8802_mpeg_irq(dev);
453 };
454 if (MAX_IRQ_LOOP == loop) {
455 dprintk( 0, "clearing mask\n" );
456 printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
457 core->name);
458 cx_write(MO_PCI_INTMSK,0);
459 }
460
461 out:
462 return IRQ_RETVAL(handled);
463}
464
465static int cx8802_init_common(struct cx8802_dev *dev)
466{
467 struct cx88_core *core = dev->core;
468 int err;
469
470 /* pci init */
471 if (pci_enable_device(dev->pci))
472 return -EIO;
473 pci_set_master(dev->pci);
474 if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) {
475 printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
476 return -EIO;
477 }
478
479 dev->pci_rev = dev->pci->revision;
480 pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat);
481 printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, "
482 "latency: %d, mmio: 0x%llx\n", dev->core->name,
483 pci_name(dev->pci), dev->pci_rev, dev->pci->irq,
484 dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0));
485
486 /* initialize driver struct */
487 spin_lock_init(&dev->slock);
488
489 /* init dma queue */
490 INIT_LIST_HEAD(&dev->mpegq.active);
491 INIT_LIST_HEAD(&dev->mpegq.queued);
492 dev->mpegq.timeout.function = cx8802_timeout;
493 dev->mpegq.timeout.data = (unsigned long)dev;
494 init_timer(&dev->mpegq.timeout);
495 cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
496 MO_TS_DMACNTRL,0x11,0x00);
497
498 /* get irq */
499 err = request_irq(dev->pci->irq, cx8802_irq,
500 IRQF_SHARED | IRQF_DISABLED, dev->core->name, dev);
501 if (err < 0) {
502 printk(KERN_ERR "%s: can't get IRQ %d\n",
503 dev->core->name, dev->pci->irq);
504 return err;
505 }
506 cx_set(MO_PCI_INTMSK, core->pci_irqmask);
507
508 /* everything worked */
509 pci_set_drvdata(dev->pci,dev);
510 return 0;
511}
512
513static void cx8802_fini_common(struct cx8802_dev *dev)
514{
515 dprintk( 2, "cx8802_fini_common\n" );
516 cx8802_stop_dma(dev);
517 pci_disable_device(dev->pci);
518
519 /* unregister stuff */
520 free_irq(dev->pci->irq, dev);
521 pci_set_drvdata(dev->pci, NULL);
522
523 /* free memory */
524 btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
525}
526
527/* ----------------------------------------------------------- */
528
529static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
530{
531 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
532 struct cx88_core *core = dev->core;
533
534 /* stop mpeg dma */
535 spin_lock(&dev->slock);
536 if (!list_empty(&dev->mpegq.active)) {
537 dprintk( 2, "suspend\n" );
538 printk("%s: suspend mpeg\n", core->name);
539 cx8802_stop_dma(dev);
540 del_timer(&dev->mpegq.timeout);
541 }
542 spin_unlock(&dev->slock);
543
544 /* FIXME -- shutdown device */
545 cx88_shutdown(dev->core);
546
547 pci_save_state(pci_dev);
548 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
549 pci_disable_device(pci_dev);
550 dev->state.disabled = 1;
551 }
552 return 0;
553}
554
555static int cx8802_resume_common(struct pci_dev *pci_dev)
556{
557 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
558 struct cx88_core *core = dev->core;
559 int err;
560
561 if (dev->state.disabled) {
562 err=pci_enable_device(pci_dev);
563 if (err) {
564 printk(KERN_ERR "%s: can't enable device\n",
565 dev->core->name);
566 return err;
567 }
568 dev->state.disabled = 0;
569 }
570 err=pci_set_power_state(pci_dev, PCI_D0);
571 if (err) {
572 printk(KERN_ERR "%s: can't enable device\n",
573 dev->core->name);
574 pci_disable_device(pci_dev);
575 dev->state.disabled = 1;
576
577 return err;
578 }
579 pci_restore_state(pci_dev);
580
581 /* FIXME: re-initialize hardware */
582 cx88_reset(dev->core);
583
584 /* restart video+vbi capture */
585 spin_lock(&dev->slock);
586 if (!list_empty(&dev->mpegq.active)) {
587 printk("%s: resume mpeg\n", core->name);
588 cx8802_restart_queue(dev,&dev->mpegq);
589 }
590 spin_unlock(&dev->slock);
591
592 return 0;
593}
594
595struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
596{
597 struct cx8802_driver *d;
598
599 list_for_each_entry(d, &dev->drvlist, drvlist)
600 if (d->type_id == btype)
601 return d;
602
603 return NULL;
604}
605
606/* Driver asked for hardware access. */
607static int cx8802_request_acquire(struct cx8802_driver *drv)
608{
609 struct cx88_core *core = drv->core;
610 unsigned int i;
611
612 /* Fail a request for hardware if the device is busy. */
613 if (core->active_type_id != CX88_BOARD_NONE &&
614 core->active_type_id != drv->type_id)
615 return -EBUSY;
616
617 if (drv->type_id == CX88_MPEG_DVB) {
618 /* When switching to DVB, always set the input to the tuner */
619 core->last_analog_input = core->input;
620 core->input = 0;
621 for (i = 0;
622 i < (sizeof(core->board.input) / sizeof(struct cx88_input));
623 i++) {
624 if (core->board.input[i].type == CX88_VMUX_DVB) {
625 core->input = i;
626 break;
627 }
628 }
629 }
630
631 if (drv->advise_acquire)
632 {
633 core->active_ref++;
634 if (core->active_type_id == CX88_BOARD_NONE) {
635 core->active_type_id = drv->type_id;
636 drv->advise_acquire(drv);
637 }
638
639 mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
640 }
641
642 return 0;
643}
644
645/* Driver asked to release hardware. */
646static int cx8802_request_release(struct cx8802_driver *drv)
647{
648 struct cx88_core *core = drv->core;
649
650 if (drv->advise_release && --core->active_ref == 0)
651 {
652 if (drv->type_id == CX88_MPEG_DVB) {
653 /* If the DVB driver is releasing, reset the input
654 state to the last configured analog input */
655 core->input = core->last_analog_input;
656 }
657
658 drv->advise_release(drv);
659 core->active_type_id = CX88_BOARD_NONE;
660 mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
661 }
662
663 return 0;
664}
665
666static int cx8802_check_driver(struct cx8802_driver *drv)
667{
668 if (drv == NULL)
669 return -ENODEV;
670
671 if ((drv->type_id != CX88_MPEG_DVB) &&
672 (drv->type_id != CX88_MPEG_BLACKBIRD))
673 return -EINVAL;
674
675 if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
676 (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
677 return -EINVAL;
678
679 if ((drv->probe == NULL) ||
680 (drv->remove == NULL) ||
681 (drv->advise_acquire == NULL) ||
682 (drv->advise_release == NULL))
683 return -EINVAL;
684
685 return 0;
686}
687
688int cx8802_register_driver(struct cx8802_driver *drv)
689{
690 struct cx8802_dev *dev;
691 struct cx8802_driver *driver;
692 int err, i = 0;
693
694 printk(KERN_INFO
695 "cx88/2: registering cx8802 driver, type: %s access: %s\n",
696 drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
697 drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
698
699 if ((err = cx8802_check_driver(drv)) != 0) {
700 printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n");
701 return err;
702 }
703
704 mutex_lock(&cx8802_mutex);
705
706 list_for_each_entry(dev, &cx8802_devlist, devlist) {
707 printk(KERN_INFO
708 "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
709 dev->core->name, dev->pci->subsystem_vendor,
710 dev->pci->subsystem_device, dev->core->board.name,
711 dev->core->boardnr);
712
713 /* Bring up a new struct for each driver instance */
714 driver = kzalloc(sizeof(*drv),GFP_KERNEL);
715 if (driver == NULL) {
716 err = -ENOMEM;
717 goto out;
718 }
719
720 /* Snapshot of the driver registration data */
721 drv->core = dev->core;
722 drv->suspend = cx8802_suspend_common;
723 drv->resume = cx8802_resume_common;
724 drv->request_acquire = cx8802_request_acquire;
725 drv->request_release = cx8802_request_release;
726 memcpy(driver, drv, sizeof(*driver));
727
728 mutex_lock(&drv->core->lock);
729 err = drv->probe(driver);
730 if (err == 0) {
731 i++;
732 list_add_tail(&driver->drvlist, &dev->drvlist);
733 } else {
734 printk(KERN_ERR
735 "%s/2: cx8802 probe failed, err = %d\n",
736 dev->core->name, err);
737 }
738 mutex_unlock(&drv->core->lock);
739 }
740
741 err = i ? 0 : -ENODEV;
742out:
743 mutex_unlock(&cx8802_mutex);
744 return err;
745}
746
747int cx8802_unregister_driver(struct cx8802_driver *drv)
748{
749 struct cx8802_dev *dev;
750 struct cx8802_driver *d, *dtmp;
751 int err = 0;
752
753 printk(KERN_INFO
754 "cx88/2: unregistering cx8802 driver, type: %s access: %s\n",
755 drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
756 drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
757
758 mutex_lock(&cx8802_mutex);
759
760 list_for_each_entry(dev, &cx8802_devlist, devlist) {
761 printk(KERN_INFO
762 "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
763 dev->core->name, dev->pci->subsystem_vendor,
764 dev->pci->subsystem_device, dev->core->board.name,
765 dev->core->boardnr);
766
767 mutex_lock(&dev->core->lock);
768
769 list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {
770 /* only unregister the correct driver type */
771 if (d->type_id != drv->type_id)
772 continue;
773
774 err = d->remove(d);
775 if (err == 0) {
776 list_del(&d->drvlist);
777 kfree(d);
778 } else
779 printk(KERN_ERR "%s/2: cx8802 driver remove "
780 "failed (%d)\n", dev->core->name, err);
781 }
782
783 mutex_unlock(&dev->core->lock);
784 }
785
786 mutex_unlock(&cx8802_mutex);
787
788 return err;
789}
790
791/* ----------------------------------------------------------- */
792static int __devinit cx8802_probe(struct pci_dev *pci_dev,
793 const struct pci_device_id *pci_id)
794{
795 struct cx8802_dev *dev;
796 struct cx88_core *core;
797 int err;
798
799 /* general setup */
800 core = cx88_core_get(pci_dev);
801 if (NULL == core)
802 return -EINVAL;
803
804 printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
805
806 err = -ENODEV;
807 if (!core->board.mpeg)
808 goto fail_core;
809
810 err = -ENOMEM;
811 dev = kzalloc(sizeof(*dev),GFP_KERNEL);
812 if (NULL == dev)
813 goto fail_core;
814 dev->pci = pci_dev;
815 dev->core = core;
816
817 /* Maintain a reference so cx88-video can query the 8802 device. */
818 core->dvbdev = dev;
819
820 err = cx8802_init_common(dev);
821 if (err != 0)
822 goto fail_free;
823
824 INIT_LIST_HEAD(&dev->drvlist);
825 mutex_lock(&cx8802_mutex);
826 list_add_tail(&dev->devlist,&cx8802_devlist);
827 mutex_unlock(&cx8802_mutex);
828
829 /* now autoload cx88-dvb or cx88-blackbird */
830 request_modules(dev);
831 return 0;
832
833 fail_free:
834 kfree(dev);
835 fail_core:
836 core->dvbdev = NULL;
837 cx88_core_put(core,pci_dev);
838 return err;
839}
840
841static void __devexit cx8802_remove(struct pci_dev *pci_dev)
842{
843 struct cx8802_dev *dev;
844
845 dev = pci_get_drvdata(pci_dev);
846
847 dprintk( 1, "%s\n", __func__);
848
849 flush_request_modules(dev);
850
851 mutex_lock(&dev->core->lock);
852
853 if (!list_empty(&dev->drvlist)) {
854 struct cx8802_driver *drv, *tmp;
855 int err;
856
857 printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "
858 "while cx8802 sub-drivers still loaded?!\n",
859 dev->core->name);
860
861 list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
862 err = drv->remove(drv);
863 if (err == 0) {
864 list_del(&drv->drvlist);
865 } else
866 printk(KERN_ERR "%s/2: cx8802 driver remove "
867 "failed (%d)\n", dev->core->name, err);
868 kfree(drv);
869 }
870 }
871
872 mutex_unlock(&dev->core->lock);
873
874 /* Destroy any 8802 reference. */
875 dev->core->dvbdev = NULL;
876
877 /* common */
878 cx8802_fini_common(dev);
879 cx88_core_put(dev->core,dev->pci);
880 kfree(dev);
881}
882
883static const struct pci_device_id cx8802_pci_tbl[] = {
884 {
885 .vendor = 0x14f1,
886 .device = 0x8802,
887 .subvendor = PCI_ANY_ID,
888 .subdevice = PCI_ANY_ID,
889 },{
890 /* --- end of list --- */
891 }
892};
893MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
894
895static struct pci_driver cx8802_pci_driver = {
896 .name = "cx88-mpeg driver manager",
897 .id_table = cx8802_pci_tbl,
898 .probe = cx8802_probe,
899 .remove = __devexit_p(cx8802_remove),
900};
901
902static int __init cx8802_init(void)
903{
904 printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %s loaded\n",
905 CX88_VERSION);
906 return pci_register_driver(&cx8802_pci_driver);
907}
908
909static void __exit cx8802_fini(void)
910{
911 pci_unregister_driver(&cx8802_pci_driver);
912}
913
914module_init(cx8802_init);
915module_exit(cx8802_fini);
916EXPORT_SYMBOL(cx8802_buf_prepare);
917EXPORT_SYMBOL(cx8802_buf_queue);
918EXPORT_SYMBOL(cx8802_cancel_buffers);
919
920EXPORT_SYMBOL(cx8802_register_driver);
921EXPORT_SYMBOL(cx8802_unregister_driver);
922EXPORT_SYMBOL(cx8802_get_driver);
923/* ----------------------------------------------------------- */
924/*
925 * Local variables:
926 * c-basic-offset: 8
927 * End:
928 * 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
929 */
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
new file mode 100644
index 00000000000..2ec52d1cdea
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-reg.h
@@ -0,0 +1,836 @@
1/*
2
3 cx88x-hw.h - CX2388x register offsets
4
5 Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
6 2001 Michael Eskin
7 2002 Yurij Sysoev <yurij@naturesoft.net>
8 2003 Gerd Knorr <kraxel@bytesex.org>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/
24
25#ifndef _CX88_REG_H_
26#define _CX88_REG_H_
27
28/* ---------------------------------------------------------------------- */
29/* PCI IDs and config space */
30
31#ifndef PCI_VENDOR_ID_CONEXANT
32# define PCI_VENDOR_ID_CONEXANT 0x14F1
33#endif
34#ifndef PCI_DEVICE_ID_CX2300_VID
35# define PCI_DEVICE_ID_CX2300_VID 0x8800
36#endif
37
38#define CX88X_DEVCTRL 0x40
39#define CX88X_EN_TBFX 0x02
40#define CX88X_EN_VSFX 0x04
41
42/* ---------------------------------------------------------------------- */
43/* PCI controller registers */
44
45/* Command and Status Register */
46#define F0_CMD_STAT_MM 0x2f0004
47#define F1_CMD_STAT_MM 0x2f0104
48#define F2_CMD_STAT_MM 0x2f0204
49#define F3_CMD_STAT_MM 0x2f0304
50#define F4_CMD_STAT_MM 0x2f0404
51
52/* Device Control #1 */
53#define F0_DEV_CNTRL1_MM 0x2f0040
54#define F1_DEV_CNTRL1_MM 0x2f0140
55#define F2_DEV_CNTRL1_MM 0x2f0240
56#define F3_DEV_CNTRL1_MM 0x2f0340
57#define F4_DEV_CNTRL1_MM 0x2f0440
58
59/* Device Control #1 */
60#define F0_BAR0_MM 0x2f0010
61#define F1_BAR0_MM 0x2f0110
62#define F2_BAR0_MM 0x2f0210
63#define F3_BAR0_MM 0x2f0310
64#define F4_BAR0_MM 0x2f0410
65
66/* ---------------------------------------------------------------------- */
67/* DMA Controller registers */
68
69#define MO_PDMA_STHRSH 0x200000 // Source threshold
70#define MO_PDMA_STADRS 0x200004 // Source target address
71#define MO_PDMA_SIADRS 0x200008 // Source internal address
72#define MO_PDMA_SCNTRL 0x20000C // Source control
73#define MO_PDMA_DTHRSH 0x200010 // Destination threshold
74#define MO_PDMA_DTADRS 0x200014 // Destination target address
75#define MO_PDMA_DIADRS 0x200018 // Destination internal address
76#define MO_PDMA_DCNTRL 0x20001C // Destination control
77#define MO_LD_SSID 0x200030 // Load subsystem ID
78#define MO_DEV_CNTRL2 0x200034 // Device control
79#define MO_PCI_INTMSK 0x200040 // PCI interrupt mask
80#define MO_PCI_INTSTAT 0x200044 // PCI interrupt status
81#define MO_PCI_INTMSTAT 0x200048 // PCI interrupt masked status
82#define MO_VID_INTMSK 0x200050 // Video interrupt mask
83#define MO_VID_INTSTAT 0x200054 // Video interrupt status
84#define MO_VID_INTMSTAT 0x200058 // Video interrupt masked status
85#define MO_VID_INTSSTAT 0x20005C // Video interrupt set status
86#define MO_AUD_INTMSK 0x200060 // Audio interrupt mask
87#define MO_AUD_INTSTAT 0x200064 // Audio interrupt status
88#define MO_AUD_INTMSTAT 0x200068 // Audio interrupt masked status
89#define MO_AUD_INTSSTAT 0x20006C // Audio interrupt set status
90#define MO_TS_INTMSK 0x200070 // Transport stream interrupt mask
91#define MO_TS_INTSTAT 0x200074 // Transport stream interrupt status
92#define MO_TS_INTMSTAT 0x200078 // Transport stream interrupt mask status
93#define MO_TS_INTSSTAT 0x20007C // Transport stream interrupt set status
94#define MO_VIP_INTMSK 0x200080 // VIP interrupt mask
95#define MO_VIP_INTSTAT 0x200084 // VIP interrupt status
96#define MO_VIP_INTMSTAT 0x200088 // VIP interrupt masked status
97#define MO_VIP_INTSSTAT 0x20008C // VIP interrupt set status
98#define MO_GPHST_INTMSK 0x200090 // Host interrupt mask
99#define MO_GPHST_INTSTAT 0x200094 // Host interrupt status
100#define MO_GPHST_INTMSTAT 0x200098 // Host interrupt masked status
101#define MO_GPHST_INTSSTAT 0x20009C // Host interrupt set status
102
103// DMA Channels 1-6 belong to SPIPE
104#define MO_DMA7_PTR1 0x300018 // {24}RW* DMA Current Ptr : Ch#7
105#define MO_DMA8_PTR1 0x30001C // {24}RW* DMA Current Ptr : Ch#8
106
107// DMA Channels 9-20 belong to SPIPE
108#define MO_DMA21_PTR1 0x300080 // {24}R0* DMA Current Ptr : Ch#21
109#define MO_DMA22_PTR1 0x300084 // {24}R0* DMA Current Ptr : Ch#22
110#define MO_DMA23_PTR1 0x300088 // {24}R0* DMA Current Ptr : Ch#23
111#define MO_DMA24_PTR1 0x30008C // {24}R0* DMA Current Ptr : Ch#24
112#define MO_DMA25_PTR1 0x300090 // {24}R0* DMA Current Ptr : Ch#25
113#define MO_DMA26_PTR1 0x300094 // {24}R0* DMA Current Ptr : Ch#26
114#define MO_DMA27_PTR1 0x300098 // {24}R0* DMA Current Ptr : Ch#27
115#define MO_DMA28_PTR1 0x30009C // {24}R0* DMA Current Ptr : Ch#28
116#define MO_DMA29_PTR1 0x3000A0 // {24}R0* DMA Current Ptr : Ch#29
117#define MO_DMA30_PTR1 0x3000A4 // {24}R0* DMA Current Ptr : Ch#30
118#define MO_DMA31_PTR1 0x3000A8 // {24}R0* DMA Current Ptr : Ch#31
119#define MO_DMA32_PTR1 0x3000AC // {24}R0* DMA Current Ptr : Ch#32
120
121#define MO_DMA21_PTR2 0x3000C0 // {24}RW* DMA Tab Ptr : Ch#21
122#define MO_DMA22_PTR2 0x3000C4 // {24}RW* DMA Tab Ptr : Ch#22
123#define MO_DMA23_PTR2 0x3000C8 // {24}RW* DMA Tab Ptr : Ch#23
124#define MO_DMA24_PTR2 0x3000CC // {24}RW* DMA Tab Ptr : Ch#24
125#define MO_DMA25_PTR2 0x3000D0 // {24}RW* DMA Tab Ptr : Ch#25
126#define MO_DMA26_PTR2 0x3000D4 // {24}RW* DMA Tab Ptr : Ch#26
127#define MO_DMA27_PTR2 0x3000D8 // {24}RW* DMA Tab Ptr : Ch#27
128#define MO_DMA28_PTR2 0x3000DC // {24}RW* DMA Tab Ptr : Ch#28
129#define MO_DMA29_PTR2 0x3000E0 // {24}RW* DMA Tab Ptr : Ch#29
130#define MO_DMA30_PTR2 0x3000E4 // {24}RW* DMA Tab Ptr : Ch#30
131#define MO_DMA31_PTR2 0x3000E8 // {24}RW* DMA Tab Ptr : Ch#31
132#define MO_DMA32_PTR2 0x3000EC // {24}RW* DMA Tab Ptr : Ch#32
133
134#define MO_DMA21_CNT1 0x300100 // {11}RW* DMA Buffer Size : Ch#21
135#define MO_DMA22_CNT1 0x300104 // {11}RW* DMA Buffer Size : Ch#22
136#define MO_DMA23_CNT1 0x300108 // {11}RW* DMA Buffer Size : Ch#23
137#define MO_DMA24_CNT1 0x30010C // {11}RW* DMA Buffer Size : Ch#24
138#define MO_DMA25_CNT1 0x300110 // {11}RW* DMA Buffer Size : Ch#25
139#define MO_DMA26_CNT1 0x300114 // {11}RW* DMA Buffer Size : Ch#26
140#define MO_DMA27_CNT1 0x300118 // {11}RW* DMA Buffer Size : Ch#27
141#define MO_DMA28_CNT1 0x30011C // {11}RW* DMA Buffer Size : Ch#28
142#define MO_DMA29_CNT1 0x300120 // {11}RW* DMA Buffer Size : Ch#29
143#define MO_DMA30_CNT1 0x300124 // {11}RW* DMA Buffer Size : Ch#30
144#define MO_DMA31_CNT1 0x300128 // {11}RW* DMA Buffer Size : Ch#31
145#define MO_DMA32_CNT1 0x30012C // {11}RW* DMA Buffer Size : Ch#32
146
147#define MO_DMA21_CNT2 0x300140 // {11}RW* DMA Table Size : Ch#21
148#define MO_DMA22_CNT2 0x300144 // {11}RW* DMA Table Size : Ch#22
149#define MO_DMA23_CNT2 0x300148 // {11}RW* DMA Table Size : Ch#23
150#define MO_DMA24_CNT2 0x30014C // {11}RW* DMA Table Size : Ch#24
151#define MO_DMA25_CNT2 0x300150 // {11}RW* DMA Table Size : Ch#25
152#define MO_DMA26_CNT2 0x300154 // {11}RW* DMA Table Size : Ch#26
153#define MO_DMA27_CNT2 0x300158 // {11}RW* DMA Table Size : Ch#27
154#define MO_DMA28_CNT2 0x30015C // {11}RW* DMA Table Size : Ch#28
155#define MO_DMA29_CNT2 0x300160 // {11}RW* DMA Table Size : Ch#29
156#define MO_DMA30_CNT2 0x300164 // {11}RW* DMA Table Size : Ch#30
157#define MO_DMA31_CNT2 0x300168 // {11}RW* DMA Table Size : Ch#31
158#define MO_DMA32_CNT2 0x30016C // {11}RW* DMA Table Size : Ch#32
159
160
161/* ---------------------------------------------------------------------- */
162/* Video registers */
163
164#define MO_VIDY_DMA 0x310000 // {64}RWp Video Y
165#define MO_VIDU_DMA 0x310008 // {64}RWp Video U
166#define MO_VIDV_DMA 0x310010 // {64}RWp Video V
167#define MO_VBI_DMA 0x310018 // {64}RWp VBI (Vertical blanking interval)
168
169#define MO_DEVICE_STATUS 0x310100
170#define MO_INPUT_FORMAT 0x310104
171#define MO_AGC_BURST 0x31010c
172#define MO_CONTR_BRIGHT 0x310110
173#define MO_UV_SATURATION 0x310114
174#define MO_HUE 0x310118
175#define MO_HTOTAL 0x310120
176#define MO_HDELAY_EVEN 0x310124
177#define MO_HDELAY_ODD 0x310128
178#define MO_VDELAY_ODD 0x31012c
179#define MO_VDELAY_EVEN 0x310130
180#define MO_HACTIVE_EVEN 0x31013c
181#define MO_HACTIVE_ODD 0x310140
182#define MO_VACTIVE_EVEN 0x310144
183#define MO_VACTIVE_ODD 0x310148
184#define MO_HSCALE_EVEN 0x31014c
185#define MO_HSCALE_ODD 0x310150
186#define MO_VSCALE_EVEN 0x310154
187#define MO_FILTER_EVEN 0x31015c
188#define MO_VSCALE_ODD 0x310158
189#define MO_FILTER_ODD 0x310160
190#define MO_OUTPUT_FORMAT 0x310164
191
192#define MO_PLL_REG 0x310168 // PLL register
193#define MO_PLL_ADJ_CTRL 0x31016c // PLL adjust control register
194#define MO_SCONV_REG 0x310170 // sample rate conversion register
195#define MO_SCONV_FIFO 0x310174 // sample rate conversion fifo
196#define MO_SUB_STEP 0x310178 // subcarrier step size
197#define MO_SUB_STEP_DR 0x31017c // subcarrier step size for DR line
198
199#define MO_CAPTURE_CTRL 0x310180 // capture control
200#define MO_COLOR_CTRL 0x310184
201#define MO_VBI_PACKET 0x310188 // vbi packet size / delay
202#define MO_FIELD_COUNT 0x310190 // field counter
203#define MO_VIP_CONFIG 0x310194
204#define MO_VBOS_CONTROL 0x3101a8
205
206#define MO_AGC_BACK_VBI 0x310200
207#define MO_AGC_SYNC_TIP1 0x310208
208
209#define MO_VIDY_GPCNT 0x31C020 // {16}RO Video Y general purpose counter
210#define MO_VIDU_GPCNT 0x31C024 // {16}RO Video U general purpose counter
211#define MO_VIDV_GPCNT 0x31C028 // {16}RO Video V general purpose counter
212#define MO_VBI_GPCNT 0x31C02C // {16}RO VBI general purpose counter
213#define MO_VIDY_GPCNTRL 0x31C030 // {2}WO Video Y general purpose control
214#define MO_VIDU_GPCNTRL 0x31C034 // {2}WO Video U general purpose control
215#define MO_VIDV_GPCNTRL 0x31C038 // {2}WO Video V general purpose control
216#define MO_VBI_GPCNTRL 0x31C03C // {2}WO VBI general purpose counter
217#define MO_VID_DMACNTRL 0x31C040 // {8}RW Video DMA control
218#define MO_VID_XFR_STAT 0x31C044 // {1}RO Video transfer status
219
220
221/* ---------------------------------------------------------------------- */
222/* audio registers */
223
224#define MO_AUDD_DMA 0x320000 // {64}RWp Audio downstream
225#define MO_AUDU_DMA 0x320008 // {64}RWp Audio upstream
226#define MO_AUDR_DMA 0x320010 // {64}RWp Audio RDS (downstream)
227#define MO_AUDD_GPCNT 0x32C020 // {16}RO Audio down general purpose counter
228#define MO_AUDU_GPCNT 0x32C024 // {16}RO Audio up general purpose counter
229#define MO_AUDR_GPCNT 0x32C028 // {16}RO Audio RDS general purpose counter
230#define MO_AUDD_GPCNTRL 0x32C030 // {2}WO Audio down general purpose control
231#define MO_AUDU_GPCNTRL 0x32C034 // {2}WO Audio up general purpose control
232#define MO_AUDR_GPCNTRL 0x32C038 // {2}WO Audio RDS general purpose control
233#define MO_AUD_DMACNTRL 0x32C040 // {6}RW Audio DMA control
234#define MO_AUD_XFR_STAT 0x32C044 // {1}RO Audio transfer status
235#define MO_AUDD_LNGTH 0x32C048 // {12}RW Audio down line length
236#define MO_AUDR_LNGTH 0x32C04C // {12}RW Audio RDS line length
237
238#define AUD_INIT 0x320100
239#define AUD_INIT_LD 0x320104
240#define AUD_SOFT_RESET 0x320108
241#define AUD_I2SINPUTCNTL 0x320120
242#define AUD_BAUDRATE 0x320124
243#define AUD_I2SOUTPUTCNTL 0x320128
244#define AAGC_HYST 0x320134
245#define AAGC_GAIN 0x320138
246#define AAGC_DEF 0x32013c
247#define AUD_IIR1_0_SEL 0x320150
248#define AUD_IIR1_0_SHIFT 0x320154
249#define AUD_IIR1_1_SEL 0x320158
250#define AUD_IIR1_1_SHIFT 0x32015c
251#define AUD_IIR1_2_SEL 0x320160
252#define AUD_IIR1_2_SHIFT 0x320164
253#define AUD_IIR1_3_SEL 0x320168
254#define AUD_IIR1_3_SHIFT 0x32016c
255#define AUD_IIR1_4_SEL 0x320170
256#define AUD_IIR1_4_SHIFT 0x32017c
257#define AUD_IIR1_5_SEL 0x320180
258#define AUD_IIR1_5_SHIFT 0x320184
259#define AUD_IIR2_0_SEL 0x320190
260#define AUD_IIR2_0_SHIFT 0x320194
261#define AUD_IIR2_1_SEL 0x320198
262#define AUD_IIR2_1_SHIFT 0x32019c
263#define AUD_IIR2_2_SEL 0x3201a0
264#define AUD_IIR2_2_SHIFT 0x3201a4
265#define AUD_IIR2_3_SEL 0x3201a8
266#define AUD_IIR2_3_SHIFT 0x3201ac
267#define AUD_IIR3_0_SEL 0x3201c0
268#define AUD_IIR3_0_SHIFT 0x3201c4
269#define AUD_IIR3_1_SEL 0x3201c8
270#define AUD_IIR3_1_SHIFT 0x3201cc
271#define AUD_IIR3_2_SEL 0x3201d0
272#define AUD_IIR3_2_SHIFT 0x3201d4
273#define AUD_IIR4_0_SEL 0x3201e0
274#define AUD_IIR4_0_SHIFT 0x3201e4
275#define AUD_IIR4_1_SEL 0x3201e8
276#define AUD_IIR4_1_SHIFT 0x3201ec
277#define AUD_IIR4_2_SEL 0x3201f0
278#define AUD_IIR4_2_SHIFT 0x3201f4
279#define AUD_IIR4_0_CA0 0x320200
280#define AUD_IIR4_0_CA1 0x320204
281#define AUD_IIR4_0_CA2 0x320208
282#define AUD_IIR4_0_CB0 0x32020c
283#define AUD_IIR4_0_CB1 0x320210
284#define AUD_IIR4_1_CA0 0x320214
285#define AUD_IIR4_1_CA1 0x320218
286#define AUD_IIR4_1_CA2 0x32021c
287#define AUD_IIR4_1_CB0 0x320220
288#define AUD_IIR4_1_CB1 0x320224
289#define AUD_IIR4_2_CA0 0x320228
290#define AUD_IIR4_2_CA1 0x32022c
291#define AUD_IIR4_2_CA2 0x320230
292#define AUD_IIR4_2_CB0 0x320234
293#define AUD_IIR4_2_CB1 0x320238
294#define AUD_HP_MD_IIR4_1 0x320250
295#define AUD_HP_PROG_IIR4_1 0x320254
296#define AUD_FM_MODE_ENABLE 0x320258
297#define AUD_POLY0_DDS_CONSTANT 0x320270
298#define AUD_DN0_FREQ 0x320274
299#define AUD_DN1_FREQ 0x320278
300#define AUD_DN1_FREQ_SHIFT 0x32027c
301#define AUD_DN1_AFC 0x320280
302#define AUD_DN1_SRC_SEL 0x320284
303#define AUD_DN1_SHFT 0x320288
304#define AUD_DN2_FREQ 0x32028c
305#define AUD_DN2_FREQ_SHIFT 0x320290
306#define AUD_DN2_AFC 0x320294
307#define AUD_DN2_SRC_SEL 0x320298
308#define AUD_DN2_SHFT 0x32029c
309#define AUD_CRDC0_SRC_SEL 0x320300
310#define AUD_CRDC0_SHIFT 0x320304
311#define AUD_CORDIC_SHIFT_0 0x320308
312#define AUD_CRDC1_SRC_SEL 0x32030c
313#define AUD_CRDC1_SHIFT 0x320310
314#define AUD_CORDIC_SHIFT_1 0x320314
315#define AUD_DCOC_0_SRC 0x320320
316#define AUD_DCOC0_SHIFT 0x320324
317#define AUD_DCOC_0_SHIFT_IN0 0x320328
318#define AUD_DCOC_0_SHIFT_IN1 0x32032c
319#define AUD_DCOC_1_SRC 0x320330
320#define AUD_DCOC1_SHIFT 0x320334
321#define AUD_DCOC_1_SHIFT_IN0 0x320338
322#define AUD_DCOC_1_SHIFT_IN1 0x32033c
323#define AUD_DCOC_2_SRC 0x320340
324#define AUD_DCOC2_SHIFT 0x320344
325#define AUD_DCOC_2_SHIFT_IN0 0x320348
326#define AUD_DCOC_2_SHIFT_IN1 0x32034c
327#define AUD_DCOC_PASS_IN 0x320350
328#define AUD_PDET_SRC 0x320370
329#define AUD_PDET_SHIFT 0x320374
330#define AUD_PILOT_BQD_1_K0 0x320380
331#define AUD_PILOT_BQD_1_K1 0x320384
332#define AUD_PILOT_BQD_1_K2 0x320388
333#define AUD_PILOT_BQD_1_K3 0x32038c
334#define AUD_PILOT_BQD_1_K4 0x320390
335#define AUD_PILOT_BQD_2_K0 0x320394
336#define AUD_PILOT_BQD_2_K1 0x320398
337#define AUD_PILOT_BQD_2_K2 0x32039c
338#define AUD_PILOT_BQD_2_K3 0x3203a0
339#define AUD_PILOT_BQD_2_K4 0x3203a4
340#define AUD_THR_FR 0x3203c0
341#define AUD_X_PROG 0x3203c4
342#define AUD_Y_PROG 0x3203c8
343#define AUD_HARMONIC_MULT 0x3203cc
344#define AUD_C1_UP_THR 0x3203d0
345#define AUD_C1_LO_THR 0x3203d4
346#define AUD_C2_UP_THR 0x3203d8
347#define AUD_C2_LO_THR 0x3203dc
348#define AUD_PLL_EN 0x320400
349#define AUD_PLL_SRC 0x320404
350#define AUD_PLL_SHIFT 0x320408
351#define AUD_PLL_IF_SEL 0x32040c
352#define AUD_PLL_IF_SHIFT 0x320410
353#define AUD_BIQUAD_PLL_K0 0x320414
354#define AUD_BIQUAD_PLL_K1 0x320418
355#define AUD_BIQUAD_PLL_K2 0x32041c
356#define AUD_BIQUAD_PLL_K3 0x320420
357#define AUD_BIQUAD_PLL_K4 0x320424
358#define AUD_DEEMPH0_SRC_SEL 0x320440
359#define AUD_DEEMPH0_SHIFT 0x320444
360#define AUD_DEEMPH0_G0 0x320448
361#define AUD_DEEMPH0_A0 0x32044c
362#define AUD_DEEMPH0_B0 0x320450
363#define AUD_DEEMPH0_A1 0x320454
364#define AUD_DEEMPH0_B1 0x320458
365#define AUD_DEEMPH1_SRC_SEL 0x32045c
366#define AUD_DEEMPH1_SHIFT 0x320460
367#define AUD_DEEMPH1_G0 0x320464
368#define AUD_DEEMPH1_A0 0x320468
369#define AUD_DEEMPH1_B0 0x32046c
370#define AUD_DEEMPH1_A1 0x320470
371#define AUD_DEEMPH1_B1 0x320474
372#define AUD_OUT0_SEL 0x320490
373#define AUD_OUT0_SHIFT 0x320494
374#define AUD_OUT1_SEL 0x320498
375#define AUD_OUT1_SHIFT 0x32049c
376#define AUD_RDSI_SEL 0x3204a0
377#define AUD_RDSI_SHIFT 0x3204a4
378#define AUD_RDSQ_SEL 0x3204a8
379#define AUD_RDSQ_SHIFT 0x3204ac
380#define AUD_DBX_IN_GAIN 0x320500
381#define AUD_DBX_WBE_GAIN 0x320504
382#define AUD_DBX_SE_GAIN 0x320508
383#define AUD_DBX_RMS_WBE 0x32050c
384#define AUD_DBX_RMS_SE 0x320510
385#define AUD_DBX_SE_BYPASS 0x320514
386#define AUD_FAWDETCTL 0x320530
387#define AUD_FAWDETWINCTL 0x320534
388#define AUD_DEEMPHGAIN_R 0x320538
389#define AUD_DEEMPHNUMER1_R 0x32053c
390#define AUD_DEEMPHNUMER2_R 0x320540
391#define AUD_DEEMPHDENOM1_R 0x320544
392#define AUD_DEEMPHDENOM2_R 0x320548
393#define AUD_ERRLOGPERIOD_R 0x32054c
394#define AUD_ERRINTRPTTHSHLD1_R 0x320550
395#define AUD_ERRINTRPTTHSHLD2_R 0x320554
396#define AUD_ERRINTRPTTHSHLD3_R 0x320558
397#define AUD_NICAM_STATUS1 0x32055c
398#define AUD_NICAM_STATUS2 0x320560
399#define AUD_ERRLOG1 0x320564
400#define AUD_ERRLOG2 0x320568
401#define AUD_ERRLOG3 0x32056c
402#define AUD_DAC_BYPASS_L 0x320580
403#define AUD_DAC_BYPASS_R 0x320584
404#define AUD_DAC_BYPASS_CTL 0x320588
405#define AUD_CTL 0x32058c
406#define AUD_STATUS 0x320590
407#define AUD_VOL_CTL 0x320594
408#define AUD_BAL_CTL 0x320598
409#define AUD_START_TIMER 0x3205b0
410#define AUD_MODE_CHG_TIMER 0x3205b4
411#define AUD_POLYPH80SCALEFAC 0x3205b8
412#define AUD_DMD_RA_DDS 0x3205bc
413#define AUD_I2S_RA_DDS 0x3205c0
414#define AUD_RATE_THRES_DMD 0x3205d0
415#define AUD_RATE_THRES_I2S 0x3205d4
416#define AUD_RATE_ADJ1 0x3205d8
417#define AUD_RATE_ADJ2 0x3205dc
418#define AUD_RATE_ADJ3 0x3205e0
419#define AUD_RATE_ADJ4 0x3205e4
420#define AUD_RATE_ADJ5 0x3205e8
421#define AUD_APB_IN_RATE_ADJ 0x3205ec
422#define AUD_I2SCNTL 0x3205ec
423#define AUD_PHASE_FIX_CTL 0x3205f0
424#define AUD_PLL_PRESCALE 0x320600
425#define AUD_PLL_DDS 0x320604
426#define AUD_PLL_INT 0x320608
427#define AUD_PLL_FRAC 0x32060c
428#define AUD_PLL_JTAG 0x320620
429#define AUD_PLL_SPMP 0x320624
430#define AUD_AFE_12DB_EN 0x320628
431
432// Audio QAM Register Addresses
433#define AUD_PDF_DDS_CNST_BYTE2 0x320d01
434#define AUD_PDF_DDS_CNST_BYTE1 0x320d02
435#define AUD_PDF_DDS_CNST_BYTE0 0x320d03
436#define AUD_PHACC_FREQ_8MSB 0x320d2a
437#define AUD_PHACC_FREQ_8LSB 0x320d2b
438#define AUD_QAM_MODE 0x320d04
439
440
441/* ---------------------------------------------------------------------- */
442/* transport stream registers */
443
444#define MO_TS_DMA 0x330000 // {64}RWp Transport stream downstream
445#define MO_TS_GPCNT 0x33C020 // {16}RO TS general purpose counter
446#define MO_TS_GPCNTRL 0x33C030 // {2}WO TS general purpose control
447#define MO_TS_DMACNTRL 0x33C040 // {6}RW TS DMA control
448#define MO_TS_XFR_STAT 0x33C044 // {1}RO TS transfer status
449#define MO_TS_LNGTH 0x33C048 // {12}RW TS line length
450
451#define TS_HW_SOP_CNTRL 0x33C04C
452#define TS_GEN_CNTRL 0x33C050
453#define TS_BD_PKT_STAT 0x33C054
454#define TS_SOP_STAT 0x33C058
455#define TS_FIFO_OVFL_STAT 0x33C05C
456#define TS_VALERR_CNTRL 0x33C060
457
458
459/* ---------------------------------------------------------------------- */
460/* VIP registers */
461
462#define MO_VIPD_DMA 0x340000 // {64}RWp VIP downstream
463#define MO_VIPU_DMA 0x340008 // {64}RWp VIP upstream
464#define MO_VIPD_GPCNT 0x34C020 // {16}RO VIP down general purpose counter
465#define MO_VIPU_GPCNT 0x34C024 // {16}RO VIP up general purpose counter
466#define MO_VIPD_GPCNTRL 0x34C030 // {2}WO VIP down general purpose control
467#define MO_VIPU_GPCNTRL 0x34C034 // {2}WO VIP up general purpose control
468#define MO_VIP_DMACNTRL 0x34C040 // {6}RW VIP DMA control
469#define MO_VIP_XFR_STAT 0x34C044 // {1}RO VIP transfer status
470#define MO_VIP_CFG 0x340048 // VIP configuration
471#define MO_VIPU_CNTRL 0x34004C // VIP upstream control #1
472#define MO_VIPD_CNTRL 0x340050 // VIP downstream control #2
473#define MO_VIPD_LNGTH 0x340054 // VIP downstream line length
474#define MO_VIP_BRSTLN 0x340058 // VIP burst length
475#define MO_VIP_INTCNTRL 0x34C05C // VIP Interrupt Control
476#define MO_VIP_XFTERM 0x340060 // VIP transfer terminate
477
478
479/* ---------------------------------------------------------------------- */
480/* misc registers */
481
482#define MO_M2M_DMA 0x350000 // {64}RWp Mem2Mem DMA Bfr
483#define MO_GP0_IO 0x350010 // {32}RW* GPIOoutput enablesdata I/O
484#define MO_GP1_IO 0x350014 // {32}RW* GPIOoutput enablesdata I/O
485#define MO_GP2_IO 0x350018 // {32}RW* GPIOoutput enablesdata I/O
486#define MO_GP3_IO 0x35001C // {32}RW* GPIO Mode/Ctrloutput enables
487#define MO_GPIO 0x350020 // {32}RW* GPIO I2C Ctrldata I/O
488#define MO_GPOE 0x350024 // {32}RW GPIO I2C Ctrloutput enables
489#define MO_GP_ISM 0x350028 // {16}WO GPIO Intr Sens/Pol
490
491#define MO_PLL_B 0x35C008 // {32}RW* PLL Control for ASB bus clks
492#define MO_M2M_CNT 0x35C024 // {32}RW Mem2Mem DMA Cnt
493#define MO_M2M_XSUM 0x35C028 // {32}RO M2M XOR-Checksum
494#define MO_CRC 0x35C02C // {16}RW CRC16 init/result
495#define MO_CRC_D 0x35C030 // {32}WO CRC16 new data in
496#define MO_TM_CNT_LDW 0x35C034 // {32}RO Timer : Counter low dword
497#define MO_TM_CNT_UW 0x35C038 // {16}RO Timer : Counter high word
498#define MO_TM_LMT_LDW 0x35C03C // {32}RW Timer : Limit low dword
499#define MO_TM_LMT_UW 0x35C040 // {32}RW Timer : Limit high word
500#define MO_PINMUX_IO 0x35C044 // {8}RW Pin Mux Control
501#define MO_TSTSEL_IO 0x35C048 // {2}RW Pin Mux Control
502#define MO_AFECFG_IO 0x35C04C // AFE configuration reg
503#define MO_DDS_IO 0x35C050 // DDS Increment reg
504#define MO_DDSCFG_IO 0x35C054 // DDS Configuration reg
505#define MO_SAMPLE_IO 0x35C058 // IRIn sample reg
506#define MO_SRST_IO 0x35C05C // Output system reset reg
507
508#define MO_INT1_MSK 0x35C060 // DMA RISC interrupt mask
509#define MO_INT1_STAT 0x35C064 // DMA RISC interrupt status
510#define MO_INT1_MSTAT 0x35C068 // DMA RISC interrupt masked status
511
512
513/* ---------------------------------------------------------------------- */
514/* i2c bus registers */
515
516#define MO_I2C 0x368000 // I2C data/control
517#define MO_I2C_DIV (0xf<<4)
518#define MO_I2C_SYNC (1<<3)
519#define MO_I2C_W3B (1<<2)
520#define MO_I2C_SCL (1<<1)
521#define MO_I2C_SDA (1<<0)
522
523
524/* ---------------------------------------------------------------------- */
525/* general purpose host registers */
526/* FIXME: tyops? s/0x35/0x38/ ?? */
527
528#define MO_GPHSTD_DMA 0x350000 // {64}RWp Host downstream
529#define MO_GPHSTU_DMA 0x350008 // {64}RWp Host upstream
530#define MO_GPHSTU_CNTRL 0x380048 // Host upstream control #1
531#define MO_GPHSTD_CNTRL 0x38004C // Host downstream control #2
532#define MO_GPHSTD_LNGTH 0x380050 // Host downstream line length
533#define MO_GPHST_WSC 0x380054 // Host wait state control
534#define MO_GPHST_XFR 0x380058 // Host transfer control
535#define MO_GPHST_WDTH 0x38005C // Host interface width
536#define MO_GPHST_HDSHK 0x380060 // Host peripheral handshake
537#define MO_GPHST_MUX16 0x380064 // Host muxed 16-bit transfer parameters
538#define MO_GPHST_MODE 0x380068 // Host mode select
539
540#define MO_GPHSTD_GPCNT 0x35C020 // Host down general purpose counter
541#define MO_GPHSTU_GPCNT 0x35C024 // Host up general purpose counter
542#define MO_GPHSTD_GPCNTRL 0x38C030 // Host down general purpose control
543#define MO_GPHSTU_GPCNTRL 0x38C034 // Host up general purpose control
544#define MO_GPHST_DMACNTRL 0x38C040 // Host DMA control
545#define MO_GPHST_XFR_STAT 0x38C044 // Host transfer status
546#define MO_GPHST_SOFT_RST 0x38C06C // Host software reset
547
548
549/* ---------------------------------------------------------------------- */
550/* RISC instructions */
551
552#define RISC_SYNC 0x80000000
553#define RISC_SYNC_ODD 0x80000000
554#define RISC_SYNC_EVEN 0x80000200
555#define RISC_RESYNC 0x80008000
556#define RISC_RESYNC_ODD 0x80008000
557#define RISC_RESYNC_EVEN 0x80008200
558#define RISC_WRITE 0x10000000
559#define RISC_WRITEC 0x50000000
560#define RISC_READ 0x90000000
561#define RISC_READC 0xA0000000
562#define RISC_JUMP 0x70000000
563#define RISC_SKIP 0x20000000
564#define RISC_WRITERM 0xB0000000
565#define RISC_WRITECM 0xC0000000
566#define RISC_WRITECR 0xD0000000
567#define RISC_IMM 0x00000001
568
569#define RISC_SOL 0x08000000
570#define RISC_EOL 0x04000000
571
572#define RISC_IRQ2 0x02000000
573#define RISC_IRQ1 0x01000000
574
575#define RISC_CNT_NONE 0x00000000
576#define RISC_CNT_INC 0x00010000
577#define RISC_CNT_RSVR 0x00020000
578#define RISC_CNT_RESET 0x00030000
579#define RISC_JMP_SRP 0x01
580
581
582/* ---------------------------------------------------------------------- */
583/* various constants */
584
585// DMA
586/* Interrupt mask/status */
587#define PCI_INT_VIDINT (1 << 0)
588#define PCI_INT_AUDINT (1 << 1)
589#define PCI_INT_TSINT (1 << 2)
590#define PCI_INT_VIPINT (1 << 3)
591#define PCI_INT_HSTINT (1 << 4)
592#define PCI_INT_TM1INT (1 << 5)
593#define PCI_INT_SRCDMAINT (1 << 6)
594#define PCI_INT_DSTDMAINT (1 << 7)
595#define PCI_INT_RISC_RD_BERRINT (1 << 10)
596#define PCI_INT_RISC_WR_BERRINT (1 << 11)
597#define PCI_INT_BRDG_BERRINT (1 << 12)
598#define PCI_INT_SRC_DMA_BERRINT (1 << 13)
599#define PCI_INT_DST_DMA_BERRINT (1 << 14)
600#define PCI_INT_IPB_DMA_BERRINT (1 << 15)
601#define PCI_INT_I2CDONE (1 << 16)
602#define PCI_INT_I2CRACK (1 << 17)
603#define PCI_INT_IR_SMPINT (1 << 18)
604#define PCI_INT_GPIO_INT0 (1 << 19)
605#define PCI_INT_GPIO_INT1 (1 << 20)
606
607#define SEL_BTSC 0x01
608#define SEL_EIAJ 0x02
609#define SEL_A2 0x04
610#define SEL_SAP 0x08
611#define SEL_NICAM 0x10
612#define SEL_FMRADIO 0x20
613
614// AUD_CTL
615#define AUD_INT_DN_RISCI1 (1 << 0)
616#define AUD_INT_UP_RISCI1 (1 << 1)
617#define AUD_INT_RDS_DN_RISCI1 (1 << 2)
618#define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */
619#define AUD_INT_UP_RISCI2 (1 << 5)
620#define AUD_INT_RDS_DN_RISCI2 (1 << 6)
621#define AUD_INT_DN_SYNC (1 << 12)
622#define AUD_INT_UP_SYNC (1 << 13)
623#define AUD_INT_RDS_DN_SYNC (1 << 14)
624#define AUD_INT_OPC_ERR (1 << 16)
625#define AUD_INT_BER_IRQ (1 << 20)
626#define AUD_INT_MCHG_IRQ (1 << 21)
627
628#define EN_BTSC_FORCE_MONO 0
629#define EN_BTSC_FORCE_STEREO 1
630#define EN_BTSC_FORCE_SAP 2
631#define EN_BTSC_AUTO_STEREO 3
632#define EN_BTSC_AUTO_SAP 4
633
634#define EN_A2_FORCE_MONO1 8
635#define EN_A2_FORCE_MONO2 9
636#define EN_A2_FORCE_STEREO 10
637#define EN_A2_AUTO_MONO2 11
638#define EN_A2_AUTO_STEREO 12
639
640#define EN_EIAJ_FORCE_MONO1 16
641#define EN_EIAJ_FORCE_MONO2 17
642#define EN_EIAJ_FORCE_STEREO 18
643#define EN_EIAJ_AUTO_MONO2 19
644#define EN_EIAJ_AUTO_STEREO 20
645
646#define EN_NICAM_FORCE_MONO1 32
647#define EN_NICAM_FORCE_MONO2 33
648#define EN_NICAM_FORCE_STEREO 34
649#define EN_NICAM_AUTO_MONO2 35
650#define EN_NICAM_AUTO_STEREO 36
651
652#define EN_FMRADIO_FORCE_MONO 24
653#define EN_FMRADIO_FORCE_STEREO 25
654#define EN_FMRADIO_AUTO_STEREO 26
655
656#define EN_NICAM_AUTO_FALLBACK 0x00000040
657#define EN_FMRADIO_EN_RDS 0x00000200
658#define EN_NICAM_TRY_AGAIN_BIT 0x00000400
659#define EN_DAC_ENABLE 0x00001000
660#define EN_I2SOUT_ENABLE 0x00002000
661#define EN_I2SIN_STR2DAC 0x00004000
662#define EN_I2SIN_ENABLE 0x00008000
663
664#define EN_DMTRX_SUMDIFF (0 << 7)
665#define EN_DMTRX_SUMR (1 << 7)
666#define EN_DMTRX_LR (2 << 7)
667#define EN_DMTRX_MONO (3 << 7)
668#define EN_DMTRX_BYPASS (1 << 11)
669
670// Video
671#define VID_CAPTURE_CONTROL 0x310180
672
673#define CX23880_CAP_CTL_CAPTURE_VBI_ODD (1<<3)
674#define CX23880_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
675#define CX23880_CAP_CTL_CAPTURE_ODD (1<<1)
676#define CX23880_CAP_CTL_CAPTURE_EVEN (1<<0)
677
678#define VideoInputMux0 0x0
679#define VideoInputMux1 0x1
680#define VideoInputMux2 0x2
681#define VideoInputMux3 0x3
682#define VideoInputTuner 0x0
683#define VideoInputComposite 0x1
684#define VideoInputSVideo 0x2
685#define VideoInputOther 0x3
686
687#define Xtal0 0x1
688#define Xtal1 0x2
689#define XtalAuto 0x3
690
691#define VideoFormatAuto 0x0
692#define VideoFormatNTSC 0x1
693#define VideoFormatNTSCJapan 0x2
694#define VideoFormatNTSC443 0x3
695#define VideoFormatPAL 0x4
696#define VideoFormatPALB 0x4
697#define VideoFormatPALD 0x4
698#define VideoFormatPALG 0x4
699#define VideoFormatPALH 0x4
700#define VideoFormatPALI 0x4
701#define VideoFormatPALBDGHI 0x4
702#define VideoFormatPALM 0x5
703#define VideoFormatPALN 0x6
704#define VideoFormatPALNC 0x7
705#define VideoFormatPAL60 0x8
706#define VideoFormatSECAM 0x9
707
708#define VideoFormatAuto27MHz 0x10
709#define VideoFormatNTSC27MHz 0x11
710#define VideoFormatNTSCJapan27MHz 0x12
711#define VideoFormatNTSC44327MHz 0x13
712#define VideoFormatPAL27MHz 0x14
713#define VideoFormatPALB27MHz 0x14
714#define VideoFormatPALD27MHz 0x14
715#define VideoFormatPALG27MHz 0x14
716#define VideoFormatPALH27MHz 0x14
717#define VideoFormatPALI27MHz 0x14
718#define VideoFormatPALBDGHI27MHz 0x14
719#define VideoFormatPALM27MHz 0x15
720#define VideoFormatPALN27MHz 0x16
721#define VideoFormatPALNC27MHz 0x17
722#define VideoFormatPAL6027MHz 0x18
723#define VideoFormatSECAM27MHz 0x19
724
725#define NominalUSECAM 0x87
726#define NominalVSECAM 0x85
727#define NominalUNTSC 0xFE
728#define NominalVNTSC 0xB4
729
730#define NominalContrast 0xD8
731
732#define HFilterAutoFormat 0x0
733#define HFilterCIF 0x1
734#define HFilterQCIF 0x2
735#define HFilterICON 0x3
736
737#define VFilter2TapInterpolate 0
738#define VFilter3TapInterpolate 1
739#define VFilter4TapInterpolate 2
740#define VFilter5TapInterpolate 3
741#define VFilter2TapNoInterpolate 4
742#define VFilter3TapNoInterpolate 5
743#define VFilter4TapNoInterpolate 6
744#define VFilter5TapNoInterpolate 7
745
746#define ColorFormatRGB32 0x0000
747#define ColorFormatRGB24 0x0011
748#define ColorFormatRGB16 0x0022
749#define ColorFormatRGB15 0x0033
750#define ColorFormatYUY2 0x0044
751#define ColorFormatBTYUV 0x0055
752#define ColorFormatY8 0x0066
753#define ColorFormatRGB8 0x0077
754#define ColorFormatPL422 0x0088
755#define ColorFormatPL411 0x0099
756#define ColorFormatYUV12 0x00AA
757#define ColorFormatYUV9 0x00BB
758#define ColorFormatRAW 0x00EE
759#define ColorFormatBSWAP 0x0300
760#define ColorFormatWSWAP 0x0c00
761#define ColorFormatEvenMask 0x050f
762#define ColorFormatOddMask 0x0af0
763#define ColorFormatGamma 0x1000
764
765#define Interlaced 0x1
766#define NonInterlaced 0x0
767
768#define FieldEven 0x1
769#define FieldOdd 0x0
770
771#define TGReadWriteMode 0x0
772#define TGEnableMode 0x1
773
774#define DV_CbAlign 0x0
775#define DV_Y0Align 0x1
776#define DV_CrAlign 0x2
777#define DV_Y1Align 0x3
778
779#define DVF_Analog 0x0
780#define DVF_CCIR656 0x1
781#define DVF_ByteStream 0x2
782#define DVF_ExtVSYNC 0x4
783#define DVF_ExtField 0x5
784
785#define CHANNEL_VID_Y 0x1
786#define CHANNEL_VID_U 0x2
787#define CHANNEL_VID_V 0x3
788#define CHANNEL_VID_VBI 0x4
789#define CHANNEL_AUD_DN 0x5
790#define CHANNEL_AUD_UP 0x6
791#define CHANNEL_AUD_RDS_DN 0x7
792#define CHANNEL_MPEG_DN 0x8
793#define CHANNEL_VIP_DN 0x9
794#define CHANNEL_VIP_UP 0xA
795#define CHANNEL_HOST_DN 0xB
796#define CHANNEL_HOST_UP 0xC
797#define CHANNEL_FIRST 0x1
798#define CHANNEL_LAST 0xC
799
800#define GP_COUNT_CONTROL_NONE 0x0
801#define GP_COUNT_CONTROL_INC 0x1
802#define GP_COUNT_CONTROL_RESERVED 0x2
803#define GP_COUNT_CONTROL_RESET 0x3
804
805#define PLL_PRESCALE_BY_2 2
806#define PLL_PRESCALE_BY_3 3
807#define PLL_PRESCALE_BY_4 4
808#define PLL_PRESCALE_BY_5 5
809
810#define HLNotchFilter4xFsc 0
811#define HLNotchFilterSquare 1
812#define HLNotchFilter135NTSC 2
813#define HLNotchFilter135PAL 3
814
815#define NTSC_8x_SUB_CARRIER 28.63636E6
816#define PAL_8x_SUB_CARRIER 35.46895E6
817
818// Default analog settings
819#define DEFAULT_HUE_NTSC 0x00
820#define DEFAULT_BRIGHTNESS_NTSC 0x00
821#define DEFAULT_CONTRAST_NTSC 0x39
822#define DEFAULT_SAT_U_NTSC 0x7F
823#define DEFAULT_SAT_V_NTSC 0x5A
824
825typedef enum
826{
827 SOURCE_TUNER = 0,
828 SOURCE_COMPOSITE,
829 SOURCE_SVIDEO,
830 SOURCE_OTHER1,
831 SOURCE_OTHER2,
832 SOURCE_COMPVIASVIDEO,
833 SOURCE_CCIR656
834} VIDEOSOURCETYPE;
835
836#endif /* _CX88_REG_H_ */
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
new file mode 100644
index 00000000000..770ec05b5e9
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -0,0 +1,1059 @@
1/*
2
3 cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
4
5 (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
6 (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
7 (c) 2003 Gerd Knorr <kraxel@bytesex.org>
8
9 -----------------------------------------------------------------------
10
11 Lot of voodoo here. Even the data sheet doesn't help to
12 understand what is going on here, the documentation for the audio
13 part of the cx2388x chip is *very* bad.
14
15 Some of this comes from party done linux driver sources I got from
16 [undocumented].
17
18 Some comes from the dscaler sources, one of the dscaler driver guy works
19 for Conexant ...
20
21 -----------------------------------------------------------------------
22
23 This program is free software; you can redistribute it and/or modify
24 it under the terms of the GNU General Public License as published by
25 the Free Software Foundation; either version 2 of the License, or
26 (at your option) any later version.
27
28 This program is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
32
33 You should have received a copy of the GNU General Public License
34 along with this program; if not, write to the Free Software
35 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36*/
37
38#include <linux/module.h>
39#include <linux/errno.h>
40#include <linux/freezer.h>
41#include <linux/kernel.h>
42#include <linux/mm.h>
43#include <linux/poll.h>
44#include <linux/signal.h>
45#include <linux/ioport.h>
46#include <linux/types.h>
47#include <linux/interrupt.h>
48#include <linux/vmalloc.h>
49#include <linux/init.h>
50#include <linux/delay.h>
51#include <linux/kthread.h>
52
53#include "cx88.h"
54
55static unsigned int audio_debug;
56module_param(audio_debug, int, 0644);
57MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
58
59static unsigned int always_analog;
60module_param(always_analog,int,0644);
61MODULE_PARM_DESC(always_analog,"force analog audio out");
62
63static unsigned int radio_deemphasis;
64module_param(radio_deemphasis,int,0644);
65MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, "
66 "0=None, 1=50us (elsewhere), 2=75us (USA)");
67
68#define dprintk(fmt, arg...) if (audio_debug) \
69 printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
70
71/* ----------------------------------------------------------- */
72
73static const char * const aud_ctl_names[64] = {
74 [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO",
75 [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO",
76 [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP",
77 [EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO",
78 [EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP",
79 [EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1",
80 [EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2",
81 [EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO",
82 [EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2",
83 [EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO",
84 [EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1",
85 [EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2",
86 [EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO",
87 [EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2",
88 [EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO",
89 [EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1",
90 [EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2",
91 [EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO",
92 [EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2",
93 [EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO",
94 [EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO",
95 [EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO",
96 [EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO",
97};
98
99struct rlist {
100 u32 reg;
101 u32 val;
102};
103
104static void set_audio_registers(struct cx88_core *core, const struct rlist *l)
105{
106 int i;
107
108 for (i = 0; l[i].reg; i++) {
109 switch (l[i].reg) {
110 case AUD_PDF_DDS_CNST_BYTE2:
111 case AUD_PDF_DDS_CNST_BYTE1:
112 case AUD_PDF_DDS_CNST_BYTE0:
113 case AUD_QAM_MODE:
114 case AUD_PHACC_FREQ_8MSB:
115 case AUD_PHACC_FREQ_8LSB:
116 cx_writeb(l[i].reg, l[i].val);
117 break;
118 default:
119 cx_write(l[i].reg, l[i].val);
120 break;
121 }
122 }
123}
124
125static void set_audio_start(struct cx88_core *core, u32 mode)
126{
127 /* mute */
128 cx_write(AUD_VOL_CTL, (1 << 6));
129
130 /* start programming */
131 cx_write(AUD_INIT, mode);
132 cx_write(AUD_INIT_LD, 0x0001);
133 cx_write(AUD_SOFT_RESET, 0x0001);
134}
135
136static void set_audio_finish(struct cx88_core *core, u32 ctl)
137{
138 u32 volume;
139
140 /* restart dma; This avoids buzz in NICAM and is good in others */
141 cx88_stop_audio_dma(core);
142 cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
143 cx88_start_audio_dma(core);
144
145 if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
146 cx_write(AUD_I2SINPUTCNTL, 4);
147 cx_write(AUD_BAUDRATE, 1);
148 /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
149 cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
150 cx_write(AUD_I2SOUTPUTCNTL, 1);
151 cx_write(AUD_I2SCNTL, 0);
152 /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
153 }
154 if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
155 ctl |= EN_DAC_ENABLE;
156 cx_write(AUD_CTL, ctl);
157 }
158
159 /* finish programming */
160 cx_write(AUD_SOFT_RESET, 0x0000);
161
162 /* unmute */
163 volume = cx_sread(SHADOW_AUD_VOL_CTL);
164 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
165
166 core->last_change = jiffies;
167}
168
169/* ----------------------------------------------------------- */
170
171static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
172 u32 mode)
173{
174 static const struct rlist btsc[] = {
175 {AUD_AFE_12DB_EN, 0x00000001},
176 {AUD_OUT1_SEL, 0x00000013},
177 {AUD_OUT1_SHIFT, 0x00000000},
178 {AUD_POLY0_DDS_CONSTANT, 0x0012010c},
179 {AUD_DMD_RA_DDS, 0x00c3e7aa},
180 {AUD_DBX_IN_GAIN, 0x00004734},
181 {AUD_DBX_WBE_GAIN, 0x00004640},
182 {AUD_DBX_SE_GAIN, 0x00008d31},
183 {AUD_DCOC_0_SRC, 0x0000001a},
184 {AUD_IIR1_4_SEL, 0x00000021},
185 {AUD_DCOC_PASS_IN, 0x00000003},
186 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
187 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
188 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
189 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
190 {AUD_DN0_FREQ, 0x0000283b},
191 {AUD_DN2_SRC_SEL, 0x00000008},
192 {AUD_DN2_FREQ, 0x00003000},
193 {AUD_DN2_AFC, 0x00000002},
194 {AUD_DN2_SHFT, 0x00000000},
195 {AUD_IIR2_2_SEL, 0x00000020},
196 {AUD_IIR2_2_SHIFT, 0x00000000},
197 {AUD_IIR2_3_SEL, 0x0000001f},
198 {AUD_IIR2_3_SHIFT, 0x00000000},
199 {AUD_CRDC1_SRC_SEL, 0x000003ce},
200 {AUD_CRDC1_SHIFT, 0x00000000},
201 {AUD_CORDIC_SHIFT_1, 0x00000007},
202 {AUD_DCOC_1_SRC, 0x0000001b},
203 {AUD_DCOC1_SHIFT, 0x00000000},
204 {AUD_RDSI_SEL, 0x00000008},
205 {AUD_RDSQ_SEL, 0x00000008},
206 {AUD_RDSI_SHIFT, 0x00000000},
207 {AUD_RDSQ_SHIFT, 0x00000000},
208 {AUD_POLYPH80SCALEFAC, 0x00000003},
209 { /* end of list */ },
210 };
211 static const struct rlist btsc_sap[] = {
212 {AUD_AFE_12DB_EN, 0x00000001},
213 {AUD_DBX_IN_GAIN, 0x00007200},
214 {AUD_DBX_WBE_GAIN, 0x00006200},
215 {AUD_DBX_SE_GAIN, 0x00006200},
216 {AUD_IIR1_1_SEL, 0x00000000},
217 {AUD_IIR1_3_SEL, 0x00000001},
218 {AUD_DN1_SRC_SEL, 0x00000007},
219 {AUD_IIR1_4_SHIFT, 0x00000006},
220 {AUD_IIR2_1_SHIFT, 0x00000000},
221 {AUD_IIR2_2_SHIFT, 0x00000000},
222 {AUD_IIR3_0_SHIFT, 0x00000000},
223 {AUD_IIR3_1_SHIFT, 0x00000000},
224 {AUD_IIR3_0_SEL, 0x0000000d},
225 {AUD_IIR3_1_SEL, 0x0000000e},
226 {AUD_DEEMPH1_SRC_SEL, 0x00000014},
227 {AUD_DEEMPH1_SHIFT, 0x00000000},
228 {AUD_DEEMPH1_G0, 0x00004000},
229 {AUD_DEEMPH1_A0, 0x00000000},
230 {AUD_DEEMPH1_B0, 0x00000000},
231 {AUD_DEEMPH1_A1, 0x00000000},
232 {AUD_DEEMPH1_B1, 0x00000000},
233 {AUD_OUT0_SEL, 0x0000003f},
234 {AUD_OUT1_SEL, 0x0000003f},
235 {AUD_DN1_AFC, 0x00000002},
236 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
237 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
238 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
239 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
240 {AUD_IIR1_0_SEL, 0x0000001d},
241 {AUD_IIR1_2_SEL, 0x0000001e},
242 {AUD_IIR2_1_SEL, 0x00000002},
243 {AUD_IIR2_2_SEL, 0x00000004},
244 {AUD_IIR3_2_SEL, 0x0000000f},
245 {AUD_DCOC2_SHIFT, 0x00000001},
246 {AUD_IIR3_2_SHIFT, 0x00000001},
247 {AUD_DEEMPH0_SRC_SEL, 0x00000014},
248 {AUD_CORDIC_SHIFT_1, 0x00000006},
249 {AUD_POLY0_DDS_CONSTANT, 0x000e4db2},
250 {AUD_DMD_RA_DDS, 0x00f696e6},
251 {AUD_IIR2_3_SEL, 0x00000025},
252 {AUD_IIR1_4_SEL, 0x00000021},
253 {AUD_DN1_FREQ, 0x0000c965},
254 {AUD_DCOC_PASS_IN, 0x00000003},
255 {AUD_DCOC_0_SRC, 0x0000001a},
256 {AUD_DCOC_1_SRC, 0x0000001b},
257 {AUD_DCOC1_SHIFT, 0x00000000},
258 {AUD_RDSI_SEL, 0x00000009},
259 {AUD_RDSQ_SEL, 0x00000009},
260 {AUD_RDSI_SHIFT, 0x00000000},
261 {AUD_RDSQ_SHIFT, 0x00000000},
262 {AUD_POLYPH80SCALEFAC, 0x00000003},
263 { /* end of list */ },
264 };
265
266 mode |= EN_FMRADIO_EN_RDS;
267
268 if (sap) {
269 dprintk("%s SAP (status: unknown)\n", __func__);
270 set_audio_start(core, SEL_SAP);
271 set_audio_registers(core, btsc_sap);
272 set_audio_finish(core, mode);
273 } else {
274 dprintk("%s (status: known-good)\n", __func__);
275 set_audio_start(core, SEL_BTSC);
276 set_audio_registers(core, btsc);
277 set_audio_finish(core, mode);
278 }
279}
280
281static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
282{
283 static const struct rlist nicam_l[] = {
284 {AUD_AFE_12DB_EN, 0x00000001},
285 {AUD_RATE_ADJ1, 0x00000060},
286 {AUD_RATE_ADJ2, 0x000000F9},
287 {AUD_RATE_ADJ3, 0x000001CC},
288 {AUD_RATE_ADJ4, 0x000002B3},
289 {AUD_RATE_ADJ5, 0x00000726},
290 {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
291 {AUD_DEEMPHDENOM2_R, 0x00000000},
292 {AUD_ERRLOGPERIOD_R, 0x00000064},
293 {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
294 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
295 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
296 {AUD_POLYPH80SCALEFAC, 0x00000003},
297 {AUD_DMD_RA_DDS, 0x00C00000},
298 {AUD_PLL_INT, 0x0000001E},
299 {AUD_PLL_DDS, 0x00000000},
300 {AUD_PLL_FRAC, 0x0000E542},
301 {AUD_START_TIMER, 0x00000000},
302 {AUD_DEEMPHNUMER1_R, 0x000353DE},
303 {AUD_DEEMPHNUMER2_R, 0x000001B1},
304 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
305 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
306 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
307 {AUD_QAM_MODE, 0x05},
308 {AUD_PHACC_FREQ_8MSB, 0x34},
309 {AUD_PHACC_FREQ_8LSB, 0x4C},
310 {AUD_DEEMPHGAIN_R, 0x00006680},
311 {AUD_RATE_THRES_DMD, 0x000000C0},
312 { /* end of list */ },
313 };
314
315 static const struct rlist nicam_bgdki_common[] = {
316 {AUD_AFE_12DB_EN, 0x00000001},
317 {AUD_RATE_ADJ1, 0x00000010},
318 {AUD_RATE_ADJ2, 0x00000040},
319 {AUD_RATE_ADJ3, 0x00000100},
320 {AUD_RATE_ADJ4, 0x00000400},
321 {AUD_RATE_ADJ5, 0x00001000},
322 {AUD_ERRLOGPERIOD_R, 0x00000fff},
323 {AUD_ERRINTRPTTHSHLD1_R, 0x000003ff},
324 {AUD_ERRINTRPTTHSHLD2_R, 0x000000ff},
325 {AUD_ERRINTRPTTHSHLD3_R, 0x0000003f},
326 {AUD_POLYPH80SCALEFAC, 0x00000003},
327 {AUD_DEEMPHGAIN_R, 0x000023c2},
328 {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
329 {AUD_DEEMPHNUMER2_R, 0x0003023e},
330 {AUD_DEEMPHDENOM1_R, 0x0000f3d0},
331 {AUD_DEEMPHDENOM2_R, 0x00000000},
332 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
333 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
334 {AUD_QAM_MODE, 0x05},
335 { /* end of list */ },
336 };
337
338 static const struct rlist nicam_i[] = {
339 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
340 {AUD_PHACC_FREQ_8MSB, 0x3a},
341 {AUD_PHACC_FREQ_8LSB, 0x93},
342 { /* end of list */ },
343 };
344
345 static const struct rlist nicam_default[] = {
346 {AUD_PDF_DDS_CNST_BYTE0, 0x16},
347 {AUD_PHACC_FREQ_8MSB, 0x34},
348 {AUD_PHACC_FREQ_8LSB, 0x4c},
349 { /* end of list */ },
350 };
351
352 set_audio_start(core,SEL_NICAM);
353 switch (core->tvaudio) {
354 case WW_L:
355 dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
356 set_audio_registers(core, nicam_l);
357 break;
358 case WW_I:
359 dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
360 set_audio_registers(core, nicam_bgdki_common);
361 set_audio_registers(core, nicam_i);
362 break;
363 case WW_NONE:
364 case WW_BTSC:
365 case WW_BG:
366 case WW_DK:
367 case WW_EIAJ:
368 case WW_I2SPT:
369 case WW_FM:
370 case WW_I2SADC:
371 case WW_M:
372 dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
373 set_audio_registers(core, nicam_bgdki_common);
374 set_audio_registers(core, nicam_default);
375 break;
376 };
377
378 mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
379 set_audio_finish(core, mode);
380}
381
382static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
383{
384 static const struct rlist a2_bgdk_common[] = {
385 {AUD_ERRLOGPERIOD_R, 0x00000064},
386 {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
387 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
388 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
389 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
390 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
391 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
392 {AUD_QAM_MODE, 0x05},
393 {AUD_PHACC_FREQ_8MSB, 0x34},
394 {AUD_PHACC_FREQ_8LSB, 0x4c},
395 {AUD_RATE_ADJ1, 0x00000100},
396 {AUD_RATE_ADJ2, 0x00000200},
397 {AUD_RATE_ADJ3, 0x00000300},
398 {AUD_RATE_ADJ4, 0x00000400},
399 {AUD_RATE_ADJ5, 0x00000500},
400 {AUD_THR_FR, 0x00000000},
401 {AAGC_HYST, 0x0000001a},
402 {AUD_PILOT_BQD_1_K0, 0x0000755b},
403 {AUD_PILOT_BQD_1_K1, 0x00551340},
404 {AUD_PILOT_BQD_1_K2, 0x006d30be},
405 {AUD_PILOT_BQD_1_K3, 0xffd394af},
406 {AUD_PILOT_BQD_1_K4, 0x00400000},
407 {AUD_PILOT_BQD_2_K0, 0x00040000},
408 {AUD_PILOT_BQD_2_K1, 0x002a4841},
409 {AUD_PILOT_BQD_2_K2, 0x00400000},
410 {AUD_PILOT_BQD_2_K3, 0x00000000},
411 {AUD_PILOT_BQD_2_K4, 0x00000000},
412 {AUD_MODE_CHG_TIMER, 0x00000040},
413 {AUD_AFE_12DB_EN, 0x00000001},
414 {AUD_CORDIC_SHIFT_0, 0x00000007},
415 {AUD_CORDIC_SHIFT_1, 0x00000007},
416 {AUD_DEEMPH0_G0, 0x00000380},
417 {AUD_DEEMPH1_G0, 0x00000380},
418 {AUD_DCOC_0_SRC, 0x0000001a},
419 {AUD_DCOC0_SHIFT, 0x00000000},
420 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
421 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
422 {AUD_DCOC_PASS_IN, 0x00000003},
423 {AUD_IIR3_0_SEL, 0x00000021},
424 {AUD_DN2_AFC, 0x00000002},
425 {AUD_DCOC_1_SRC, 0x0000001b},
426 {AUD_DCOC1_SHIFT, 0x00000000},
427 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
428 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
429 {AUD_IIR3_1_SEL, 0x00000023},
430 {AUD_RDSI_SEL, 0x00000017},
431 {AUD_RDSI_SHIFT, 0x00000000},
432 {AUD_RDSQ_SEL, 0x00000017},
433 {AUD_RDSQ_SHIFT, 0x00000000},
434 {AUD_PLL_INT, 0x0000001e},
435 {AUD_PLL_DDS, 0x00000000},
436 {AUD_PLL_FRAC, 0x0000e542},
437 {AUD_POLYPH80SCALEFAC, 0x00000001},
438 {AUD_START_TIMER, 0x00000000},
439 { /* end of list */ },
440 };
441
442 static const struct rlist a2_bg[] = {
443 {AUD_DMD_RA_DDS, 0x002a4f2f},
444 {AUD_C1_UP_THR, 0x00007000},
445 {AUD_C1_LO_THR, 0x00005400},
446 {AUD_C2_UP_THR, 0x00005400},
447 {AUD_C2_LO_THR, 0x00003000},
448 { /* end of list */ },
449 };
450
451 static const struct rlist a2_dk[] = {
452 {AUD_DMD_RA_DDS, 0x002a4f2f},
453 {AUD_C1_UP_THR, 0x00007000},
454 {AUD_C1_LO_THR, 0x00005400},
455 {AUD_C2_UP_THR, 0x00005400},
456 {AUD_C2_LO_THR, 0x00003000},
457 {AUD_DN0_FREQ, 0x00003a1c},
458 {AUD_DN2_FREQ, 0x0000d2e0},
459 { /* end of list */ },
460 };
461
462 static const struct rlist a1_i[] = {
463 {AUD_ERRLOGPERIOD_R, 0x00000064},
464 {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
465 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
466 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
467 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
468 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
469 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
470 {AUD_QAM_MODE, 0x05},
471 {AUD_PHACC_FREQ_8MSB, 0x3a},
472 {AUD_PHACC_FREQ_8LSB, 0x93},
473 {AUD_DMD_RA_DDS, 0x002a4f2f},
474 {AUD_PLL_INT, 0x0000001e},
475 {AUD_PLL_DDS, 0x00000004},
476 {AUD_PLL_FRAC, 0x0000e542},
477 {AUD_RATE_ADJ1, 0x00000100},
478 {AUD_RATE_ADJ2, 0x00000200},
479 {AUD_RATE_ADJ3, 0x00000300},
480 {AUD_RATE_ADJ4, 0x00000400},
481 {AUD_RATE_ADJ5, 0x00000500},
482 {AUD_THR_FR, 0x00000000},
483 {AUD_PILOT_BQD_1_K0, 0x0000755b},
484 {AUD_PILOT_BQD_1_K1, 0x00551340},
485 {AUD_PILOT_BQD_1_K2, 0x006d30be},
486 {AUD_PILOT_BQD_1_K3, 0xffd394af},
487 {AUD_PILOT_BQD_1_K4, 0x00400000},
488 {AUD_PILOT_BQD_2_K0, 0x00040000},
489 {AUD_PILOT_BQD_2_K1, 0x002a4841},
490 {AUD_PILOT_BQD_2_K2, 0x00400000},
491 {AUD_PILOT_BQD_2_K3, 0x00000000},
492 {AUD_PILOT_BQD_2_K4, 0x00000000},
493 {AUD_MODE_CHG_TIMER, 0x00000060},
494 {AUD_AFE_12DB_EN, 0x00000001},
495 {AAGC_HYST, 0x0000000a},
496 {AUD_CORDIC_SHIFT_0, 0x00000007},
497 {AUD_CORDIC_SHIFT_1, 0x00000007},
498 {AUD_C1_UP_THR, 0x00007000},
499 {AUD_C1_LO_THR, 0x00005400},
500 {AUD_C2_UP_THR, 0x00005400},
501 {AUD_C2_LO_THR, 0x00003000},
502 {AUD_DCOC_0_SRC, 0x0000001a},
503 {AUD_DCOC0_SHIFT, 0x00000000},
504 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
505 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
506 {AUD_DCOC_PASS_IN, 0x00000003},
507 {AUD_IIR3_0_SEL, 0x00000021},
508 {AUD_DN2_AFC, 0x00000002},
509 {AUD_DCOC_1_SRC, 0x0000001b},
510 {AUD_DCOC1_SHIFT, 0x00000000},
511 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
512 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
513 {AUD_IIR3_1_SEL, 0x00000023},
514 {AUD_DN0_FREQ, 0x000035a3},
515 {AUD_DN2_FREQ, 0x000029c7},
516 {AUD_CRDC0_SRC_SEL, 0x00000511},
517 {AUD_IIR1_0_SEL, 0x00000001},
518 {AUD_IIR1_1_SEL, 0x00000000},
519 {AUD_IIR3_2_SEL, 0x00000003},
520 {AUD_IIR3_2_SHIFT, 0x00000000},
521 {AUD_IIR3_0_SEL, 0x00000002},
522 {AUD_IIR2_0_SEL, 0x00000021},
523 {AUD_IIR2_0_SHIFT, 0x00000002},
524 {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
525 {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
526 {AUD_POLYPH80SCALEFAC, 0x00000001},
527 {AUD_START_TIMER, 0x00000000},
528 { /* end of list */ },
529 };
530
531 static const struct rlist am_l[] = {
532 {AUD_ERRLOGPERIOD_R, 0x00000064},
533 {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
534 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
535 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
536 {AUD_PDF_DDS_CNST_BYTE2, 0x48},
537 {AUD_PDF_DDS_CNST_BYTE1, 0x3D},
538 {AUD_QAM_MODE, 0x00},
539 {AUD_PDF_DDS_CNST_BYTE0, 0xf5},
540 {AUD_PHACC_FREQ_8MSB, 0x3a},
541 {AUD_PHACC_FREQ_8LSB, 0x4a},
542 {AUD_DEEMPHGAIN_R, 0x00006680},
543 {AUD_DEEMPHNUMER1_R, 0x000353DE},
544 {AUD_DEEMPHNUMER2_R, 0x000001B1},
545 {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
546 {AUD_DEEMPHDENOM2_R, 0x00000000},
547 {AUD_FM_MODE_ENABLE, 0x00000007},
548 {AUD_POLYPH80SCALEFAC, 0x00000003},
549 {AUD_AFE_12DB_EN, 0x00000001},
550 {AAGC_GAIN, 0x00000000},
551 {AAGC_HYST, 0x00000018},
552 {AAGC_DEF, 0x00000020},
553 {AUD_DN0_FREQ, 0x00000000},
554 {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2},
555 {AUD_DCOC_0_SRC, 0x00000021},
556 {AUD_IIR1_0_SEL, 0x00000000},
557 {AUD_IIR1_0_SHIFT, 0x00000007},
558 {AUD_IIR1_1_SEL, 0x00000002},
559 {AUD_IIR1_1_SHIFT, 0x00000000},
560 {AUD_DCOC_1_SRC, 0x00000003},
561 {AUD_DCOC1_SHIFT, 0x00000000},
562 {AUD_DCOC_PASS_IN, 0x00000000},
563 {AUD_IIR1_2_SEL, 0x00000023},
564 {AUD_IIR1_2_SHIFT, 0x00000000},
565 {AUD_IIR1_3_SEL, 0x00000004},
566 {AUD_IIR1_3_SHIFT, 0x00000007},
567 {AUD_IIR1_4_SEL, 0x00000005},
568 {AUD_IIR1_4_SHIFT, 0x00000007},
569 {AUD_IIR3_0_SEL, 0x00000007},
570 {AUD_IIR3_0_SHIFT, 0x00000000},
571 {AUD_DEEMPH0_SRC_SEL, 0x00000011},
572 {AUD_DEEMPH0_SHIFT, 0x00000000},
573 {AUD_DEEMPH0_G0, 0x00007000},
574 {AUD_DEEMPH0_A0, 0x00000000},
575 {AUD_DEEMPH0_B0, 0x00000000},
576 {AUD_DEEMPH0_A1, 0x00000000},
577 {AUD_DEEMPH0_B1, 0x00000000},
578 {AUD_DEEMPH1_SRC_SEL, 0x00000011},
579 {AUD_DEEMPH1_SHIFT, 0x00000000},
580 {AUD_DEEMPH1_G0, 0x00007000},
581 {AUD_DEEMPH1_A0, 0x00000000},
582 {AUD_DEEMPH1_B0, 0x00000000},
583 {AUD_DEEMPH1_A1, 0x00000000},
584 {AUD_DEEMPH1_B1, 0x00000000},
585 {AUD_OUT0_SEL, 0x0000003F},
586 {AUD_OUT1_SEL, 0x0000003F},
587 {AUD_DMD_RA_DDS, 0x00F5C285},
588 {AUD_PLL_INT, 0x0000001E},
589 {AUD_PLL_DDS, 0x00000000},
590 {AUD_PLL_FRAC, 0x0000E542},
591 {AUD_RATE_ADJ1, 0x00000100},
592 {AUD_RATE_ADJ2, 0x00000200},
593 {AUD_RATE_ADJ3, 0x00000300},
594 {AUD_RATE_ADJ4, 0x00000400},
595 {AUD_RATE_ADJ5, 0x00000500},
596 {AUD_RATE_THRES_DMD, 0x000000C0},
597 { /* end of list */ },
598 };
599
600 static const struct rlist a2_deemph50[] = {
601 {AUD_DEEMPH0_G0, 0x00000380},
602 {AUD_DEEMPH1_G0, 0x00000380},
603 {AUD_DEEMPHGAIN_R, 0x000011e1},
604 {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
605 {AUD_DEEMPHNUMER2_R, 0x0003023c},
606 { /* end of list */ },
607 };
608
609 set_audio_start(core, SEL_A2);
610 switch (core->tvaudio) {
611 case WW_BG:
612 dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
613 set_audio_registers(core, a2_bgdk_common);
614 set_audio_registers(core, a2_bg);
615 set_audio_registers(core, a2_deemph50);
616 break;
617 case WW_DK:
618 dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
619 set_audio_registers(core, a2_bgdk_common);
620 set_audio_registers(core, a2_dk);
621 set_audio_registers(core, a2_deemph50);
622 break;
623 case WW_I:
624 dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
625 set_audio_registers(core, a1_i);
626 set_audio_registers(core, a2_deemph50);
627 break;
628 case WW_L:
629 dprintk("%s AM-L (status: devel)\n", __func__);
630 set_audio_registers(core, am_l);
631 break;
632 case WW_NONE:
633 case WW_BTSC:
634 case WW_EIAJ:
635 case WW_I2SPT:
636 case WW_FM:
637 case WW_I2SADC:
638 case WW_M:
639 dprintk("%s Warning: wrong value\n", __func__);
640 return;
641 break;
642 };
643
644 mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
645 set_audio_finish(core, mode);
646}
647
648static void set_audio_standard_EIAJ(struct cx88_core *core)
649{
650 static const struct rlist eiaj[] = {
651 /* TODO: eiaj register settings are not there yet ... */
652
653 { /* end of list */ },
654 };
655 dprintk("%s (status: unknown)\n", __func__);
656
657 set_audio_start(core, SEL_EIAJ);
658 set_audio_registers(core, eiaj);
659 set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
660}
661
662static void set_audio_standard_FM(struct cx88_core *core,
663 enum cx88_deemph_type deemph)
664{
665 static const struct rlist fm_deemph_50[] = {
666 {AUD_DEEMPH0_G0, 0x0C45},
667 {AUD_DEEMPH0_A0, 0x6262},
668 {AUD_DEEMPH0_B0, 0x1C29},
669 {AUD_DEEMPH0_A1, 0x3FC66},
670 {AUD_DEEMPH0_B1, 0x399A},
671
672 {AUD_DEEMPH1_G0, 0x0D80},
673 {AUD_DEEMPH1_A0, 0x6262},
674 {AUD_DEEMPH1_B0, 0x1C29},
675 {AUD_DEEMPH1_A1, 0x3FC66},
676 {AUD_DEEMPH1_B1, 0x399A},
677
678 {AUD_POLYPH80SCALEFAC, 0x0003},
679 { /* end of list */ },
680 };
681 static const struct rlist fm_deemph_75[] = {
682 {AUD_DEEMPH0_G0, 0x091B},
683 {AUD_DEEMPH0_A0, 0x6B68},
684 {AUD_DEEMPH0_B0, 0x11EC},
685 {AUD_DEEMPH0_A1, 0x3FC66},
686 {AUD_DEEMPH0_B1, 0x399A},
687
688 {AUD_DEEMPH1_G0, 0x0AA0},
689 {AUD_DEEMPH1_A0, 0x6B68},
690 {AUD_DEEMPH1_B0, 0x11EC},
691 {AUD_DEEMPH1_A1, 0x3FC66},
692 {AUD_DEEMPH1_B1, 0x399A},
693
694 {AUD_POLYPH80SCALEFAC, 0x0003},
695 { /* end of list */ },
696 };
697
698 /* It is enough to leave default values? */
699 /* No, it's not! The deemphasis registers are reset to the 75us
700 * values by default. Analyzing the spectrum of the decoded audio
701 * reveals that "no deemphasis" is the same as 75 us, while the 50 us
702 * setting results in less deemphasis. */
703 static const struct rlist fm_no_deemph[] = {
704
705 {AUD_POLYPH80SCALEFAC, 0x0003},
706 { /* end of list */ },
707 };
708
709 dprintk("%s (status: unknown)\n", __func__);
710 set_audio_start(core, SEL_FMRADIO);
711
712 switch (deemph) {
713 default:
714 case FM_NO_DEEMPH:
715 set_audio_registers(core, fm_no_deemph);
716 break;
717
718 case FM_DEEMPH_50:
719 set_audio_registers(core, fm_deemph_50);
720 break;
721
722 case FM_DEEMPH_75:
723 set_audio_registers(core, fm_deemph_75);
724 break;
725 }
726
727 set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
728}
729
730/* ----------------------------------------------------------- */
731
732static int cx88_detect_nicam(struct cx88_core *core)
733{
734 int i, j = 0;
735
736 dprintk("start nicam autodetect.\n");
737
738 for (i = 0; i < 6; i++) {
739 /* if bit1=1 then nicam is detected */
740 j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
741
742 if (j == 1) {
743 dprintk("nicam is detected.\n");
744 return 1;
745 }
746
747 /* wait a little bit for next reading status */
748 msleep(10);
749 }
750
751 dprintk("nicam is not detected.\n");
752 return 0;
753}
754
755void cx88_set_tvaudio(struct cx88_core *core)
756{
757 switch (core->tvaudio) {
758 case WW_BTSC:
759 set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
760 break;
761 case WW_BG:
762 case WW_DK:
763 case WW_M:
764 case WW_I:
765 case WW_L:
766 /* prepare all dsp registers */
767 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
768
769 /* set nicam mode - otherwise
770 AUD_NICAM_STATUS2 contains wrong values */
771 set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
772 if (0 == cx88_detect_nicam(core)) {
773 /* fall back to fm / am mono */
774 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
775 core->audiomode_current = V4L2_TUNER_MODE_MONO;
776 core->use_nicam = 0;
777 } else {
778 core->use_nicam = 1;
779 }
780 break;
781 case WW_EIAJ:
782 set_audio_standard_EIAJ(core);
783 break;
784 case WW_FM:
785 set_audio_standard_FM(core, radio_deemphasis);
786 break;
787 case WW_I2SADC:
788 set_audio_start(core, 0x01);
789 /*
790 * Slave/Philips/Autobaud
791 * NB on Nova-S bit1 NPhilipsSony appears to be inverted:
792 * 0= Sony, 1=Philips
793 */
794 cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl);
795 /* Switch to "I2S ADC mode" */
796 cx_write(AUD_I2SCNTL, 0x1);
797 set_audio_finish(core, EN_I2SIN_ENABLE);
798 break;
799 case WW_NONE:
800 case WW_I2SPT:
801 printk("%s/0: unknown tv audio mode [%d]\n",
802 core->name, core->tvaudio);
803 break;
804 }
805 return;
806}
807
808void cx88_newstation(struct cx88_core *core)
809{
810 core->audiomode_manual = UNSET;
811 core->last_change = jiffies;
812}
813
814void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
815{
816 static const char * const m[] = { "stereo", "dual mono", "mono", "sap" };
817 static const char * const p[] = { "no pilot", "pilot c1", "pilot c2", "?" };
818 u32 reg, mode, pilot;
819
820 reg = cx_read(AUD_STATUS);
821 mode = reg & 0x03;
822 pilot = (reg >> 2) & 0x03;
823
824 if (core->astat != reg)
825 dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
826 reg, m[mode], p[pilot],
827 aud_ctl_names[cx_read(AUD_CTL) & 63]);
828 core->astat = reg;
829
830 t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
831 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
832 t->rxsubchans = UNSET;
833 t->audmode = V4L2_TUNER_MODE_MONO;
834
835 switch (mode) {
836 case 0:
837 t->audmode = V4L2_TUNER_MODE_STEREO;
838 break;
839 case 1:
840 t->audmode = V4L2_TUNER_MODE_LANG2;
841 break;
842 case 2:
843 t->audmode = V4L2_TUNER_MODE_MONO;
844 break;
845 case 3:
846 t->audmode = V4L2_TUNER_MODE_SAP;
847 break;
848 }
849
850 switch (core->tvaudio) {
851 case WW_BTSC:
852 case WW_BG:
853 case WW_DK:
854 case WW_M:
855 case WW_EIAJ:
856 if (!core->use_nicam) {
857 t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
858 break;
859 }
860 break;
861 case WW_NONE:
862 case WW_I:
863 case WW_L:
864 case WW_I2SPT:
865 case WW_FM:
866 case WW_I2SADC:
867 /* nothing */
868 break;
869 }
870
871 /* If software stereo detection is not supported... */
872 if (UNSET == t->rxsubchans) {
873 t->rxsubchans = V4L2_TUNER_SUB_MONO;
874 /* If the hardware itself detected stereo, also return
875 stereo as an available subchannel */
876 if (V4L2_TUNER_MODE_STEREO == t->audmode)
877 t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
878 }
879 return;
880}
881
882void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
883{
884 u32 ctl = UNSET;
885 u32 mask = UNSET;
886
887 if (manual) {
888 core->audiomode_manual = mode;
889 } else {
890 if (UNSET != core->audiomode_manual)
891 return;
892 }
893 core->audiomode_current = mode;
894
895 switch (core->tvaudio) {
896 case WW_BTSC:
897 switch (mode) {
898 case V4L2_TUNER_MODE_MONO:
899 set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
900 break;
901 case V4L2_TUNER_MODE_LANG1:
902 set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
903 break;
904 case V4L2_TUNER_MODE_LANG2:
905 set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
906 break;
907 case V4L2_TUNER_MODE_STEREO:
908 case V4L2_TUNER_MODE_LANG1_LANG2:
909 set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
910 break;
911 }
912 break;
913 case WW_BG:
914 case WW_DK:
915 case WW_M:
916 case WW_I:
917 case WW_L:
918 if (1 == core->use_nicam) {
919 switch (mode) {
920 case V4L2_TUNER_MODE_MONO:
921 case V4L2_TUNER_MODE_LANG1:
922 set_audio_standard_NICAM(core,
923 EN_NICAM_FORCE_MONO1);
924 break;
925 case V4L2_TUNER_MODE_LANG2:
926 set_audio_standard_NICAM(core,
927 EN_NICAM_FORCE_MONO2);
928 break;
929 case V4L2_TUNER_MODE_STEREO:
930 case V4L2_TUNER_MODE_LANG1_LANG2:
931 set_audio_standard_NICAM(core,
932 EN_NICAM_FORCE_STEREO);
933 break;
934 }
935 } else {
936 if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) {
937 /* fall back to fm / am mono */
938 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
939 } else {
940 /* TODO: Add A2 autodection */
941 mask = 0x3f;
942 switch (mode) {
943 case V4L2_TUNER_MODE_MONO:
944 case V4L2_TUNER_MODE_LANG1:
945 ctl = EN_A2_FORCE_MONO1;
946 break;
947 case V4L2_TUNER_MODE_LANG2:
948 ctl = EN_A2_FORCE_MONO2;
949 break;
950 case V4L2_TUNER_MODE_STEREO:
951 case V4L2_TUNER_MODE_LANG1_LANG2:
952 ctl = EN_A2_FORCE_STEREO;
953 break;
954 }
955 }
956 }
957 break;
958 case WW_FM:
959 switch (mode) {
960 case V4L2_TUNER_MODE_MONO:
961 ctl = EN_FMRADIO_FORCE_MONO;
962 mask = 0x3f;
963 break;
964 case V4L2_TUNER_MODE_STEREO:
965 ctl = EN_FMRADIO_AUTO_STEREO;
966 mask = 0x3f;
967 break;
968 }
969 break;
970 case WW_I2SADC:
971 case WW_NONE:
972 case WW_EIAJ:
973 case WW_I2SPT:
974 /* DO NOTHING */
975 break;
976 }
977
978 if (UNSET != ctl) {
979 dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
980 "[status=0x%x,ctl=0x%x,vol=0x%x]\n",
981 mask, ctl, cx_read(AUD_STATUS),
982 cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
983 cx_andor(AUD_CTL, mask, ctl);
984 }
985 return;
986}
987
988int cx88_audio_thread(void *data)
989{
990 struct cx88_core *core = data;
991 struct v4l2_tuner t;
992 u32 mode = 0;
993
994 dprintk("cx88: tvaudio thread started\n");
995 set_freezable();
996 for (;;) {
997 msleep_interruptible(1000);
998 if (kthread_should_stop())
999 break;
1000 try_to_freeze();
1001
1002 switch (core->tvaudio) {
1003 case WW_BG:
1004 case WW_DK:
1005 case WW_M:
1006 case WW_I:
1007 case WW_L:
1008 if (core->use_nicam)
1009 goto hw_autodetect;
1010
1011 /* just monitor the audio status for now ... */
1012 memset(&t, 0, sizeof(t));
1013 cx88_get_stereo(core, &t);
1014
1015 if (UNSET != core->audiomode_manual)
1016 /* manually set, don't do anything. */
1017 continue;
1018
1019 /* monitor signal and set stereo if available */
1020 if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
1021 mode = V4L2_TUNER_MODE_STEREO;
1022 else
1023 mode = V4L2_TUNER_MODE_MONO;
1024 if (mode == core->audiomode_current)
1025 continue;
1026 /* automatically switch to best available mode */
1027 cx88_set_stereo(core, mode, 0);
1028 break;
1029 case WW_NONE:
1030 case WW_BTSC:
1031 case WW_EIAJ:
1032 case WW_I2SPT:
1033 case WW_FM:
1034 case WW_I2SADC:
1035hw_autodetect:
1036 /* stereo autodetection is supported by hardware so
1037 we don't need to do it manually. Do nothing. */
1038 break;
1039 }
1040 }
1041
1042 dprintk("cx88: tvaudio thread exiting\n");
1043 return 0;
1044}
1045
1046/* ----------------------------------------------------------- */
1047
1048EXPORT_SYMBOL(cx88_set_tvaudio);
1049EXPORT_SYMBOL(cx88_newstation);
1050EXPORT_SYMBOL(cx88_set_stereo);
1051EXPORT_SYMBOL(cx88_get_stereo);
1052EXPORT_SYMBOL(cx88_audio_thread);
1053
1054/*
1055 * Local variables:
1056 * c-basic-offset: 8
1057 * End:
1058 * 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
1059 */
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
new file mode 100644
index 00000000000..f8f8389c036
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -0,0 +1,245 @@
1/*
2 */
3#include <linux/kernel.h>
4#include <linux/module.h>
5#include <linux/init.h>
6
7#include "cx88.h"
8
9static unsigned int vbibufs = 4;
10module_param(vbibufs,int,0644);
11MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
12
13static unsigned int vbi_debug;
14module_param(vbi_debug,int,0644);
15MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
16
17#define dprintk(level,fmt, arg...) if (vbi_debug >= level) \
18 printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)
19
20/* ------------------------------------------------------------------ */
21
22int cx8800_vbi_fmt (struct file *file, void *priv,
23 struct v4l2_format *f)
24{
25 struct cx8800_fh *fh = priv;
26 struct cx8800_dev *dev = fh->dev;
27
28 f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
29 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
30 f->fmt.vbi.offset = 244;
31 f->fmt.vbi.count[0] = VBI_LINE_COUNT;
32 f->fmt.vbi.count[1] = VBI_LINE_COUNT;
33
34 if (dev->core->tvnorm & V4L2_STD_525_60) {
35 /* ntsc */
36 f->fmt.vbi.sampling_rate = 28636363;
37 f->fmt.vbi.start[0] = 10;
38 f->fmt.vbi.start[1] = 273;
39
40 } else if (dev->core->tvnorm & V4L2_STD_625_50) {
41 /* pal */
42 f->fmt.vbi.sampling_rate = 35468950;
43 f->fmt.vbi.start[0] = 7 -1;
44 f->fmt.vbi.start[1] = 319 -1;
45 }
46 return 0;
47}
48
49static int cx8800_start_vbi_dma(struct cx8800_dev *dev,
50 struct cx88_dmaqueue *q,
51 struct cx88_buffer *buf)
52{
53 struct cx88_core *core = dev->core;
54
55 /* setup fifo + format */
56 cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
57 buf->vb.width, buf->risc.dma);
58
59 cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup
60 (1 << 15) | // enable vbi capture
61 (1 << 11) ));
62
63 /* reset counter */
64 cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);
65 q->count = 1;
66
67 /* enable irqs */
68 cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
69 cx_set(MO_VID_INTMSK, 0x0f0088);
70
71 /* enable capture */
72 cx_set(VID_CAPTURE_CONTROL,0x18);
73
74 /* start dma */
75 cx_set(MO_DEV_CNTRL2, (1<<5));
76 cx_set(MO_VID_DMACNTRL, 0x88);
77
78 return 0;
79}
80
81int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
82{
83 struct cx88_core *core = dev->core;
84
85 /* stop dma */
86 cx_clear(MO_VID_DMACNTRL, 0x88);
87
88 /* disable capture */
89 cx_clear(VID_CAPTURE_CONTROL,0x18);
90
91 /* disable irqs */
92 cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
93 cx_clear(MO_VID_INTMSK, 0x0f0088);
94 return 0;
95}
96
97int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
98 struct cx88_dmaqueue *q)
99{
100 struct cx88_buffer *buf;
101
102 if (list_empty(&q->active))
103 return 0;
104
105 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
106 dprintk(2,"restart_queue [%p/%d]: restart dma\n",
107 buf, buf->vb.i);
108 cx8800_start_vbi_dma(dev, q, buf);
109 list_for_each_entry(buf, &q->active, vb.queue)
110 buf->count = q->count++;
111 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
112 return 0;
113}
114
115void cx8800_vbi_timeout(unsigned long data)
116{
117 struct cx8800_dev *dev = (struct cx8800_dev*)data;
118 struct cx88_core *core = dev->core;
119 struct cx88_dmaqueue *q = &dev->vbiq;
120 struct cx88_buffer *buf;
121 unsigned long flags;
122
123 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]);
124
125 cx_clear(MO_VID_DMACNTRL, 0x88);
126 cx_clear(VID_CAPTURE_CONTROL, 0x18);
127
128 spin_lock_irqsave(&dev->slock,flags);
129 while (!list_empty(&q->active)) {
130 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
131 list_del(&buf->vb.queue);
132 buf->vb.state = VIDEOBUF_ERROR;
133 wake_up(&buf->vb.done);
134 printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,
135 buf, buf->vb.i, (unsigned long)buf->risc.dma);
136 }
137 cx8800_restart_vbi_queue(dev,q);
138 spin_unlock_irqrestore(&dev->slock,flags);
139}
140
141/* ------------------------------------------------------------------ */
142
143static int
144vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
145{
146 *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
147 if (0 == *count)
148 *count = vbibufs;
149 if (*count < 2)
150 *count = 2;
151 if (*count > 32)
152 *count = 32;
153 return 0;
154}
155
156static int
157vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
158 enum v4l2_field field)
159{
160 struct cx8800_fh *fh = q->priv_data;
161 struct cx8800_dev *dev = fh->dev;
162 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
163 unsigned int size;
164 int rc;
165
166 size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
167 if (0 != buf->vb.baddr && buf->vb.bsize < size)
168 return -EINVAL;
169
170 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
171 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
172 buf->vb.width = VBI_LINE_LENGTH;
173 buf->vb.height = VBI_LINE_COUNT;
174 buf->vb.size = size;
175 buf->vb.field = V4L2_FIELD_SEQ_TB;
176
177 if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
178 goto fail;
179 cx88_risc_buffer(dev->pci, &buf->risc,
180 dma->sglist,
181 0, buf->vb.width * buf->vb.height,
182 buf->vb.width, 0,
183 buf->vb.height);
184 }
185 buf->vb.state = VIDEOBUF_PREPARED;
186 return 0;
187
188 fail:
189 cx88_free_buffer(q,buf);
190 return rc;
191}
192
193static void
194vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
195{
196 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
197 struct cx88_buffer *prev;
198 struct cx8800_fh *fh = vq->priv_data;
199 struct cx8800_dev *dev = fh->dev;
200 struct cx88_dmaqueue *q = &dev->vbiq;
201
202 /* add jump to stopper */
203 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
204 buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
205
206 if (list_empty(&q->active)) {
207 list_add_tail(&buf->vb.queue,&q->active);
208 cx8800_start_vbi_dma(dev, q, buf);
209 buf->vb.state = VIDEOBUF_ACTIVE;
210 buf->count = q->count++;
211 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
212 dprintk(2,"[%p/%d] vbi_queue - first active\n",
213 buf, buf->vb.i);
214
215 } else {
216 prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
217 list_add_tail(&buf->vb.queue,&q->active);
218 buf->vb.state = VIDEOBUF_ACTIVE;
219 buf->count = q->count++;
220 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
221 dprintk(2,"[%p/%d] buffer_queue - append to active\n",
222 buf, buf->vb.i);
223 }
224}
225
226static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
227{
228 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
229
230 cx88_free_buffer(q,buf);
231}
232
233const struct videobuf_queue_ops cx8800_vbi_qops = {
234 .buf_setup = vbi_setup,
235 .buf_prepare = vbi_prepare,
236 .buf_queue = vbi_queue,
237 .buf_release = vbi_release,
238};
239
240/* ------------------------------------------------------------------ */
241/*
242 * Local variables:
243 * c-basic-offset: 8
244 * End:
245 */
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
new file mode 100644
index 00000000000..60d28fdd779
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -0,0 +1,2194 @@
1/*
2 *
3 * device driver for Conexant 2388x based TV cards
4 * video4linux video interface
5 *
6 * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7 *
8 * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
9 * - Multituner support
10 * - video_ioctl2 conversion
11 * - PAL/M fixes
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28#include <linux/init.h>
29#include <linux/list.h>
30#include <linux/module.h>
31#include <linux/kmod.h>
32#include <linux/kernel.h>
33#include <linux/slab.h>
34#include <linux/interrupt.h>
35#include <linux/dma-mapping.h>
36#include <linux/delay.h>
37#include <linux/kthread.h>
38#include <asm/div64.h>
39
40#include "cx88.h"
41#include <media/v4l2-common.h>
42#include <media/v4l2-ioctl.h>
43#include <media/wm8775.h>
44
45MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
46MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
47MODULE_LICENSE("GPL");
48MODULE_VERSION(CX88_VERSION);
49
50/* ------------------------------------------------------------------ */
51
52static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
53static unsigned int vbi_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
54static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
55
56module_param_array(video_nr, int, NULL, 0444);
57module_param_array(vbi_nr, int, NULL, 0444);
58module_param_array(radio_nr, int, NULL, 0444);
59
60MODULE_PARM_DESC(video_nr,"video device numbers");
61MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
62MODULE_PARM_DESC(radio_nr,"radio device numbers");
63
64static unsigned int video_debug;
65module_param(video_debug,int,0644);
66MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
67
68static unsigned int irq_debug;
69module_param(irq_debug,int,0644);
70MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
71
72static unsigned int vid_limit = 16;
73module_param(vid_limit,int,0644);
74MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
75
76#define dprintk(level,fmt, arg...) if (video_debug >= level) \
77 printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
78
79/* ------------------------------------------------------------------- */
80/* static data */
81
82static const struct cx8800_fmt formats[] = {
83 {
84 .name = "8 bpp, gray",
85 .fourcc = V4L2_PIX_FMT_GREY,
86 .cxformat = ColorFormatY8,
87 .depth = 8,
88 .flags = FORMAT_FLAGS_PACKED,
89 },{
90 .name = "15 bpp RGB, le",
91 .fourcc = V4L2_PIX_FMT_RGB555,
92 .cxformat = ColorFormatRGB15,
93 .depth = 16,
94 .flags = FORMAT_FLAGS_PACKED,
95 },{
96 .name = "15 bpp RGB, be",
97 .fourcc = V4L2_PIX_FMT_RGB555X,
98 .cxformat = ColorFormatRGB15 | ColorFormatBSWAP,
99 .depth = 16,
100 .flags = FORMAT_FLAGS_PACKED,
101 },{
102 .name = "16 bpp RGB, le",
103 .fourcc = V4L2_PIX_FMT_RGB565,
104 .cxformat = ColorFormatRGB16,
105 .depth = 16,
106 .flags = FORMAT_FLAGS_PACKED,
107 },{
108 .name = "16 bpp RGB, be",
109 .fourcc = V4L2_PIX_FMT_RGB565X,
110 .cxformat = ColorFormatRGB16 | ColorFormatBSWAP,
111 .depth = 16,
112 .flags = FORMAT_FLAGS_PACKED,
113 },{
114 .name = "24 bpp RGB, le",
115 .fourcc = V4L2_PIX_FMT_BGR24,
116 .cxformat = ColorFormatRGB24,
117 .depth = 24,
118 .flags = FORMAT_FLAGS_PACKED,
119 },{
120 .name = "32 bpp RGB, le",
121 .fourcc = V4L2_PIX_FMT_BGR32,
122 .cxformat = ColorFormatRGB32,
123 .depth = 32,
124 .flags = FORMAT_FLAGS_PACKED,
125 },{
126 .name = "32 bpp RGB, be",
127 .fourcc = V4L2_PIX_FMT_RGB32,
128 .cxformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP,
129 .depth = 32,
130 .flags = FORMAT_FLAGS_PACKED,
131 },{
132 .name = "4:2:2, packed, YUYV",
133 .fourcc = V4L2_PIX_FMT_YUYV,
134 .cxformat = ColorFormatYUY2,
135 .depth = 16,
136 .flags = FORMAT_FLAGS_PACKED,
137 },{
138 .name = "4:2:2, packed, UYVY",
139 .fourcc = V4L2_PIX_FMT_UYVY,
140 .cxformat = ColorFormatYUY2 | ColorFormatBSWAP,
141 .depth = 16,
142 .flags = FORMAT_FLAGS_PACKED,
143 },
144};
145
146static const struct cx8800_fmt* format_by_fourcc(unsigned int fourcc)
147{
148 unsigned int i;
149
150 for (i = 0; i < ARRAY_SIZE(formats); i++)
151 if (formats[i].fourcc == fourcc)
152 return formats+i;
153 return NULL;
154}
155
156/* ------------------------------------------------------------------- */
157
158static const struct v4l2_queryctrl no_ctl = {
159 .name = "42",
160 .flags = V4L2_CTRL_FLAG_DISABLED,
161};
162
163static const struct cx88_ctrl cx8800_ctls[] = {
164 /* --- video --- */
165 {
166 .v = {
167 .id = V4L2_CID_BRIGHTNESS,
168 .name = "Brightness",
169 .minimum = 0x00,
170 .maximum = 0xff,
171 .step = 1,
172 .default_value = 0x7f,
173 .type = V4L2_CTRL_TYPE_INTEGER,
174 },
175 .off = 128,
176 .reg = MO_CONTR_BRIGHT,
177 .mask = 0x00ff,
178 .shift = 0,
179 },{
180 .v = {
181 .id = V4L2_CID_CONTRAST,
182 .name = "Contrast",
183 .minimum = 0,
184 .maximum = 0xff,
185 .step = 1,
186 .default_value = 0x3f,
187 .type = V4L2_CTRL_TYPE_INTEGER,
188 },
189 .off = 0,
190 .reg = MO_CONTR_BRIGHT,
191 .mask = 0xff00,
192 .shift = 8,
193 },{
194 .v = {
195 .id = V4L2_CID_HUE,
196 .name = "Hue",
197 .minimum = 0,
198 .maximum = 0xff,
199 .step = 1,
200 .default_value = 0x7f,
201 .type = V4L2_CTRL_TYPE_INTEGER,
202 },
203 .off = 128,
204 .reg = MO_HUE,
205 .mask = 0x00ff,
206 .shift = 0,
207 },{
208 /* strictly, this only describes only U saturation.
209 * V saturation is handled specially through code.
210 */
211 .v = {
212 .id = V4L2_CID_SATURATION,
213 .name = "Saturation",
214 .minimum = 0,
215 .maximum = 0xff,
216 .step = 1,
217 .default_value = 0x7f,
218 .type = V4L2_CTRL_TYPE_INTEGER,
219 },
220 .off = 0,
221 .reg = MO_UV_SATURATION,
222 .mask = 0x00ff,
223 .shift = 0,
224 }, {
225 .v = {
226 .id = V4L2_CID_SHARPNESS,
227 .name = "Sharpness",
228 .minimum = 0,
229 .maximum = 4,
230 .step = 1,
231 .default_value = 0x0,
232 .type = V4L2_CTRL_TYPE_INTEGER,
233 },
234 .off = 0,
235 /* NOTE: the value is converted and written to both even
236 and odd registers in the code */
237 .reg = MO_FILTER_ODD,
238 .mask = 7 << 7,
239 .shift = 7,
240 }, {
241 .v = {
242 .id = V4L2_CID_CHROMA_AGC,
243 .name = "Chroma AGC",
244 .minimum = 0,
245 .maximum = 1,
246 .default_value = 0x1,
247 .type = V4L2_CTRL_TYPE_BOOLEAN,
248 },
249 .reg = MO_INPUT_FORMAT,
250 .mask = 1 << 10,
251 .shift = 10,
252 }, {
253 .v = {
254 .id = V4L2_CID_COLOR_KILLER,
255 .name = "Color killer",
256 .minimum = 0,
257 .maximum = 1,
258 .default_value = 0x1,
259 .type = V4L2_CTRL_TYPE_BOOLEAN,
260 },
261 .reg = MO_INPUT_FORMAT,
262 .mask = 1 << 9,
263 .shift = 9,
264 }, {
265 .v = {
266 .id = V4L2_CID_BAND_STOP_FILTER,
267 .name = "Notch filter",
268 .minimum = 0,
269 .maximum = 3,
270 .step = 1,
271 .default_value = 0x0,
272 .type = V4L2_CTRL_TYPE_INTEGER,
273 },
274 .off = 0,
275 .reg = MO_HTOTAL,
276 .mask = 3 << 11,
277 .shift = 11,
278 }, {
279 /* --- audio --- */
280 .v = {
281 .id = V4L2_CID_AUDIO_MUTE,
282 .name = "Mute",
283 .minimum = 0,
284 .maximum = 1,
285 .default_value = 1,
286 .type = V4L2_CTRL_TYPE_BOOLEAN,
287 },
288 .reg = AUD_VOL_CTL,
289 .sreg = SHADOW_AUD_VOL_CTL,
290 .mask = (1 << 6),
291 .shift = 6,
292 },{
293 .v = {
294 .id = V4L2_CID_AUDIO_VOLUME,
295 .name = "Volume",
296 .minimum = 0,
297 .maximum = 0x3f,
298 .step = 1,
299 .default_value = 0x3f,
300 .type = V4L2_CTRL_TYPE_INTEGER,
301 },
302 .reg = AUD_VOL_CTL,
303 .sreg = SHADOW_AUD_VOL_CTL,
304 .mask = 0x3f,
305 .shift = 0,
306 },{
307 .v = {
308 .id = V4L2_CID_AUDIO_BALANCE,
309 .name = "Balance",
310 .minimum = 0,
311 .maximum = 0x7f,
312 .step = 1,
313 .default_value = 0x40,
314 .type = V4L2_CTRL_TYPE_INTEGER,
315 },
316 .reg = AUD_BAL_CTL,
317 .sreg = SHADOW_AUD_BAL_CTL,
318 .mask = 0x7f,
319 .shift = 0,
320 }
321};
322enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) };
323
324/* Must be sorted from low to high control ID! */
325const u32 cx88_user_ctrls[] = {
326 V4L2_CID_USER_CLASS,
327 V4L2_CID_BRIGHTNESS,
328 V4L2_CID_CONTRAST,
329 V4L2_CID_SATURATION,
330 V4L2_CID_HUE,
331 V4L2_CID_AUDIO_VOLUME,
332 V4L2_CID_AUDIO_BALANCE,
333 V4L2_CID_AUDIO_MUTE,
334 V4L2_CID_SHARPNESS,
335 V4L2_CID_CHROMA_AGC,
336 V4L2_CID_COLOR_KILLER,
337 V4L2_CID_BAND_STOP_FILTER,
338 0
339};
340EXPORT_SYMBOL(cx88_user_ctrls);
341
342static const u32 * const ctrl_classes[] = {
343 cx88_user_ctrls,
344 NULL
345};
346
347int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl)
348{
349 int i;
350
351 if (qctrl->id < V4L2_CID_BASE ||
352 qctrl->id >= V4L2_CID_LASTP1)
353 return -EINVAL;
354 for (i = 0; i < CX8800_CTLS; i++)
355 if (cx8800_ctls[i].v.id == qctrl->id)
356 break;
357 if (i == CX8800_CTLS) {
358 *qctrl = no_ctl;
359 return 0;
360 }
361 *qctrl = cx8800_ctls[i].v;
362 /* Report chroma AGC as inactive when SECAM is selected */
363 if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC &&
364 core->tvnorm & V4L2_STD_SECAM)
365 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
366
367 return 0;
368}
369EXPORT_SYMBOL(cx8800_ctrl_query);
370
371/* ------------------------------------------------------------------- */
372/* resource management */
373
374static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
375{
376 struct cx88_core *core = dev->core;
377 if (fh->resources & bit)
378 /* have it already allocated */
379 return 1;
380
381 /* is it free? */
382 mutex_lock(&core->lock);
383 if (dev->resources & bit) {
384 /* no, someone else uses it */
385 mutex_unlock(&core->lock);
386 return 0;
387 }
388 /* it's free, grab it */
389 fh->resources |= bit;
390 dev->resources |= bit;
391 dprintk(1,"res: get %d\n",bit);
392 mutex_unlock(&core->lock);
393 return 1;
394}
395
396static
397int res_check(struct cx8800_fh *fh, unsigned int bit)
398{
399 return (fh->resources & bit);
400}
401
402static
403int res_locked(struct cx8800_dev *dev, unsigned int bit)
404{
405 return (dev->resources & bit);
406}
407
408static
409void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
410{
411 struct cx88_core *core = dev->core;
412 BUG_ON((fh->resources & bits) != bits);
413
414 mutex_lock(&core->lock);
415 fh->resources &= ~bits;
416 dev->resources &= ~bits;
417 dprintk(1,"res: put %d\n",bits);
418 mutex_unlock(&core->lock);
419}
420
421/* ------------------------------------------------------------------ */
422
423int cx88_video_mux(struct cx88_core *core, unsigned int input)
424{
425 /* struct cx88_core *core = dev->core; */
426
427 dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
428 input, INPUT(input).vmux,
429 INPUT(input).gpio0,INPUT(input).gpio1,
430 INPUT(input).gpio2,INPUT(input).gpio3);
431 core->input = input;
432 cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14);
433 cx_write(MO_GP3_IO, INPUT(input).gpio3);
434 cx_write(MO_GP0_IO, INPUT(input).gpio0);
435 cx_write(MO_GP1_IO, INPUT(input).gpio1);
436 cx_write(MO_GP2_IO, INPUT(input).gpio2);
437
438 switch (INPUT(input).type) {
439 case CX88_VMUX_SVIDEO:
440 cx_set(MO_AFECFG_IO, 0x00000001);
441 cx_set(MO_INPUT_FORMAT, 0x00010010);
442 cx_set(MO_FILTER_EVEN, 0x00002020);
443 cx_set(MO_FILTER_ODD, 0x00002020);
444 break;
445 default:
446 cx_clear(MO_AFECFG_IO, 0x00000001);
447 cx_clear(MO_INPUT_FORMAT, 0x00010010);
448 cx_clear(MO_FILTER_EVEN, 0x00002020);
449 cx_clear(MO_FILTER_ODD, 0x00002020);
450 break;
451 }
452
453 /* if there are audioroutes defined, we have an external
454 ADC to deal with audio */
455 if (INPUT(input).audioroute) {
456 /* The wm8775 module has the "2" route hardwired into
457 the initialization. Some boards may use different
458 routes for different inputs. HVR-1300 surely does */
459 if (core->board.audio_chip &&
460 core->board.audio_chip == V4L2_IDENT_WM8775) {
461 call_all(core, audio, s_routing,
462 INPUT(input).audioroute, 0, 0);
463 }
464 /* cx2388's C-ADC is connected to the tuner only.
465 When used with S-Video, that ADC is busy dealing with
466 chroma, so an external must be used for baseband audio */
467 if (INPUT(input).type != CX88_VMUX_TELEVISION &&
468 INPUT(input).type != CX88_VMUX_CABLE) {
469 /* "I2S ADC mode" */
470 core->tvaudio = WW_I2SADC;
471 cx88_set_tvaudio(core);
472 } else {
473 /* Normal mode */
474 cx_write(AUD_I2SCNTL, 0x0);
475 cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
476 }
477 }
478
479 return 0;
480}
481EXPORT_SYMBOL(cx88_video_mux);
482
483/* ------------------------------------------------------------------ */
484
485static int start_video_dma(struct cx8800_dev *dev,
486 struct cx88_dmaqueue *q,
487 struct cx88_buffer *buf)
488{
489 struct cx88_core *core = dev->core;
490
491 /* setup fifo + format */
492 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
493 buf->bpl, buf->risc.dma);
494 cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
495 cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
496
497 /* reset counter */
498 cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
499 q->count = 1;
500
501 /* enable irqs */
502 cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
503
504 /* Enables corresponding bits at PCI_INT_STAT:
505 bits 0 to 4: video, audio, transport stream, VIP, Host
506 bit 7: timer
507 bits 8 and 9: DMA complete for: SRC, DST
508 bits 10 and 11: BERR signal asserted for RISC: RD, WR
509 bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
510 */
511 cx_set(MO_VID_INTMSK, 0x0f0011);
512
513 /* enable capture */
514 cx_set(VID_CAPTURE_CONTROL,0x06);
515
516 /* start dma */
517 cx_set(MO_DEV_CNTRL2, (1<<5));
518 cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */
519
520 return 0;
521}
522
523#ifdef CONFIG_PM
524static int stop_video_dma(struct cx8800_dev *dev)
525{
526 struct cx88_core *core = dev->core;
527
528 /* stop dma */
529 cx_clear(MO_VID_DMACNTRL, 0x11);
530
531 /* disable capture */
532 cx_clear(VID_CAPTURE_CONTROL,0x06);
533
534 /* disable irqs */
535 cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
536 cx_clear(MO_VID_INTMSK, 0x0f0011);
537 return 0;
538}
539#endif
540
541static int restart_video_queue(struct cx8800_dev *dev,
542 struct cx88_dmaqueue *q)
543{
544 struct cx88_core *core = dev->core;
545 struct cx88_buffer *buf, *prev;
546
547 if (!list_empty(&q->active)) {
548 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
549 dprintk(2,"restart_queue [%p/%d]: restart dma\n",
550 buf, buf->vb.i);
551 start_video_dma(dev, q, buf);
552 list_for_each_entry(buf, &q->active, vb.queue)
553 buf->count = q->count++;
554 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
555 return 0;
556 }
557
558 prev = NULL;
559 for (;;) {
560 if (list_empty(&q->queued))
561 return 0;
562 buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
563 if (NULL == prev) {
564 list_move_tail(&buf->vb.queue, &q->active);
565 start_video_dma(dev, q, buf);
566 buf->vb.state = VIDEOBUF_ACTIVE;
567 buf->count = q->count++;
568 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
569 dprintk(2,"[%p/%d] restart_queue - first active\n",
570 buf,buf->vb.i);
571
572 } else if (prev->vb.width == buf->vb.width &&
573 prev->vb.height == buf->vb.height &&
574 prev->fmt == buf->fmt) {
575 list_move_tail(&buf->vb.queue, &q->active);
576 buf->vb.state = VIDEOBUF_ACTIVE;
577 buf->count = q->count++;
578 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
579 dprintk(2,"[%p/%d] restart_queue - move to active\n",
580 buf,buf->vb.i);
581 } else {
582 return 0;
583 }
584 prev = buf;
585 }
586}
587
588/* ------------------------------------------------------------------ */
589
590static int
591buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
592{
593 struct cx8800_fh *fh = q->priv_data;
594
595 *size = fh->fmt->depth*fh->width*fh->height >> 3;
596 if (0 == *count)
597 *count = 32;
598 if (*size * *count > vid_limit * 1024 * 1024)
599 *count = (vid_limit * 1024 * 1024) / *size;
600 return 0;
601}
602
603static int
604buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
605 enum v4l2_field field)
606{
607 struct cx8800_fh *fh = q->priv_data;
608 struct cx8800_dev *dev = fh->dev;
609 struct cx88_core *core = dev->core;
610 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
611 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
612 int rc, init_buffer = 0;
613
614 BUG_ON(NULL == fh->fmt);
615 if (fh->width < 48 || fh->width > norm_maxw(core->tvnorm) ||
616 fh->height < 32 || fh->height > norm_maxh(core->tvnorm))
617 return -EINVAL;
618 buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
619 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
620 return -EINVAL;
621
622 if (buf->fmt != fh->fmt ||
623 buf->vb.width != fh->width ||
624 buf->vb.height != fh->height ||
625 buf->vb.field != field) {
626 buf->fmt = fh->fmt;
627 buf->vb.width = fh->width;
628 buf->vb.height = fh->height;
629 buf->vb.field = field;
630 init_buffer = 1;
631 }
632
633 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
634 init_buffer = 1;
635 if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
636 goto fail;
637 }
638
639 if (init_buffer) {
640 buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
641 switch (buf->vb.field) {
642 case V4L2_FIELD_TOP:
643 cx88_risc_buffer(dev->pci, &buf->risc,
644 dma->sglist, 0, UNSET,
645 buf->bpl, 0, buf->vb.height);
646 break;
647 case V4L2_FIELD_BOTTOM:
648 cx88_risc_buffer(dev->pci, &buf->risc,
649 dma->sglist, UNSET, 0,
650 buf->bpl, 0, buf->vb.height);
651 break;
652 case V4L2_FIELD_INTERLACED:
653 cx88_risc_buffer(dev->pci, &buf->risc,
654 dma->sglist, 0, buf->bpl,
655 buf->bpl, buf->bpl,
656 buf->vb.height >> 1);
657 break;
658 case V4L2_FIELD_SEQ_TB:
659 cx88_risc_buffer(dev->pci, &buf->risc,
660 dma->sglist,
661 0, buf->bpl * (buf->vb.height >> 1),
662 buf->bpl, 0,
663 buf->vb.height >> 1);
664 break;
665 case V4L2_FIELD_SEQ_BT:
666 cx88_risc_buffer(dev->pci, &buf->risc,
667 dma->sglist,
668 buf->bpl * (buf->vb.height >> 1), 0,
669 buf->bpl, 0,
670 buf->vb.height >> 1);
671 break;
672 default:
673 BUG();
674 }
675 }
676 dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
677 buf, buf->vb.i,
678 fh->width, fh->height, fh->fmt->depth, fh->fmt->name,
679 (unsigned long)buf->risc.dma);
680
681 buf->vb.state = VIDEOBUF_PREPARED;
682 return 0;
683
684 fail:
685 cx88_free_buffer(q,buf);
686 return rc;
687}
688
689static void
690buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
691{
692 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
693 struct cx88_buffer *prev;
694 struct cx8800_fh *fh = vq->priv_data;
695 struct cx8800_dev *dev = fh->dev;
696 struct cx88_core *core = dev->core;
697 struct cx88_dmaqueue *q = &dev->vidq;
698
699 /* add jump to stopper */
700 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
701 buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
702
703 if (!list_empty(&q->queued)) {
704 list_add_tail(&buf->vb.queue,&q->queued);
705 buf->vb.state = VIDEOBUF_QUEUED;
706 dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
707 buf, buf->vb.i);
708
709 } else if (list_empty(&q->active)) {
710 list_add_tail(&buf->vb.queue,&q->active);
711 start_video_dma(dev, q, buf);
712 buf->vb.state = VIDEOBUF_ACTIVE;
713 buf->count = q->count++;
714 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
715 dprintk(2,"[%p/%d] buffer_queue - first active\n",
716 buf, buf->vb.i);
717
718 } else {
719 prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
720 if (prev->vb.width == buf->vb.width &&
721 prev->vb.height == buf->vb.height &&
722 prev->fmt == buf->fmt) {
723 list_add_tail(&buf->vb.queue,&q->active);
724 buf->vb.state = VIDEOBUF_ACTIVE;
725 buf->count = q->count++;
726 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
727 dprintk(2,"[%p/%d] buffer_queue - append to active\n",
728 buf, buf->vb.i);
729
730 } else {
731 list_add_tail(&buf->vb.queue,&q->queued);
732 buf->vb.state = VIDEOBUF_QUEUED;
733 dprintk(2,"[%p/%d] buffer_queue - first queued\n",
734 buf, buf->vb.i);
735 }
736 }
737}
738
739static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
740{
741 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
742
743 cx88_free_buffer(q,buf);
744}
745
746static const struct videobuf_queue_ops cx8800_video_qops = {
747 .buf_setup = buffer_setup,
748 .buf_prepare = buffer_prepare,
749 .buf_queue = buffer_queue,
750 .buf_release = buffer_release,
751};
752
753/* ------------------------------------------------------------------ */
754
755
756/* ------------------------------------------------------------------ */
757
758static struct videobuf_queue* get_queue(struct cx8800_fh *fh)
759{
760 switch (fh->type) {
761 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
762 return &fh->vidq;
763 case V4L2_BUF_TYPE_VBI_CAPTURE:
764 return &fh->vbiq;
765 default:
766 BUG();
767 return NULL;
768 }
769}
770
771static int get_ressource(struct cx8800_fh *fh)
772{
773 switch (fh->type) {
774 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
775 return RESOURCE_VIDEO;
776 case V4L2_BUF_TYPE_VBI_CAPTURE:
777 return RESOURCE_VBI;
778 default:
779 BUG();
780 return 0;
781 }
782}
783
784static int video_open(struct file *file)
785{
786 struct video_device *vdev = video_devdata(file);
787 struct cx8800_dev *dev = video_drvdata(file);
788 struct cx88_core *core = dev->core;
789 struct cx8800_fh *fh;
790 enum v4l2_buf_type type = 0;
791 int radio = 0;
792
793 switch (vdev->vfl_type) {
794 case VFL_TYPE_GRABBER:
795 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
796 break;
797 case VFL_TYPE_VBI:
798 type = V4L2_BUF_TYPE_VBI_CAPTURE;
799 break;
800 case VFL_TYPE_RADIO:
801 radio = 1;
802 break;
803 }
804
805 dprintk(1, "open dev=%s radio=%d type=%s\n",
806 video_device_node_name(vdev), radio, v4l2_type_names[type]);
807
808 /* allocate + initialize per filehandle data */
809 fh = kzalloc(sizeof(*fh),GFP_KERNEL);
810 if (unlikely(!fh))
811 return -ENOMEM;
812
813 file->private_data = fh;
814 fh->dev = dev;
815 fh->radio = radio;
816 fh->type = type;
817 fh->width = 320;
818 fh->height = 240;
819 fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
820
821 mutex_lock(&core->lock);
822
823 videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
824 &dev->pci->dev, &dev->slock,
825 V4L2_BUF_TYPE_VIDEO_CAPTURE,
826 V4L2_FIELD_INTERLACED,
827 sizeof(struct cx88_buffer),
828 fh, NULL);
829 videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
830 &dev->pci->dev, &dev->slock,
831 V4L2_BUF_TYPE_VBI_CAPTURE,
832 V4L2_FIELD_SEQ_TB,
833 sizeof(struct cx88_buffer),
834 fh, NULL);
835
836 if (fh->radio) {
837 dprintk(1,"video_open: setting radio device\n");
838 cx_write(MO_GP3_IO, core->board.radio.gpio3);
839 cx_write(MO_GP0_IO, core->board.radio.gpio0);
840 cx_write(MO_GP1_IO, core->board.radio.gpio1);
841 cx_write(MO_GP2_IO, core->board.radio.gpio2);
842 if (core->board.radio.audioroute) {
843 if(core->board.audio_chip &&
844 core->board.audio_chip == V4L2_IDENT_WM8775) {
845 call_all(core, audio, s_routing,
846 core->board.radio.audioroute, 0, 0);
847 }
848 /* "I2S ADC mode" */
849 core->tvaudio = WW_I2SADC;
850 cx88_set_tvaudio(core);
851 } else {
852 /* FM Mode */
853 core->tvaudio = WW_FM;
854 cx88_set_tvaudio(core);
855 cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
856 }
857 call_all(core, tuner, s_radio);
858 }
859
860 core->users++;
861 mutex_unlock(&core->lock);
862
863 return 0;
864}
865
866static ssize_t
867video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
868{
869 struct cx8800_fh *fh = file->private_data;
870
871 switch (fh->type) {
872 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
873 if (res_locked(fh->dev,RESOURCE_VIDEO))
874 return -EBUSY;
875 return videobuf_read_one(&fh->vidq, data, count, ppos,
876 file->f_flags & O_NONBLOCK);
877 case V4L2_BUF_TYPE_VBI_CAPTURE:
878 if (!res_get(fh->dev,fh,RESOURCE_VBI))
879 return -EBUSY;
880 return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
881 file->f_flags & O_NONBLOCK);
882 default:
883 BUG();
884 return 0;
885 }
886}
887
888static unsigned int
889video_poll(struct file *file, struct poll_table_struct *wait)
890{
891 struct cx8800_fh *fh = file->private_data;
892 struct cx88_buffer *buf;
893 unsigned int rc = POLLERR;
894
895 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
896 if (!res_get(fh->dev,fh,RESOURCE_VBI))
897 return POLLERR;
898 return videobuf_poll_stream(file, &fh->vbiq, wait);
899 }
900
901 mutex_lock(&fh->vidq.vb_lock);
902 if (res_check(fh,RESOURCE_VIDEO)) {
903 /* streaming capture */
904 if (list_empty(&fh->vidq.stream))
905 goto done;
906 buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
907 } else {
908 /* read() capture */
909 buf = (struct cx88_buffer*)fh->vidq.read_buf;
910 if (NULL == buf)
911 goto done;
912 }
913 poll_wait(file, &buf->vb.done, wait);
914 if (buf->vb.state == VIDEOBUF_DONE ||
915 buf->vb.state == VIDEOBUF_ERROR)
916 rc = POLLIN|POLLRDNORM;
917 else
918 rc = 0;
919done:
920 mutex_unlock(&fh->vidq.vb_lock);
921 return rc;
922}
923
924static int video_release(struct file *file)
925{
926 struct cx8800_fh *fh = file->private_data;
927 struct cx8800_dev *dev = fh->dev;
928
929 /* turn off overlay */
930 if (res_check(fh, RESOURCE_OVERLAY)) {
931 /* FIXME */
932 res_free(dev,fh,RESOURCE_OVERLAY);
933 }
934
935 /* stop video capture */
936 if (res_check(fh, RESOURCE_VIDEO)) {
937 videobuf_queue_cancel(&fh->vidq);
938 res_free(dev,fh,RESOURCE_VIDEO);
939 }
940 if (fh->vidq.read_buf) {
941 buffer_release(&fh->vidq,fh->vidq.read_buf);
942 kfree(fh->vidq.read_buf);
943 }
944
945 /* stop vbi capture */
946 if (res_check(fh, RESOURCE_VBI)) {
947 videobuf_stop(&fh->vbiq);
948 res_free(dev,fh,RESOURCE_VBI);
949 }
950
951 videobuf_mmap_free(&fh->vidq);
952 videobuf_mmap_free(&fh->vbiq);
953
954 mutex_lock(&dev->core->lock);
955 file->private_data = NULL;
956 kfree(fh);
957
958 dev->core->users--;
959 if (!dev->core->users)
960 call_all(dev->core, core, s_power, 0);
961 mutex_unlock(&dev->core->lock);
962
963 return 0;
964}
965
966static int
967video_mmap(struct file *file, struct vm_area_struct * vma)
968{
969 struct cx8800_fh *fh = file->private_data;
970
971 return videobuf_mmap_mapper(get_queue(fh), vma);
972}
973
974/* ------------------------------------------------------------------ */
975/* VIDEO CTRL IOCTLS */
976
977int cx88_get_control (struct cx88_core *core, struct v4l2_control *ctl)
978{
979 const struct cx88_ctrl *c = NULL;
980 u32 value;
981 int i;
982
983 for (i = 0; i < CX8800_CTLS; i++)
984 if (cx8800_ctls[i].v.id == ctl->id)
985 c = &cx8800_ctls[i];
986 if (unlikely(NULL == c))
987 return -EINVAL;
988
989 value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg);
990 switch (ctl->id) {
991 case V4L2_CID_AUDIO_BALANCE:
992 ctl->value = ((value & 0x7f) < 0x40) ? ((value & 0x7f) + 0x40)
993 : (0x7f - (value & 0x7f));
994 break;
995 case V4L2_CID_AUDIO_VOLUME:
996 ctl->value = 0x3f - (value & 0x3f);
997 break;
998 case V4L2_CID_SHARPNESS:
999 ctl->value = ((value & 0x0200) ? (((value & 0x0180) >> 7) + 1)
1000 : 0);
1001 break;
1002 default:
1003 ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift;
1004 break;
1005 }
1006 dprintk(1,"get_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
1007 ctl->id, c->v.name, ctl->value, c->reg,
1008 value,c->mask, c->sreg ? " [shadowed]" : "");
1009 return 0;
1010}
1011EXPORT_SYMBOL(cx88_get_control);
1012
1013int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
1014{
1015 const struct cx88_ctrl *c = NULL;
1016 u32 value,mask;
1017 int i;
1018
1019 for (i = 0; i < CX8800_CTLS; i++) {
1020 if (cx8800_ctls[i].v.id == ctl->id) {
1021 c = &cx8800_ctls[i];
1022 }
1023 }
1024 if (unlikely(NULL == c))
1025 return -EINVAL;
1026
1027 if (ctl->value < c->v.minimum)
1028 ctl->value = c->v.minimum;
1029 if (ctl->value > c->v.maximum)
1030 ctl->value = c->v.maximum;
1031
1032 /* Pass changes onto any WM8775 */
1033 if (core->board.audio_chip == V4L2_IDENT_WM8775) {
1034 struct v4l2_control client_ctl;
1035 memset(&client_ctl, 0, sizeof(client_ctl));
1036 client_ctl.id = ctl->id;
1037
1038 switch (ctl->id) {
1039 case V4L2_CID_AUDIO_MUTE:
1040 client_ctl.value = ctl->value;
1041 break;
1042 case V4L2_CID_AUDIO_VOLUME:
1043 client_ctl.value = (ctl->value) ?
1044 (0x90 + ctl->value) << 8 : 0;
1045 break;
1046 case V4L2_CID_AUDIO_BALANCE:
1047 client_ctl.value = ctl->value << 9;
1048 break;
1049 default:
1050 client_ctl.id = 0;
1051 break;
1052 }
1053 if (client_ctl.id)
1054 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
1055 }
1056
1057 mask=c->mask;
1058 switch (ctl->id) {
1059 case V4L2_CID_AUDIO_BALANCE:
1060 value = (ctl->value < 0x40) ? (0x7f - ctl->value) : (ctl->value - 0x40);
1061 break;
1062 case V4L2_CID_AUDIO_VOLUME:
1063 value = 0x3f - (ctl->value & 0x3f);
1064 break;
1065 case V4L2_CID_SATURATION:
1066 /* special v_sat handling */
1067
1068 value = ((ctl->value - c->off) << c->shift) & c->mask;
1069
1070 if (core->tvnorm & V4L2_STD_SECAM) {
1071 /* For SECAM, both U and V sat should be equal */
1072 value=value<<8|value;
1073 } else {
1074 /* Keeps U Saturation proportional to V Sat */
1075 value=(value*0x5a)/0x7f<<8|value;
1076 }
1077 mask=0xffff;
1078 break;
1079 case V4L2_CID_SHARPNESS:
1080 /* 0b000, 0b100, 0b101, 0b110, or 0b111 */
1081 value = (ctl->value < 1 ? 0 : ((ctl->value + 3) << 7));
1082 /* needs to be set for both fields */
1083 cx_andor(MO_FILTER_EVEN, mask, value);
1084 break;
1085 case V4L2_CID_CHROMA_AGC:
1086 /* Do not allow chroma AGC to be enabled for SECAM */
1087 value = ((ctl->value - c->off) << c->shift) & c->mask;
1088 if (core->tvnorm & V4L2_STD_SECAM && value)
1089 return -EINVAL;
1090 break;
1091 default:
1092 value = ((ctl->value - c->off) << c->shift) & c->mask;
1093 break;
1094 }
1095 dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
1096 ctl->id, c->v.name, ctl->value, c->reg, value,
1097 mask, c->sreg ? " [shadowed]" : "");
1098 if (c->sreg) {
1099 cx_sandor(c->sreg, c->reg, mask, value);
1100 } else {
1101 cx_andor(c->reg, mask, value);
1102 }
1103 return 0;
1104}
1105EXPORT_SYMBOL(cx88_set_control);
1106
1107static void init_controls(struct cx88_core *core)
1108{
1109 struct v4l2_control ctrl;
1110 int i;
1111
1112 for (i = 0; i < CX8800_CTLS; i++) {
1113 ctrl.id=cx8800_ctls[i].v.id;
1114 ctrl.value=cx8800_ctls[i].v.default_value;
1115
1116 cx88_set_control(core, &ctrl);
1117 }
1118}
1119
1120/* ------------------------------------------------------------------ */
1121/* VIDEO IOCTLS */
1122
1123static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1124 struct v4l2_format *f)
1125{
1126 struct cx8800_fh *fh = priv;
1127
1128 f->fmt.pix.width = fh->width;
1129 f->fmt.pix.height = fh->height;
1130 f->fmt.pix.field = fh->vidq.field;
1131 f->fmt.pix.pixelformat = fh->fmt->fourcc;
1132 f->fmt.pix.bytesperline =
1133 (f->fmt.pix.width * fh->fmt->depth) >> 3;
1134 f->fmt.pix.sizeimage =
1135 f->fmt.pix.height * f->fmt.pix.bytesperline;
1136 return 0;
1137}
1138
1139static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1140 struct v4l2_format *f)
1141{
1142 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1143 const struct cx8800_fmt *fmt;
1144 enum v4l2_field field;
1145 unsigned int maxw, maxh;
1146
1147 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1148 if (NULL == fmt)
1149 return -EINVAL;
1150
1151 field = f->fmt.pix.field;
1152 maxw = norm_maxw(core->tvnorm);
1153 maxh = norm_maxh(core->tvnorm);
1154
1155 if (V4L2_FIELD_ANY == field) {
1156 field = (f->fmt.pix.height > maxh/2)
1157 ? V4L2_FIELD_INTERLACED
1158 : V4L2_FIELD_BOTTOM;
1159 }
1160
1161 switch (field) {
1162 case V4L2_FIELD_TOP:
1163 case V4L2_FIELD_BOTTOM:
1164 maxh = maxh / 2;
1165 break;
1166 case V4L2_FIELD_INTERLACED:
1167 break;
1168 default:
1169 return -EINVAL;
1170 }
1171
1172 f->fmt.pix.field = field;
1173 v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
1174 &f->fmt.pix.height, 32, maxh, 0, 0);
1175 f->fmt.pix.bytesperline =
1176 (f->fmt.pix.width * fmt->depth) >> 3;
1177 f->fmt.pix.sizeimage =
1178 f->fmt.pix.height * f->fmt.pix.bytesperline;
1179
1180 return 0;
1181}
1182
1183static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1184 struct v4l2_format *f)
1185{
1186 struct cx8800_fh *fh = priv;
1187 int err = vidioc_try_fmt_vid_cap (file,priv,f);
1188
1189 if (0 != err)
1190 return err;
1191 fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1192 fh->width = f->fmt.pix.width;
1193 fh->height = f->fmt.pix.height;
1194 fh->vidq.field = f->fmt.pix.field;
1195 return 0;
1196}
1197
1198static int vidioc_querycap (struct file *file, void *priv,
1199 struct v4l2_capability *cap)
1200{
1201 struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev;
1202 struct cx88_core *core = dev->core;
1203
1204 strcpy(cap->driver, "cx8800");
1205 strlcpy(cap->card, core->board.name, sizeof(cap->card));
1206 sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
1207 cap->capabilities =
1208 V4L2_CAP_VIDEO_CAPTURE |
1209 V4L2_CAP_READWRITE |
1210 V4L2_CAP_STREAMING |
1211 V4L2_CAP_VBI_CAPTURE;
1212 if (UNSET != core->board.tuner_type)
1213 cap->capabilities |= V4L2_CAP_TUNER;
1214 return 0;
1215}
1216
1217static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
1218 struct v4l2_fmtdesc *f)
1219{
1220 if (unlikely(f->index >= ARRAY_SIZE(formats)))
1221 return -EINVAL;
1222
1223 strlcpy(f->description,formats[f->index].name,sizeof(f->description));
1224 f->pixelformat = formats[f->index].fourcc;
1225
1226 return 0;
1227}
1228
1229static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
1230{
1231 struct cx8800_fh *fh = priv;
1232 return (videobuf_reqbufs(get_queue(fh), p));
1233}
1234
1235static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
1236{
1237 struct cx8800_fh *fh = priv;
1238 return (videobuf_querybuf(get_queue(fh), p));
1239}
1240
1241static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
1242{
1243 struct cx8800_fh *fh = priv;
1244 return (videobuf_qbuf(get_queue(fh), p));
1245}
1246
1247static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
1248{
1249 struct cx8800_fh *fh = priv;
1250 return (videobuf_dqbuf(get_queue(fh), p,
1251 file->f_flags & O_NONBLOCK));
1252}
1253
1254static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
1255{
1256 struct cx8800_fh *fh = priv;
1257 struct cx8800_dev *dev = fh->dev;
1258
1259 /* We should remember that this driver also supports teletext, */
1260 /* so we have to test if the v4l2_buf_type is VBI capture data. */
1261 if (unlikely((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
1262 (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)))
1263 return -EINVAL;
1264
1265 if (unlikely(i != fh->type))
1266 return -EINVAL;
1267
1268 if (unlikely(!res_get(dev,fh,get_ressource(fh))))
1269 return -EBUSY;
1270 return videobuf_streamon(get_queue(fh));
1271}
1272
1273static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
1274{
1275 struct cx8800_fh *fh = priv;
1276 struct cx8800_dev *dev = fh->dev;
1277 int err, res;
1278
1279 if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
1280 (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
1281 return -EINVAL;
1282
1283 if (i != fh->type)
1284 return -EINVAL;
1285
1286 res = get_ressource(fh);
1287 err = videobuf_streamoff(get_queue(fh));
1288 if (err < 0)
1289 return err;
1290 res_free(dev,fh,res);
1291 return 0;
1292}
1293
1294static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms)
1295{
1296 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1297
1298 mutex_lock(&core->lock);
1299 cx88_set_tvnorm(core,*tvnorms);
1300 mutex_unlock(&core->lock);
1301
1302 return 0;
1303}
1304
1305/* only one input in this sample driver */
1306int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i)
1307{
1308 static const char * const iname[] = {
1309 [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
1310 [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
1311 [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
1312 [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
1313 [ CX88_VMUX_SVIDEO ] = "S-Video",
1314 [ CX88_VMUX_TELEVISION ] = "Television",
1315 [ CX88_VMUX_CABLE ] = "Cable TV",
1316 [ CX88_VMUX_DVB ] = "DVB",
1317 [ CX88_VMUX_DEBUG ] = "for debug only",
1318 };
1319 unsigned int n = i->index;
1320
1321 if (n >= 4)
1322 return -EINVAL;
1323 if (0 == INPUT(n).type)
1324 return -EINVAL;
1325 i->type = V4L2_INPUT_TYPE_CAMERA;
1326 strcpy(i->name,iname[INPUT(n).type]);
1327 if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||
1328 (CX88_VMUX_CABLE == INPUT(n).type)) {
1329 i->type = V4L2_INPUT_TYPE_TUNER;
1330 i->std = CX88_NORMS;
1331 }
1332 return 0;
1333}
1334EXPORT_SYMBOL(cx88_enum_input);
1335
1336static int vidioc_enum_input (struct file *file, void *priv,
1337 struct v4l2_input *i)
1338{
1339 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1340 return cx88_enum_input (core,i);
1341}
1342
1343static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
1344{
1345 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1346
1347 *i = core->input;
1348 return 0;
1349}
1350
1351static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
1352{
1353 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1354
1355 if (i >= 4)
1356 return -EINVAL;
1357
1358 mutex_lock(&core->lock);
1359 cx88_newstation(core);
1360 cx88_video_mux(core,i);
1361 mutex_unlock(&core->lock);
1362 return 0;
1363}
1364
1365
1366
1367static int vidioc_queryctrl (struct file *file, void *priv,
1368 struct v4l2_queryctrl *qctrl)
1369{
1370 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1371
1372 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
1373 if (unlikely(qctrl->id == 0))
1374 return -EINVAL;
1375 return cx8800_ctrl_query(core, qctrl);
1376}
1377
1378static int vidioc_g_ctrl (struct file *file, void *priv,
1379 struct v4l2_control *ctl)
1380{
1381 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1382 return
1383 cx88_get_control(core,ctl);
1384}
1385
1386static int vidioc_s_ctrl (struct file *file, void *priv,
1387 struct v4l2_control *ctl)
1388{
1389 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1390 return
1391 cx88_set_control(core,ctl);
1392}
1393
1394static int vidioc_g_tuner (struct file *file, void *priv,
1395 struct v4l2_tuner *t)
1396{
1397 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1398 u32 reg;
1399
1400 if (unlikely(UNSET == core->board.tuner_type))
1401 return -EINVAL;
1402 if (0 != t->index)
1403 return -EINVAL;
1404
1405 strcpy(t->name, "Television");
1406 t->type = V4L2_TUNER_ANALOG_TV;
1407 t->capability = V4L2_TUNER_CAP_NORM;
1408 t->rangehigh = 0xffffffffUL;
1409
1410 cx88_get_stereo(core ,t);
1411 reg = cx_read(MO_DEVICE_STATUS);
1412 t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
1413 return 0;
1414}
1415
1416static int vidioc_s_tuner (struct file *file, void *priv,
1417 struct v4l2_tuner *t)
1418{
1419 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1420
1421 if (UNSET == core->board.tuner_type)
1422 return -EINVAL;
1423 if (0 != t->index)
1424 return -EINVAL;
1425
1426 cx88_set_stereo(core, t->audmode, 1);
1427 return 0;
1428}
1429
1430static int vidioc_g_frequency (struct file *file, void *priv,
1431 struct v4l2_frequency *f)
1432{
1433 struct cx8800_fh *fh = priv;
1434 struct cx88_core *core = fh->dev->core;
1435
1436 if (unlikely(UNSET == core->board.tuner_type))
1437 return -EINVAL;
1438
1439 /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
1440 f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
1441 f->frequency = core->freq;
1442
1443 call_all(core, tuner, g_frequency, f);
1444
1445 return 0;
1446}
1447
1448int cx88_set_freq (struct cx88_core *core,
1449 struct v4l2_frequency *f)
1450{
1451 if (unlikely(UNSET == core->board.tuner_type))
1452 return -EINVAL;
1453 if (unlikely(f->tuner != 0))
1454 return -EINVAL;
1455
1456 mutex_lock(&core->lock);
1457 core->freq = f->frequency;
1458 cx88_newstation(core);
1459 call_all(core, tuner, s_frequency, f);
1460
1461 /* When changing channels it is required to reset TVAUDIO */
1462 msleep (10);
1463 cx88_set_tvaudio(core);
1464
1465 mutex_unlock(&core->lock);
1466
1467 return 0;
1468}
1469EXPORT_SYMBOL(cx88_set_freq);
1470
1471static int vidioc_s_frequency (struct file *file, void *priv,
1472 struct v4l2_frequency *f)
1473{
1474 struct cx8800_fh *fh = priv;
1475 struct cx88_core *core = fh->dev->core;
1476
1477 if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
1478 return -EINVAL;
1479 if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
1480 return -EINVAL;
1481
1482 return
1483 cx88_set_freq (core,f);
1484}
1485
1486#ifdef CONFIG_VIDEO_ADV_DEBUG
1487static int vidioc_g_register (struct file *file, void *fh,
1488 struct v4l2_dbg_register *reg)
1489{
1490 struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
1491
1492 if (!v4l2_chip_match_host(&reg->match))
1493 return -EINVAL;
1494 /* cx2388x has a 24-bit register space */
1495 reg->val = cx_read(reg->reg & 0xffffff);
1496 reg->size = 4;
1497 return 0;
1498}
1499
1500static int vidioc_s_register (struct file *file, void *fh,
1501 struct v4l2_dbg_register *reg)
1502{
1503 struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
1504
1505 if (!v4l2_chip_match_host(&reg->match))
1506 return -EINVAL;
1507 cx_write(reg->reg & 0xffffff, reg->val);
1508 return 0;
1509}
1510#endif
1511
1512/* ----------------------------------------------------------- */
1513/* RADIO ESPECIFIC IOCTLS */
1514/* ----------------------------------------------------------- */
1515
1516static int radio_querycap (struct file *file, void *priv,
1517 struct v4l2_capability *cap)
1518{
1519 struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev;
1520 struct cx88_core *core = dev->core;
1521
1522 strcpy(cap->driver, "cx8800");
1523 strlcpy(cap->card, core->board.name, sizeof(cap->card));
1524 sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
1525 cap->capabilities = V4L2_CAP_TUNER;
1526 return 0;
1527}
1528
1529static int radio_g_tuner (struct file *file, void *priv,
1530 struct v4l2_tuner *t)
1531{
1532 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1533
1534 if (unlikely(t->index > 0))
1535 return -EINVAL;
1536
1537 strcpy(t->name, "Radio");
1538 t->type = V4L2_TUNER_RADIO;
1539
1540 call_all(core, tuner, g_tuner, t);
1541 return 0;
1542}
1543
1544static int radio_enum_input (struct file *file, void *priv,
1545 struct v4l2_input *i)
1546{
1547 if (i->index != 0)
1548 return -EINVAL;
1549 strcpy(i->name,"Radio");
1550 i->type = V4L2_INPUT_TYPE_TUNER;
1551
1552 return 0;
1553}
1554
1555static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a)
1556{
1557 if (unlikely(a->index))
1558 return -EINVAL;
1559
1560 strcpy(a->name,"Radio");
1561 return 0;
1562}
1563
1564/* FIXME: Should add a standard for radio */
1565
1566static int radio_s_tuner (struct file *file, void *priv,
1567 struct v4l2_tuner *t)
1568{
1569 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1570
1571 if (0 != t->index)
1572 return -EINVAL;
1573
1574 call_all(core, tuner, s_tuner, t);
1575
1576 return 0;
1577}
1578
1579static int radio_s_audio (struct file *file, void *fh,
1580 struct v4l2_audio *a)
1581{
1582 return 0;
1583}
1584
1585static int radio_s_input (struct file *file, void *fh, unsigned int i)
1586{
1587 return 0;
1588}
1589
1590static int radio_queryctrl (struct file *file, void *priv,
1591 struct v4l2_queryctrl *c)
1592{
1593 int i;
1594
1595 if (c->id < V4L2_CID_BASE ||
1596 c->id >= V4L2_CID_LASTP1)
1597 return -EINVAL;
1598 if (c->id == V4L2_CID_AUDIO_MUTE ||
1599 c->id == V4L2_CID_AUDIO_VOLUME ||
1600 c->id == V4L2_CID_AUDIO_BALANCE) {
1601 for (i = 0; i < CX8800_CTLS; i++) {
1602 if (cx8800_ctls[i].v.id == c->id)
1603 break;
1604 }
1605 if (i == CX8800_CTLS)
1606 return -EINVAL;
1607 *c = cx8800_ctls[i].v;
1608 } else
1609 *c = no_ctl;
1610 return 0;
1611}
1612
1613/* ----------------------------------------------------------- */
1614
1615static void cx8800_vid_timeout(unsigned long data)
1616{
1617 struct cx8800_dev *dev = (struct cx8800_dev*)data;
1618 struct cx88_core *core = dev->core;
1619 struct cx88_dmaqueue *q = &dev->vidq;
1620 struct cx88_buffer *buf;
1621 unsigned long flags;
1622
1623 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
1624
1625 cx_clear(MO_VID_DMACNTRL, 0x11);
1626 cx_clear(VID_CAPTURE_CONTROL, 0x06);
1627
1628 spin_lock_irqsave(&dev->slock,flags);
1629 while (!list_empty(&q->active)) {
1630 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
1631 list_del(&buf->vb.queue);
1632 buf->vb.state = VIDEOBUF_ERROR;
1633 wake_up(&buf->vb.done);
1634 printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
1635 buf, buf->vb.i, (unsigned long)buf->risc.dma);
1636 }
1637 restart_video_queue(dev,q);
1638 spin_unlock_irqrestore(&dev->slock,flags);
1639}
1640
1641static const char *cx88_vid_irqs[32] = {
1642 "y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
1643 "y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
1644 "y_oflow", "u_oflow", "v_oflow", "vbi_oflow",
1645 "y_sync", "u_sync", "v_sync", "vbi_sync",
1646 "opc_err", "par_err", "rip_err", "pci_abort",
1647};
1648
1649static void cx8800_vid_irq(struct cx8800_dev *dev)
1650{
1651 struct cx88_core *core = dev->core;
1652 u32 status, mask, count;
1653
1654 status = cx_read(MO_VID_INTSTAT);
1655 mask = cx_read(MO_VID_INTMSK);
1656 if (0 == (status & mask))
1657 return;
1658 cx_write(MO_VID_INTSTAT, status);
1659 if (irq_debug || (status & mask & ~0xff))
1660 cx88_print_irqbits(core->name, "irq vid",
1661 cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs),
1662 status, mask);
1663
1664 /* risc op code error */
1665 if (status & (1 << 16)) {
1666 printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
1667 cx_clear(MO_VID_DMACNTRL, 0x11);
1668 cx_clear(VID_CAPTURE_CONTROL, 0x06);
1669 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
1670 }
1671
1672 /* risc1 y */
1673 if (status & 0x01) {
1674 spin_lock(&dev->slock);
1675 count = cx_read(MO_VIDY_GPCNT);
1676 cx88_wakeup(core, &dev->vidq, count);
1677 spin_unlock(&dev->slock);
1678 }
1679
1680 /* risc1 vbi */
1681 if (status & 0x08) {
1682 spin_lock(&dev->slock);
1683 count = cx_read(MO_VBI_GPCNT);
1684 cx88_wakeup(core, &dev->vbiq, count);
1685 spin_unlock(&dev->slock);
1686 }
1687
1688 /* risc2 y */
1689 if (status & 0x10) {
1690 dprintk(2,"stopper video\n");
1691 spin_lock(&dev->slock);
1692 restart_video_queue(dev,&dev->vidq);
1693 spin_unlock(&dev->slock);
1694 }
1695
1696 /* risc2 vbi */
1697 if (status & 0x80) {
1698 dprintk(2,"stopper vbi\n");
1699 spin_lock(&dev->slock);
1700 cx8800_restart_vbi_queue(dev,&dev->vbiq);
1701 spin_unlock(&dev->slock);
1702 }
1703}
1704
1705static irqreturn_t cx8800_irq(int irq, void *dev_id)
1706{
1707 struct cx8800_dev *dev = dev_id;
1708 struct cx88_core *core = dev->core;
1709 u32 status;
1710 int loop, handled = 0;
1711
1712 for (loop = 0; loop < 10; loop++) {
1713 status = cx_read(MO_PCI_INTSTAT) &
1714 (core->pci_irqmask | PCI_INT_VIDINT);
1715 if (0 == status)
1716 goto out;
1717 cx_write(MO_PCI_INTSTAT, status);
1718 handled = 1;
1719
1720 if (status & core->pci_irqmask)
1721 cx88_core_irq(core,status);
1722 if (status & PCI_INT_VIDINT)
1723 cx8800_vid_irq(dev);
1724 };
1725 if (10 == loop) {
1726 printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
1727 core->name);
1728 cx_write(MO_PCI_INTMSK,0);
1729 }
1730
1731 out:
1732 return IRQ_RETVAL(handled);
1733}
1734
1735/* ----------------------------------------------------------- */
1736/* exported stuff */
1737
1738static const struct v4l2_file_operations video_fops =
1739{
1740 .owner = THIS_MODULE,
1741 .open = video_open,
1742 .release = video_release,
1743 .read = video_read,
1744 .poll = video_poll,
1745 .mmap = video_mmap,
1746 .unlocked_ioctl = video_ioctl2,
1747};
1748
1749static const struct v4l2_ioctl_ops video_ioctl_ops = {
1750 .vidioc_querycap = vidioc_querycap,
1751 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1752 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1753 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1754 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1755 .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt,
1756 .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt,
1757 .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt,
1758 .vidioc_reqbufs = vidioc_reqbufs,
1759 .vidioc_querybuf = vidioc_querybuf,
1760 .vidioc_qbuf = vidioc_qbuf,
1761 .vidioc_dqbuf = vidioc_dqbuf,
1762 .vidioc_s_std = vidioc_s_std,
1763 .vidioc_enum_input = vidioc_enum_input,
1764 .vidioc_g_input = vidioc_g_input,
1765 .vidioc_s_input = vidioc_s_input,
1766 .vidioc_queryctrl = vidioc_queryctrl,
1767 .vidioc_g_ctrl = vidioc_g_ctrl,
1768 .vidioc_s_ctrl = vidioc_s_ctrl,
1769 .vidioc_streamon = vidioc_streamon,
1770 .vidioc_streamoff = vidioc_streamoff,
1771 .vidioc_g_tuner = vidioc_g_tuner,
1772 .vidioc_s_tuner = vidioc_s_tuner,
1773 .vidioc_g_frequency = vidioc_g_frequency,
1774 .vidioc_s_frequency = vidioc_s_frequency,
1775#ifdef CONFIG_VIDEO_ADV_DEBUG
1776 .vidioc_g_register = vidioc_g_register,
1777 .vidioc_s_register = vidioc_s_register,
1778#endif
1779};
1780
1781static struct video_device cx8800_vbi_template;
1782
1783static const struct video_device cx8800_video_template = {
1784 .name = "cx8800-video",
1785 .fops = &video_fops,
1786 .ioctl_ops = &video_ioctl_ops,
1787 .tvnorms = CX88_NORMS,
1788 .current_norm = V4L2_STD_NTSC_M,
1789};
1790
1791static const struct v4l2_file_operations radio_fops =
1792{
1793 .owner = THIS_MODULE,
1794 .open = video_open,
1795 .release = video_release,
1796 .unlocked_ioctl = video_ioctl2,
1797};
1798
1799static const struct v4l2_ioctl_ops radio_ioctl_ops = {
1800 .vidioc_querycap = radio_querycap,
1801 .vidioc_g_tuner = radio_g_tuner,
1802 .vidioc_enum_input = radio_enum_input,
1803 .vidioc_g_audio = radio_g_audio,
1804 .vidioc_s_tuner = radio_s_tuner,
1805 .vidioc_s_audio = radio_s_audio,
1806 .vidioc_s_input = radio_s_input,
1807 .vidioc_queryctrl = radio_queryctrl,
1808 .vidioc_g_ctrl = vidioc_g_ctrl,
1809 .vidioc_s_ctrl = vidioc_s_ctrl,
1810 .vidioc_g_frequency = vidioc_g_frequency,
1811 .vidioc_s_frequency = vidioc_s_frequency,
1812#ifdef CONFIG_VIDEO_ADV_DEBUG
1813 .vidioc_g_register = vidioc_g_register,
1814 .vidioc_s_register = vidioc_s_register,
1815#endif
1816};
1817
1818static const struct video_device cx8800_radio_template = {
1819 .name = "cx8800-radio",
1820 .fops = &radio_fops,
1821 .ioctl_ops = &radio_ioctl_ops,
1822};
1823
1824/* ----------------------------------------------------------- */
1825
1826static void cx8800_unregister_video(struct cx8800_dev *dev)
1827{
1828 if (dev->radio_dev) {
1829 if (video_is_registered(dev->radio_dev))
1830 video_unregister_device(dev->radio_dev);
1831 else
1832 video_device_release(dev->radio_dev);
1833 dev->radio_dev = NULL;
1834 }
1835 if (dev->vbi_dev) {
1836 if (video_is_registered(dev->vbi_dev))
1837 video_unregister_device(dev->vbi_dev);
1838 else
1839 video_device_release(dev->vbi_dev);
1840 dev->vbi_dev = NULL;
1841 }
1842 if (dev->video_dev) {
1843 if (video_is_registered(dev->video_dev))
1844 video_unregister_device(dev->video_dev);
1845 else
1846 video_device_release(dev->video_dev);
1847 dev->video_dev = NULL;
1848 }
1849}
1850
1851static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
1852 const struct pci_device_id *pci_id)
1853{
1854 struct cx8800_dev *dev;
1855 struct cx88_core *core;
1856
1857 int err;
1858
1859 dev = kzalloc(sizeof(*dev),GFP_KERNEL);
1860 if (NULL == dev)
1861 return -ENOMEM;
1862
1863 /* pci init */
1864 dev->pci = pci_dev;
1865 if (pci_enable_device(pci_dev)) {
1866 err = -EIO;
1867 goto fail_free;
1868 }
1869 core = cx88_core_get(dev->pci);
1870 if (NULL == core) {
1871 err = -EINVAL;
1872 goto fail_free;
1873 }
1874 dev->core = core;
1875
1876 /* print pci info */
1877 dev->pci_rev = pci_dev->revision;
1878 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
1879 printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
1880 "latency: %d, mmio: 0x%llx\n", core->name,
1881 pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
1882 dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
1883
1884 pci_set_master(pci_dev);
1885 if (!pci_dma_supported(pci_dev,DMA_BIT_MASK(32))) {
1886 printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
1887 err = -EIO;
1888 goto fail_core;
1889 }
1890
1891 /* Initialize VBI template */
1892 memcpy( &cx8800_vbi_template, &cx8800_video_template,
1893 sizeof(cx8800_vbi_template) );
1894 strcpy(cx8800_vbi_template.name,"cx8800-vbi");
1895
1896 /* initialize driver struct */
1897 spin_lock_init(&dev->slock);
1898 core->tvnorm = cx8800_video_template.current_norm;
1899
1900 /* init video dma queues */
1901 INIT_LIST_HEAD(&dev->vidq.active);
1902 INIT_LIST_HEAD(&dev->vidq.queued);
1903 dev->vidq.timeout.function = cx8800_vid_timeout;
1904 dev->vidq.timeout.data = (unsigned long)dev;
1905 init_timer(&dev->vidq.timeout);
1906 cx88_risc_stopper(dev->pci,&dev->vidq.stopper,
1907 MO_VID_DMACNTRL,0x11,0x00);
1908
1909 /* init vbi dma queues */
1910 INIT_LIST_HEAD(&dev->vbiq.active);
1911 INIT_LIST_HEAD(&dev->vbiq.queued);
1912 dev->vbiq.timeout.function = cx8800_vbi_timeout;
1913 dev->vbiq.timeout.data = (unsigned long)dev;
1914 init_timer(&dev->vbiq.timeout);
1915 cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,
1916 MO_VID_DMACNTRL,0x88,0x00);
1917
1918 /* get irq */
1919 err = request_irq(pci_dev->irq, cx8800_irq,
1920 IRQF_SHARED | IRQF_DISABLED, core->name, dev);
1921 if (err < 0) {
1922 printk(KERN_ERR "%s/0: can't get IRQ %d\n",
1923 core->name,pci_dev->irq);
1924 goto fail_core;
1925 }
1926 cx_set(MO_PCI_INTMSK, core->pci_irqmask);
1927
1928 /* load and configure helper modules */
1929
1930 if (core->board.audio_chip == V4L2_IDENT_WM8775) {
1931 struct i2c_board_info wm8775_info = {
1932 .type = "wm8775",
1933 .addr = 0x36 >> 1,
1934 .platform_data = &core->wm8775_data,
1935 };
1936 struct v4l2_subdev *sd;
1937
1938 if (core->boardnr == CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1)
1939 core->wm8775_data.is_nova_s = true;
1940 else
1941 core->wm8775_data.is_nova_s = false;
1942
1943 sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap,
1944 &wm8775_info, NULL);
1945 if (sd != NULL)
1946 sd->grp_id = WM8775_GID;
1947 }
1948
1949 if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
1950 /* This probes for a tda9874 as is used on some
1951 Pixelview Ultra boards. */
1952 v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
1953 "tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
1954 }
1955
1956 switch (core->boardnr) {
1957 case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
1958 case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: {
1959 static const struct i2c_board_info rtc_info = {
1960 I2C_BOARD_INFO("isl1208", 0x6f)
1961 };
1962
1963 request_module("rtc-isl1208");
1964 core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info);
1965 }
1966 /* break intentionally omitted */
1967 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
1968 request_module("ir-kbd-i2c");
1969 }
1970
1971 /* Sets device info at pci_dev */
1972 pci_set_drvdata(pci_dev, dev);
1973
1974 /* initial device configuration */
1975 mutex_lock(&core->lock);
1976 cx88_set_tvnorm(core, core->tvnorm);
1977 init_controls(core);
1978 cx88_video_mux(core, 0);
1979
1980 /* register v4l devices */
1981 dev->video_dev = cx88_vdev_init(core,dev->pci,
1982 &cx8800_video_template,"video");
1983 video_set_drvdata(dev->video_dev, dev);
1984 err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
1985 video_nr[core->nr]);
1986 if (err < 0) {
1987 printk(KERN_ERR "%s/0: can't register video device\n",
1988 core->name);
1989 goto fail_unreg;
1990 }
1991 printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
1992 core->name, video_device_node_name(dev->video_dev));
1993
1994 dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
1995 video_set_drvdata(dev->vbi_dev, dev);
1996 err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
1997 vbi_nr[core->nr]);
1998 if (err < 0) {
1999 printk(KERN_ERR "%s/0: can't register vbi device\n",
2000 core->name);
2001 goto fail_unreg;
2002 }
2003 printk(KERN_INFO "%s/0: registered device %s\n",
2004 core->name, video_device_node_name(dev->vbi_dev));
2005
2006 if (core->board.radio.type == CX88_RADIO) {
2007 dev->radio_dev = cx88_vdev_init(core,dev->pci,
2008 &cx8800_radio_template,"radio");
2009 video_set_drvdata(dev->radio_dev, dev);
2010 err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
2011 radio_nr[core->nr]);
2012 if (err < 0) {
2013 printk(KERN_ERR "%s/0: can't register radio device\n",
2014 core->name);
2015 goto fail_unreg;
2016 }
2017 printk(KERN_INFO "%s/0: registered device %s\n",
2018 core->name, video_device_node_name(dev->radio_dev));
2019 }
2020
2021 /* start tvaudio thread */
2022 if (core->board.tuner_type != TUNER_ABSENT) {
2023 core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
2024 if (IS_ERR(core->kthread)) {
2025 err = PTR_ERR(core->kthread);
2026 printk(KERN_ERR "%s/0: failed to create cx88 audio thread, err=%d\n",
2027 core->name, err);
2028 }
2029 }
2030 mutex_unlock(&core->lock);
2031
2032 return 0;
2033
2034fail_unreg:
2035 cx8800_unregister_video(dev);
2036 free_irq(pci_dev->irq, dev);
2037 mutex_unlock(&core->lock);
2038fail_core:
2039 cx88_core_put(core,dev->pci);
2040fail_free:
2041 kfree(dev);
2042 return err;
2043}
2044
2045static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
2046{
2047 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
2048 struct cx88_core *core = dev->core;
2049
2050 /* stop thread */
2051 if (core->kthread) {
2052 kthread_stop(core->kthread);
2053 core->kthread = NULL;
2054 }
2055
2056 if (core->ir)
2057 cx88_ir_stop(core);
2058
2059 cx88_shutdown(core); /* FIXME */
2060 pci_disable_device(pci_dev);
2061
2062 /* unregister stuff */
2063
2064 free_irq(pci_dev->irq, dev);
2065 cx8800_unregister_video(dev);
2066 pci_set_drvdata(pci_dev, NULL);
2067
2068 /* free memory */
2069 btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
2070 cx88_core_put(core,dev->pci);
2071 kfree(dev);
2072}
2073
2074#ifdef CONFIG_PM
2075static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
2076{
2077 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
2078 struct cx88_core *core = dev->core;
2079
2080 /* stop video+vbi capture */
2081 spin_lock(&dev->slock);
2082 if (!list_empty(&dev->vidq.active)) {
2083 printk("%s/0: suspend video\n", core->name);
2084 stop_video_dma(dev);
2085 del_timer(&dev->vidq.timeout);
2086 }
2087 if (!list_empty(&dev->vbiq.active)) {
2088 printk("%s/0: suspend vbi\n", core->name);
2089 cx8800_stop_vbi_dma(dev);
2090 del_timer(&dev->vbiq.timeout);
2091 }
2092 spin_unlock(&dev->slock);
2093
2094 if (core->ir)
2095 cx88_ir_stop(core);
2096 /* FIXME -- shutdown device */
2097 cx88_shutdown(core);
2098
2099 pci_save_state(pci_dev);
2100 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
2101 pci_disable_device(pci_dev);
2102 dev->state.disabled = 1;
2103 }
2104 return 0;
2105}
2106
2107static int cx8800_resume(struct pci_dev *pci_dev)
2108{
2109 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
2110 struct cx88_core *core = dev->core;
2111 int err;
2112
2113 if (dev->state.disabled) {
2114 err=pci_enable_device(pci_dev);
2115 if (err) {
2116 printk(KERN_ERR "%s/0: can't enable device\n",
2117 core->name);
2118 return err;
2119 }
2120
2121 dev->state.disabled = 0;
2122 }
2123 err= pci_set_power_state(pci_dev, PCI_D0);
2124 if (err) {
2125 printk(KERN_ERR "%s/0: can't set power state\n", core->name);
2126 pci_disable_device(pci_dev);
2127 dev->state.disabled = 1;
2128
2129 return err;
2130 }
2131 pci_restore_state(pci_dev);
2132
2133 /* FIXME: re-initialize hardware */
2134 cx88_reset(core);
2135 if (core->ir)
2136 cx88_ir_start(core);
2137
2138 cx_set(MO_PCI_INTMSK, core->pci_irqmask);
2139
2140 /* restart video+vbi capture */
2141 spin_lock(&dev->slock);
2142 if (!list_empty(&dev->vidq.active)) {
2143 printk("%s/0: resume video\n", core->name);
2144 restart_video_queue(dev,&dev->vidq);
2145 }
2146 if (!list_empty(&dev->vbiq.active)) {
2147 printk("%s/0: resume vbi\n", core->name);
2148 cx8800_restart_vbi_queue(dev,&dev->vbiq);
2149 }
2150 spin_unlock(&dev->slock);
2151
2152 return 0;
2153}
2154#endif
2155
2156/* ----------------------------------------------------------- */
2157
2158static const struct pci_device_id cx8800_pci_tbl[] = {
2159 {
2160 .vendor = 0x14f1,
2161 .device = 0x8800,
2162 .subvendor = PCI_ANY_ID,
2163 .subdevice = PCI_ANY_ID,
2164 },{
2165 /* --- end of list --- */
2166 }
2167};
2168MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl);
2169
2170static struct pci_driver cx8800_pci_driver = {
2171 .name = "cx8800",
2172 .id_table = cx8800_pci_tbl,
2173 .probe = cx8800_initdev,
2174 .remove = __devexit_p(cx8800_finidev),
2175#ifdef CONFIG_PM
2176 .suspend = cx8800_suspend,
2177 .resume = cx8800_resume,
2178#endif
2179};
2180
2181static int __init cx8800_init(void)
2182{
2183 printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %s loaded\n",
2184 CX88_VERSION);
2185 return pci_register_driver(&cx8800_pci_driver);
2186}
2187
2188static void __exit cx8800_fini(void)
2189{
2190 pci_unregister_driver(&cx8800_pci_driver);
2191}
2192
2193module_init(cx8800_init);
2194module_exit(cx8800_fini);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
new file mode 100644
index 00000000000..d77f8ecab9d
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -0,0 +1,159 @@
1/*
2
3 cx88-vp3054-i2c.c -- support for the secondary I2C bus of the
4 DNTV Live! DVB-T Pro (VP-3054), wired as:
5 GPIO[0] -> SCL, GPIO[1] -> SDA
6
7 (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23*/
24
25#include <linux/module.h>
26#include <linux/slab.h>
27#include <linux/init.h>
28
29#include <asm/io.h>
30
31#include "cx88.h"
32#include "cx88-vp3054-i2c.h"
33
34MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
35MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
36MODULE_LICENSE("GPL");
37
38/* ----------------------------------------------------------------------- */
39
40static void vp3054_bit_setscl(void *data, int state)
41{
42 struct cx8802_dev *dev = data;
43 struct cx88_core *core = dev->core;
44 struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
45
46 if (state) {
47 vp3054_i2c->state |= 0x0001; /* SCL high */
48 vp3054_i2c->state &= ~0x0100; /* external pullup */
49 } else {
50 vp3054_i2c->state &= ~0x0001; /* SCL low */
51 vp3054_i2c->state |= 0x0100; /* drive pin */
52 }
53 cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);
54 cx_read(MO_GP0_IO);
55}
56
57static void vp3054_bit_setsda(void *data, int state)
58{
59 struct cx8802_dev *dev = data;
60 struct cx88_core *core = dev->core;
61 struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
62
63 if (state) {
64 vp3054_i2c->state |= 0x0002; /* SDA high */
65 vp3054_i2c->state &= ~0x0200; /* tristate pin */
66 } else {
67 vp3054_i2c->state &= ~0x0002; /* SDA low */
68 vp3054_i2c->state |= 0x0200; /* drive pin */
69 }
70 cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);
71 cx_read(MO_GP0_IO);
72}
73
74static int vp3054_bit_getscl(void *data)
75{
76 struct cx8802_dev *dev = data;
77 struct cx88_core *core = dev->core;
78 u32 state;
79
80 state = cx_read(MO_GP0_IO);
81 return (state & 0x01) ? 1 : 0;
82}
83
84static int vp3054_bit_getsda(void *data)
85{
86 struct cx8802_dev *dev = data;
87 struct cx88_core *core = dev->core;
88 u32 state;
89
90 state = cx_read(MO_GP0_IO);
91 return (state & 0x02) ? 1 : 0;
92}
93
94/* ----------------------------------------------------------------------- */
95
96static const struct i2c_algo_bit_data vp3054_i2c_algo_template = {
97 .setsda = vp3054_bit_setsda,
98 .setscl = vp3054_bit_setscl,
99 .getsda = vp3054_bit_getsda,
100 .getscl = vp3054_bit_getscl,
101 .udelay = 16,
102 .timeout = 200,
103};
104
105/* ----------------------------------------------------------------------- */
106
107int vp3054_i2c_probe(struct cx8802_dev *dev)
108{
109 struct cx88_core *core = dev->core;
110 struct vp3054_i2c_state *vp3054_i2c;
111 int rc;
112
113 if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
114 return 0;
115
116 vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
117 if (vp3054_i2c == NULL)
118 return -ENOMEM;
119 dev->vp3054 = vp3054_i2c;
120
121 memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
122 sizeof(vp3054_i2c->algo));
123
124 vp3054_i2c->adap.dev.parent = &dev->pci->dev;
125 strlcpy(vp3054_i2c->adap.name, core->name,
126 sizeof(vp3054_i2c->adap.name));
127 vp3054_i2c->adap.owner = THIS_MODULE;
128 vp3054_i2c->algo.data = dev;
129 i2c_set_adapdata(&vp3054_i2c->adap, dev);
130 vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
131
132 vp3054_bit_setscl(dev,1);
133 vp3054_bit_setsda(dev,1);
134
135 rc = i2c_bit_add_bus(&vp3054_i2c->adap);
136 if (0 != rc) {
137 printk("%s: vp3054_i2c register FAILED\n", core->name);
138
139 kfree(dev->vp3054);
140 dev->vp3054 = NULL;
141 }
142
143 return rc;
144}
145
146void vp3054_i2c_remove(struct cx8802_dev *dev)
147{
148 struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
149
150 if (vp3054_i2c == NULL ||
151 dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
152 return;
153
154 i2c_del_adapter(&vp3054_i2c->adap);
155 kfree(vp3054_i2c);
156}
157
158EXPORT_SYMBOL(vp3054_i2c_probe);
159EXPORT_SYMBOL(vp3054_i2c_remove);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h
new file mode 100644
index 00000000000..be99c931dc3
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h
@@ -0,0 +1,41 @@
1/*
2
3 cx88-vp3054-i2c.h -- support for the secondary I2C bus of the
4 DNTV Live! DVB-T Pro (VP-3054), wired as:
5 GPIO[0] -> SCL, GPIO[1] -> SDA
6
7 (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23*/
24
25/* ----------------------------------------------------------------------- */
26struct vp3054_i2c_state {
27 struct i2c_adapter adap;
28 struct i2c_algo_bit_data algo;
29 u32 state;
30};
31
32/* ----------------------------------------------------------------------- */
33#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
34int vp3054_i2c_probe(struct cx8802_dev *dev);
35void vp3054_i2c_remove(struct cx8802_dev *dev);
36#else
37static inline int vp3054_i2c_probe(struct cx8802_dev *dev)
38{ return 0; }
39static inline void vp3054_i2c_remove(struct cx8802_dev *dev)
40{ }
41#endif
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
new file mode 100644
index 00000000000..fa8d307e1a3
--- /dev/null
+++ b/drivers/media/video/cx88/cx88.h
@@ -0,0 +1,730 @@
1/*
2 *
3 * v4l2 device driver for cx2388x based TV cards
4 *
5 * (c) 2003,04 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/pci.h>
23#include <linux/i2c.h>
24#include <linux/i2c-algo-bit.h>
25#include <linux/videodev2.h>
26#include <linux/kdev_t.h>
27
28#include <media/v4l2-device.h>
29#include <media/tuner.h>
30#include <media/tveeprom.h>
31#include <media/videobuf-dma-sg.h>
32#include <media/v4l2-chip-ident.h>
33#include <media/cx2341x.h>
34#include <media/videobuf-dvb.h>
35#include <media/ir-kbd-i2c.h>
36#include <media/wm8775.h>
37
38#include "btcx-risc.h"
39#include "cx88-reg.h"
40#include "tuner-xc2028.h"
41
42#include <linux/mutex.h>
43
44#define CX88_VERSION "0.0.9"
45
46#define UNSET (-1U)
47
48#define CX88_MAXBOARDS 8
49
50/* Max number of inputs by card */
51#define MAX_CX88_INPUT 8
52
53/* ----------------------------------------------------------- */
54/* defines and enums */
55
56/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM/LC */
57#define CX88_NORMS (V4L2_STD_ALL \
58 & ~V4L2_STD_PAL_H \
59 & ~V4L2_STD_NTSC_M_KR \
60 & ~V4L2_STD_SECAM_LC)
61
62#define FORMAT_FLAGS_PACKED 0x01
63#define FORMAT_FLAGS_PLANAR 0x02
64
65#define VBI_LINE_COUNT 17
66#define VBI_LINE_LENGTH 2048
67
68#define AUD_RDS_LINES 4
69
70/* need "shadow" registers for some write-only ones ... */
71#define SHADOW_AUD_VOL_CTL 1
72#define SHADOW_AUD_BAL_CTL 2
73#define SHADOW_MAX 3
74
75/* FM Radio deemphasis type */
76enum cx88_deemph_type {
77 FM_NO_DEEMPH = 0,
78 FM_DEEMPH_50,
79 FM_DEEMPH_75
80};
81
82enum cx88_board_type {
83 CX88_BOARD_NONE = 0,
84 CX88_MPEG_DVB,
85 CX88_MPEG_BLACKBIRD
86};
87
88enum cx8802_board_access {
89 CX8802_DRVCTL_SHARED = 1,
90 CX8802_DRVCTL_EXCLUSIVE = 2,
91};
92
93/* ----------------------------------------------------------- */
94/* tv norms */
95
96static unsigned int inline norm_maxw(v4l2_std_id norm)
97{
98 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
99}
100
101
102static unsigned int inline norm_maxh(v4l2_std_id norm)
103{
104 return (norm & V4L2_STD_625_50) ? 576 : 480;
105}
106
107/* ----------------------------------------------------------- */
108/* static data */
109
110struct cx8800_fmt {
111 const char *name;
112 u32 fourcc; /* v4l2 format id */
113 int depth;
114 int flags;
115 u32 cxformat;
116};
117
118struct cx88_ctrl {
119 struct v4l2_queryctrl v;
120 u32 off;
121 u32 reg;
122 u32 sreg;
123 u32 mask;
124 u32 shift;
125};
126
127/* ----------------------------------------------------------- */
128/* SRAM memory management data (see cx88-core.c) */
129
130#define SRAM_CH21 0 /* video */
131#define SRAM_CH22 1
132#define SRAM_CH23 2
133#define SRAM_CH24 3 /* vbi */
134#define SRAM_CH25 4 /* audio */
135#define SRAM_CH26 5
136#define SRAM_CH28 6 /* mpeg */
137#define SRAM_CH27 7 /* audio rds */
138/* more */
139
140struct sram_channel {
141 const char *name;
142 u32 cmds_start;
143 u32 ctrl_start;
144 u32 cdt;
145 u32 fifo_start;
146 u32 fifo_size;
147 u32 ptr1_reg;
148 u32 ptr2_reg;
149 u32 cnt1_reg;
150 u32 cnt2_reg;
151};
152extern const struct sram_channel const cx88_sram_channels[];
153
154/* ----------------------------------------------------------- */
155/* card configuration */
156
157#define CX88_BOARD_NOAUTO UNSET
158#define CX88_BOARD_UNKNOWN 0
159#define CX88_BOARD_HAUPPAUGE 1
160#define CX88_BOARD_GDI 2
161#define CX88_BOARD_PIXELVIEW 3
162#define CX88_BOARD_ATI_WONDER_PRO 4
163#define CX88_BOARD_WINFAST2000XP_EXPERT 5
164#define CX88_BOARD_AVERTV_STUDIO_303 6
165#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7
166#define CX88_BOARD_WINFAST_DV2000 8
167#define CX88_BOARD_LEADTEK_PVR2000 9
168#define CX88_BOARD_IODATA_GVVCP3PCI 10
169#define CX88_BOARD_PROLINK_PLAYTVPVR 11
170#define CX88_BOARD_ASUS_PVR_416 12
171#define CX88_BOARD_MSI_TVANYWHERE 13
172#define CX88_BOARD_KWORLD_DVB_T 14
173#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1 15
174#define CX88_BOARD_KWORLD_LTV883 16
175#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q 17
176#define CX88_BOARD_HAUPPAUGE_DVB_T1 18
177#define CX88_BOARD_CONEXANT_DVB_T1 19
178#define CX88_BOARD_PROVIDEO_PV259 20
179#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21
180#define CX88_BOARD_PCHDTV_HD3000 22
181#define CX88_BOARD_DNTV_LIVE_DVB_T 23
182#define CX88_BOARD_HAUPPAUGE_ROSLYN 24
183#define CX88_BOARD_DIGITALLOGIC_MEC 25
184#define CX88_BOARD_IODATA_GVBCTV7E 26
185#define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27
186#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28
187#define CX88_BOARD_ADSTECH_DVB_T_PCI 29
188#define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30
189#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31
190#define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32
191#define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33
192#define CX88_BOARD_ATI_HDTVWONDER 34
193#define CX88_BOARD_WINFAST_DTV1000 35
194#define CX88_BOARD_AVERTV_303 36
195#define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1 37
196#define CX88_BOARD_HAUPPAUGE_NOVASE2_S1 38
197#define CX88_BOARD_KWORLD_DVBS_100 39
198#define CX88_BOARD_HAUPPAUGE_HVR1100 40
199#define CX88_BOARD_HAUPPAUGE_HVR1100LP 41
200#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO 42
201#define CX88_BOARD_KWORLD_DVB_T_CX22702 43
202#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
203#define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45
204#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46
205#define CX88_BOARD_PCHDTV_HD5500 47
206#define CX88_BOARD_KWORLD_MCE200_DELUXE 48
207#define CX88_BOARD_PIXELVIEW_PLAYTV_P7000 49
208#define CX88_BOARD_NPGTECH_REALTV_TOP10FM 50
209#define CX88_BOARD_WINFAST_DTV2000H 51
210#define CX88_BOARD_GENIATECH_DVBS 52
211#define CX88_BOARD_HAUPPAUGE_HVR3000 53
212#define CX88_BOARD_NORWOOD_MICRO 54
213#define CX88_BOARD_TE_DTV_250_OEM_SWANN 55
214#define CX88_BOARD_HAUPPAUGE_HVR1300 56
215#define CX88_BOARD_ADSTECH_PTV_390 57
216#define CX88_BOARD_PINNACLE_PCTV_HD_800i 58
217#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59
218#define CX88_BOARD_PINNACLE_HYBRID_PCTV 60
219#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61
220#define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62
221#define CX88_BOARD_GENIATECH_X8000_MT 63
222#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64
223#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65
224#define CX88_BOARD_PROLINK_PV_8000GT 66
225#define CX88_BOARD_KWORLD_ATSC_120 67
226#define CX88_BOARD_HAUPPAUGE_HVR4000 68
227#define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69
228#define CX88_BOARD_TEVII_S460 70
229#define CX88_BOARD_OMICOM_SS4_PCI 71
230#define CX88_BOARD_TBS_8920 72
231#define CX88_BOARD_TEVII_S420 73
232#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74
233#define CX88_BOARD_PROF_7300 75
234#define CX88_BOARD_SATTRADE_ST4200 76
235#define CX88_BOARD_TBS_8910 77
236#define CX88_BOARD_PROF_6200 78
237#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79
238#define CX88_BOARD_HAUPPAUGE_IRONLY 80
239#define CX88_BOARD_WINFAST_DTV1800H 81
240#define CX88_BOARD_WINFAST_DTV2000H_J 82
241#define CX88_BOARD_PROF_7301 83
242#define CX88_BOARD_SAMSUNG_SMT_7020 84
243#define CX88_BOARD_TWINHAN_VP1027_DVBS 85
244#define CX88_BOARD_TEVII_S464 86
245#define CX88_BOARD_WINFAST_DTV2000H_PLUS 87
246#define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
247
248enum cx88_itype {
249 CX88_VMUX_COMPOSITE1 = 1,
250 CX88_VMUX_COMPOSITE2,
251 CX88_VMUX_COMPOSITE3,
252 CX88_VMUX_COMPOSITE4,
253 CX88_VMUX_SVIDEO,
254 CX88_VMUX_TELEVISION,
255 CX88_VMUX_CABLE,
256 CX88_VMUX_DVB,
257 CX88_VMUX_DEBUG,
258 CX88_RADIO,
259};
260
261struct cx88_input {
262 enum cx88_itype type;
263 u32 gpio0, gpio1, gpio2, gpio3;
264 unsigned int vmux:2;
265 unsigned int audioroute:4;
266};
267
268struct cx88_board {
269 const char *name;
270 unsigned int tuner_type;
271 unsigned int radio_type;
272 unsigned char tuner_addr;
273 unsigned char radio_addr;
274 int tda9887_conf;
275 struct cx88_input input[MAX_CX88_INPUT];
276 struct cx88_input radio;
277 enum cx88_board_type mpeg;
278 unsigned int audio_chip;
279 int num_frontends;
280
281 /* Used for I2S devices */
282 int i2sinputcntl;
283};
284
285struct cx88_subid {
286 u16 subvendor;
287 u16 subdevice;
288 u32 card;
289};
290
291enum cx88_tvaudio {
292 WW_NONE = 1,
293 WW_BTSC,
294 WW_BG,
295 WW_DK,
296 WW_I,
297 WW_L,
298 WW_EIAJ,
299 WW_I2SPT,
300 WW_FM,
301 WW_I2SADC,
302 WW_M
303};
304
305#define INPUT(nr) (core->board.input[nr])
306
307/* ----------------------------------------------------------- */
308/* device / file handle status */
309
310#define RESOURCE_OVERLAY 1
311#define RESOURCE_VIDEO 2
312#define RESOURCE_VBI 4
313
314#define BUFFER_TIMEOUT msecs_to_jiffies(2000)
315
316/* buffer for one video frame */
317struct cx88_buffer {
318 /* common v4l buffer stuff -- must be first */
319 struct videobuf_buffer vb;
320
321 /* cx88 specific */
322 unsigned int bpl;
323 struct btcx_riscmem risc;
324 const struct cx8800_fmt *fmt;
325 u32 count;
326};
327
328struct cx88_dmaqueue {
329 struct list_head active;
330 struct list_head queued;
331 struct timer_list timeout;
332 struct btcx_riscmem stopper;
333 u32 count;
334};
335
336struct cx88_core {
337 struct list_head devlist;
338 atomic_t refcount;
339
340 /* board name */
341 int nr;
342 char name[32];
343
344 /* pci stuff */
345 int pci_bus;
346 int pci_slot;
347 u32 __iomem *lmmio;
348 u8 __iomem *bmmio;
349 u32 shadow[SHADOW_MAX];
350 int pci_irqmask;
351
352 /* i2c i/o */
353 struct i2c_adapter i2c_adap;
354 struct i2c_algo_bit_data i2c_algo;
355 struct i2c_client i2c_client;
356 u32 i2c_state, i2c_rc;
357
358 /* config info -- analog */
359 struct v4l2_device v4l2_dev;
360 struct i2c_client *i2c_rtc;
361 unsigned int boardnr;
362 struct cx88_board board;
363
364 /* Supported V4L _STD_ tuner formats */
365 unsigned int tuner_formats;
366
367 /* config info -- dvb */
368#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
369 int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
370#endif
371 void (*gate_ctrl)(struct cx88_core *core, int open);
372
373 /* state info */
374 struct task_struct *kthread;
375 v4l2_std_id tvnorm;
376 enum cx88_tvaudio tvaudio;
377 u32 audiomode_manual;
378 u32 audiomode_current;
379 u32 input;
380 u32 last_analog_input;
381 u32 astat;
382 u32 use_nicam;
383 unsigned long last_change;
384
385 /* IR remote control state */
386 struct cx88_IR *ir;
387
388 /* I2C remote data */
389 struct IR_i2c_init_data init_data;
390 struct wm8775_platform_data wm8775_data;
391
392 struct mutex lock;
393 /* various v4l controls */
394 u32 freq;
395 int users;
396 int mpeg_users;
397
398 /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
399 struct cx8802_dev *dvbdev;
400 enum cx88_board_type active_type_id;
401 int active_ref;
402 int active_fe_id;
403};
404
405static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
406{
407 return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
408}
409
410#define WM8775_GID (1 << 0)
411
412#define call_hw(core, grpid, o, f, args...) \
413 do { \
414 if (!core->i2c_rc) { \
415 if (core->gate_ctrl) \
416 core->gate_ctrl(core, 1); \
417 v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
418 if (core->gate_ctrl) \
419 core->gate_ctrl(core, 0); \
420 } \
421 } while (0)
422
423#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
424
425struct cx8800_dev;
426struct cx8802_dev;
427
428/* ----------------------------------------------------------- */
429/* function 0: video stuff */
430
431struct cx8800_fh {
432 struct cx8800_dev *dev;
433 enum v4l2_buf_type type;
434 int radio;
435 unsigned int resources;
436
437 /* video overlay */
438 struct v4l2_window win;
439 struct v4l2_clip *clips;
440 unsigned int nclips;
441
442 /* video capture */
443 const struct cx8800_fmt *fmt;
444 unsigned int width,height;
445 struct videobuf_queue vidq;
446
447 /* vbi capture */
448 struct videobuf_queue vbiq;
449};
450
451struct cx8800_suspend_state {
452 int disabled;
453};
454
455struct cx8800_dev {
456 struct cx88_core *core;
457 spinlock_t slock;
458
459 /* various device info */
460 unsigned int resources;
461 struct video_device *video_dev;
462 struct video_device *vbi_dev;
463 struct video_device *radio_dev;
464
465 /* pci i/o */
466 struct pci_dev *pci;
467 unsigned char pci_rev,pci_lat;
468
469
470 /* capture queues */
471 struct cx88_dmaqueue vidq;
472 struct cx88_dmaqueue vbiq;
473
474 /* various v4l controls */
475
476 /* other global state info */
477 struct cx8800_suspend_state state;
478};
479
480/* ----------------------------------------------------------- */
481/* function 1: audio/alsa stuff */
482/* =============> moved to cx88-alsa.c <====================== */
483
484
485/* ----------------------------------------------------------- */
486/* function 2: mpeg stuff */
487
488struct cx8802_fh {
489 struct cx8802_dev *dev;
490 struct videobuf_queue mpegq;
491};
492
493struct cx8802_suspend_state {
494 int disabled;
495};
496
497struct cx8802_driver {
498 struct cx88_core *core;
499
500 /* List of drivers attached to device */
501 struct list_head drvlist;
502
503 /* Type of driver and access required */
504 enum cx88_board_type type_id;
505 enum cx8802_board_access hw_access;
506
507 /* MPEG 8802 internal only */
508 int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
509 int (*resume)(struct pci_dev *pci_dev);
510
511 /* Callers to the following functions must hold core->lock */
512
513 /* MPEG 8802 -> mini driver - Driver probe and configuration */
514 int (*probe)(struct cx8802_driver *drv);
515 int (*remove)(struct cx8802_driver *drv);
516
517 /* MPEG 8802 -> mini driver - Access for hardware control */
518 int (*advise_acquire)(struct cx8802_driver *drv);
519 int (*advise_release)(struct cx8802_driver *drv);
520
521 /* MPEG 8802 <- mini driver - Access for hardware control */
522 int (*request_acquire)(struct cx8802_driver *drv);
523 int (*request_release)(struct cx8802_driver *drv);
524};
525
526struct cx8802_dev {
527 struct cx88_core *core;
528 spinlock_t slock;
529
530 /* pci i/o */
531 struct pci_dev *pci;
532 unsigned char pci_rev,pci_lat;
533
534 /* dma queues */
535 struct cx88_dmaqueue mpegq;
536 u32 ts_packet_size;
537 u32 ts_packet_count;
538
539 /* other global state info */
540 struct cx8802_suspend_state state;
541
542 /* for blackbird only */
543 struct list_head devlist;
544#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
545 defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
546 struct video_device *mpeg_dev;
547 u32 mailbox;
548 int width;
549 int height;
550 unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
551
552 /* mpeg params */
553 struct cx2341x_mpeg_params params;
554#endif
555
556#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
557 /* for dvb only */
558 struct videobuf_dvb_frontends frontends;
559#endif
560
561#if defined(CONFIG_VIDEO_CX88_VP3054) || \
562 defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
563 /* For VP3045 secondary I2C bus support */
564 struct vp3054_i2c_state *vp3054;
565#endif
566 /* for switching modulation types */
567 unsigned char ts_gen_cntrl;
568
569 /* List of attached drivers; must hold core->lock to access */
570 struct list_head drvlist;
571
572 struct work_struct request_module_wk;
573};
574
575/* ----------------------------------------------------------- */
576
577#define cx_read(reg) readl(core->lmmio + ((reg)>>2))
578#define cx_write(reg,value) writel((value), core->lmmio + ((reg)>>2))
579#define cx_writeb(reg,value) writeb((value), core->bmmio + (reg))
580
581#define cx_andor(reg,mask,value) \
582 writel((readl(core->lmmio+((reg)>>2)) & ~(mask)) |\
583 ((value) & (mask)), core->lmmio+((reg)>>2))
584#define cx_set(reg,bit) cx_andor((reg),(bit),(bit))
585#define cx_clear(reg,bit) cx_andor((reg),(bit),0)
586
587#define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); }
588
589/* shadow registers */
590#define cx_sread(sreg) (core->shadow[sreg])
591#define cx_swrite(sreg,reg,value) \
592 (core->shadow[sreg] = value, \
593 writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
594#define cx_sandor(sreg,reg,mask,value) \
595 (core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | ((value) & (mask)), \
596 writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
597
598/* ----------------------------------------------------------- */
599/* cx88-core.c */
600
601extern void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
602 int len, u32 bits, u32 mask);
603
604extern int cx88_core_irq(struct cx88_core *core, u32 status);
605extern void cx88_wakeup(struct cx88_core *core,
606 struct cx88_dmaqueue *q, u32 count);
607extern void cx88_shutdown(struct cx88_core *core);
608extern int cx88_reset(struct cx88_core *core);
609
610extern int
611cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
612 struct scatterlist *sglist,
613 unsigned int top_offset, unsigned int bottom_offset,
614 unsigned int bpl, unsigned int padding, unsigned int lines);
615extern int
616cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
617 struct scatterlist *sglist, unsigned int bpl,
618 unsigned int lines, unsigned int lpi);
619extern int
620cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
621 u32 reg, u32 mask, u32 value);
622extern void
623cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
624
625extern void cx88_risc_disasm(struct cx88_core *core,
626 struct btcx_riscmem *risc);
627extern int cx88_sram_channel_setup(struct cx88_core *core,
628 const struct sram_channel *ch,
629 unsigned int bpl, u32 risc);
630extern void cx88_sram_channel_dump(struct cx88_core *core,
631 const struct sram_channel *ch);
632
633extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
634 unsigned int height, enum v4l2_field field);
635extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
636
637extern struct video_device *cx88_vdev_init(struct cx88_core *core,
638 struct pci_dev *pci,
639 const struct video_device *template_,
640 const char *type);
641extern struct cx88_core* cx88_core_get(struct pci_dev *pci);
642extern void cx88_core_put(struct cx88_core *core,
643 struct pci_dev *pci);
644
645extern int cx88_start_audio_dma(struct cx88_core *core);
646extern int cx88_stop_audio_dma(struct cx88_core *core);
647
648
649/* ----------------------------------------------------------- */
650/* cx88-vbi.c */
651
652/* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */
653int cx8800_vbi_fmt (struct file *file, void *priv,
654 struct v4l2_format *f);
655
656/*
657int cx8800_start_vbi_dma(struct cx8800_dev *dev,
658 struct cx88_dmaqueue *q,
659 struct cx88_buffer *buf);
660*/
661int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
662int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
663 struct cx88_dmaqueue *q);
664void cx8800_vbi_timeout(unsigned long data);
665
666extern const struct videobuf_queue_ops cx8800_vbi_qops;
667
668/* ----------------------------------------------------------- */
669/* cx88-i2c.c */
670
671extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
672
673
674/* ----------------------------------------------------------- */
675/* cx88-cards.c */
676
677extern int cx88_tuner_callback(void *dev, int component, int command, int arg);
678extern int cx88_get_resources(const struct cx88_core *core,
679 struct pci_dev *pci);
680extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
681extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
682
683/* ----------------------------------------------------------- */
684/* cx88-tvaudio.c */
685
686void cx88_set_tvaudio(struct cx88_core *core);
687void cx88_newstation(struct cx88_core *core);
688void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
689void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
690int cx88_audio_thread(void *data);
691
692int cx8802_register_driver(struct cx8802_driver *drv);
693int cx8802_unregister_driver(struct cx8802_driver *drv);
694
695/* Caller must hold core->lock */
696struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
697
698/* ----------------------------------------------------------- */
699/* cx88-dsp.c */
700
701s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core);
702
703/* ----------------------------------------------------------- */
704/* cx88-input.c */
705
706int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
707int cx88_ir_fini(struct cx88_core *core);
708void cx88_ir_irq(struct cx88_core *core);
709int cx88_ir_start(struct cx88_core *core);
710void cx88_ir_stop(struct cx88_core *core);
711extern void cx88_i2c_init_ir(struct cx88_core *core);
712
713/* ----------------------------------------------------------- */
714/* cx88-mpeg.c */
715
716int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
717 struct cx88_buffer *buf, enum v4l2_field field);
718void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
719void cx8802_cancel_buffers(struct cx8802_dev *dev);
720
721/* ----------------------------------------------------------- */
722/* cx88-video.c*/
723extern const u32 cx88_user_ctrls[];
724extern int cx8800_ctrl_query(struct cx88_core *core,
725 struct v4l2_queryctrl *qctrl);
726int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i);
727int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f);
728int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
729int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl);
730int cx88_video_mux(struct cx88_core *core, unsigned int input);