aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/pci/cx88
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 04:49:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 04:49:05 -0400
commit0b8e74c6f44094189dbe78baf4101acc7570c6af (patch)
tree6440561d09fb71ba5928664604ec92f29940be6b /drivers/media/pci/cx88
parent7f60ba388f5b9dd8b0da463b394412dace3ab814 (diff)
parentbd0d10498826ed150da5e4c45baf8b9c7088fb71 (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "The first part of the media updates for Kernel 3.7. This series contain: - A major tree renaming patch series: now, drivers are organized internally by their used bus, instead of by V4L2 and/or DVB API, providing a cleaner driver location for hybrid drivers that implement both APIs, and allowing to cleanup the Kconfig items and make them more intuitive for the end user; - Media Kernel developers are typically very lazy with their duties of keeping the MAINTAINERS entries for their drivers updated. As now the tree is more organized, we're doing an effort to add/update those entries for the drivers that aren't currently orphan; - Several DVB USB drivers got moved to a new DVB USB v2 core; the new core fixes several bugs (as the existing one that got bitroted). Now, suspend/resume finally started to work fine (at least with some devices - we should expect more work with regards to it); - added multistream support for DVB-T2, and unified the API for DVB-S2 and ISDB-S. Backward binary support is preserved; - as usual, a few new drivers, some V4L2 core improvements and lots of drivers improvements and fixes. There are some points to notice on this series: 1) you should expect a trivial merge conflict on your tree, with the removal of Documentation/feature-removal-schedule.txt: this series would be adding two additional entries there. I opted to not rebase it due to this recent change; 2) With regards to the PCTV 520e udev-related breakage, I opted to fix it in a way that the patches can be backported to 3.5 even without your firmware fix patch. This way, Greg doesn't need to rush backporting your patch (as there are still the firmware cache and firmware path customization issues to be addressed there). I'll send later a patch (likely after the end of the merge window) reverting the rest of the DRX-K async firmware request, fully restoring its original behaviour to allow media drivers to initialize everything serialized as before for 3.7 and upper. 3) I'm planning to work on this weekend to test the DMABUF patches for V4L2. The patches are on my queue for several Kernel cycles, but, up to now, there is/was no way to test the series locally. I have some concerns about this particular changeset with regards to security issues, and with regards to the replacement of the old VIDIOC_OVERLAY ioctl's that is broken on modern systems, due to GPU drivers change. The Overlay API allows direct PCI2PCI transfers from a media capture card into the GPU framebuffer, but its API is crappy. Also, the only existing X11 driver that implements it requires a XV extension that is not available anymore on modern drivers. The DMABUF can do the same thing, but with it is promising to be a properly-designed API. If I can successfully test this series and be happy with it, I should be asking you to pull them next week." * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (717 commits) em28xx: regression fix: use DRX-K sync firmware requests on em28xx drxk: allow loading firmware synchrousnously em28xx: Make all em28xx extensions to be initialized asynchronously [media] tda18271: properly report read errors in tda18271_get_id [media] tda18271: delay IR & RF calibration until init() if delay_cal is set [media] MAINTAINERS: add Michael Krufky as tda827x maintainer [media] MAINTAINERS: add Michael Krufky as tda8290 maintainer [media] MAINTAINERS: add Michael Krufky as cxusb maintainer [media] MAINTAINERS: add Michael Krufky as lg2160 maintainer [media] MAINTAINERS: add Michael Krufky as lgdt3305 maintainer [media] MAINTAINERS: add Michael Krufky as mxl111sf maintainer [media] MAINTAINERS: add Michael Krufky as mxl5007t maintainer [media] MAINTAINERS: add Michael Krufky as tda18271 maintainer [media] s5p-tv: Report only multi-plane capabilities in vidioc_querycap [media] s5p-mfc: Fix misplaced return statement in s5p_mfc_suspend() [media] exynos-gsc: Add missing static storage class specifiers [media] exynos-gsc: Remove <linux/version.h> header file inclusion [media] s5p-fimc: Fix incorrect condition in fimc_lite_reqbufs() [media] s5p-tv: Fix potential NULL pointer dereference error [media] s5k6aa: Fix possible NULL pointer dereference ...
Diffstat (limited to 'drivers/media/pci/cx88')
-rw-r--r--drivers/media/pci/cx88/Kconfig86
-rw-r--r--drivers/media/pci/cx88/Makefile16
-rw-r--r--drivers/media/pci/cx88/cx88-alsa.c975
-rw-r--r--drivers/media/pci/cx88/cx88-blackbird.c1299
-rw-r--r--drivers/media/pci/cx88/cx88-cards.c3811
-rw-r--r--drivers/media/pci/cx88/cx88-core.c1131
-rw-r--r--drivers/media/pci/cx88/cx88-dsp.c322
-rw-r--r--drivers/media/pci/cx88/cx88-dvb.c1778
-rw-r--r--drivers/media/pci/cx88/cx88-i2c.c184
-rw-r--r--drivers/media/pci/cx88/cx88-input.c635
-rw-r--r--drivers/media/pci/cx88/cx88-mpeg.c929
-rw-r--r--drivers/media/pci/cx88/cx88-reg.h836
-rw-r--r--drivers/media/pci/cx88/cx88-tvaudio.c1059
-rw-r--r--drivers/media/pci/cx88/cx88-vbi.c245
-rw-r--r--drivers/media/pci/cx88/cx88-video.c2075
-rw-r--r--drivers/media/pci/cx88/cx88-vp3054-i2c.c159
-rw-r--r--drivers/media/pci/cx88/cx88-vp3054-i2c.h41
-rw-r--r--drivers/media/pci/cx88/cx88.h748
18 files changed, 16329 insertions, 0 deletions
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig
new file mode 100644
index 000000000000..d27fccbf03c4
--- /dev/null
+++ b/drivers/media/pci/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 MEDIA_SUBDRV_AUTOSELECT
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 MEDIA_SUBDRV_AUTOSELECT
50 select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
51 select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
52 select DVB_OR51132 if MEDIA_SUBDRV_AUTOSELECT
53 select DVB_CX22702 if MEDIA_SUBDRV_AUTOSELECT
54 select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
55 select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT
56 select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT
57 select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT
58 select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
59 select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
60 select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
61 select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
62 select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT
63 select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
64 select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
65 select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
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_VP3054
74 tristate "VP-3054 Secondary I2C Bus Support"
75 default m
76 depends on VIDEO_CX88_DVB && DVB_MT352
77 ---help---
78 This adds DVB-T support for cards based on the
79 Conexant 2388x chip and the MT352 demodulator,
80 which also require support for the VP-3054
81 Secondary I2C bus, such at DNTV Live! DVB-T Pro.
82
83config VIDEO_CX88_MPEG
84 tristate
85 depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
86 default y
diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile
new file mode 100644
index 000000000000..d3679c3ee248
--- /dev/null
+++ b/drivers/media/pci/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
13ccflags-y += -Idrivers/media/i2c
14ccflags-y += -Idrivers/media/tuners
15ccflags-y += -Idrivers/media/dvb-core
16ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
new file mode 100644
index 000000000000..3aa6856ead3b
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -0,0 +1,975 @@
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 bool 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 int left = value->value.integer.value[0];
589 int right = value->value.integer.value[1];
590 int v, b;
591
592 /* Pass volume & balance onto any WM8775 */
593 if (left >= right) {
594 v = left << 10;
595 b = left ? (0x8000 * right) / left : 0x8000;
596 } else {
597 v = right << 10;
598 b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
599 }
600 wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v);
601 wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b);
602}
603
604/* OK - TODO: test it */
605static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
606 struct snd_ctl_elem_value *value)
607{
608 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
609 struct cx88_core *core=chip->core;
610 int left, right, v, b;
611 int changed = 0;
612 u32 old;
613
614 if (core->board.audio_chip == V4L2_IDENT_WM8775)
615 snd_cx88_wm8775_volume_put(kcontrol, value);
616
617 left = value->value.integer.value[0] & 0x3f;
618 right = value->value.integer.value[1] & 0x3f;
619 b = right - left;
620 if (b < 0) {
621 v = 0x3f - left;
622 b = (-b) | 0x40;
623 } else {
624 v = 0x3f - right;
625 }
626 /* Do we really know this will always be called with IRQs on? */
627 spin_lock_irq(&chip->reg_lock);
628 old = cx_read(AUD_VOL_CTL);
629 if (v != (old & 0x3f)) {
630 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
631 changed = 1;
632 }
633 if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
634 cx_write(AUD_BAL_CTL, b);
635 changed = 1;
636 }
637 spin_unlock_irq(&chip->reg_lock);
638
639 return changed;
640}
641
642static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0);
643
644static const struct snd_kcontrol_new snd_cx88_volume = {
645 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
646 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
647 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
648 .name = "Analog-TV Volume",
649 .info = snd_cx88_volume_info,
650 .get = snd_cx88_volume_get,
651 .put = snd_cx88_volume_put,
652 .tlv.p = snd_cx88_db_scale,
653};
654
655static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol,
656 struct snd_ctl_elem_value *value)
657{
658 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
659 struct cx88_core *core = chip->core;
660 u32 bit = kcontrol->private_value;
661
662 value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit);
663 return 0;
664}
665
666static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
667 struct snd_ctl_elem_value *value)
668{
669 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
670 struct cx88_core *core = chip->core;
671 u32 bit = kcontrol->private_value;
672 int ret = 0;
673 u32 vol;
674
675 spin_lock_irq(&chip->reg_lock);
676 vol = cx_read(AUD_VOL_CTL);
677 if (value->value.integer.value[0] != !(vol & bit)) {
678 vol ^= bit;
679 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
680 /* Pass mute onto any WM8775 */
681 if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
682 ((1<<6) == bit))
683 wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
684 ret = 1;
685 }
686 spin_unlock_irq(&chip->reg_lock);
687 return ret;
688}
689
690static const struct snd_kcontrol_new snd_cx88_dac_switch = {
691 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
692 .name = "Audio-Out Switch",
693 .info = snd_ctl_boolean_mono_info,
694 .get = snd_cx88_switch_get,
695 .put = snd_cx88_switch_put,
696 .private_value = (1<<8),
697};
698
699static const struct snd_kcontrol_new snd_cx88_source_switch = {
700 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
701 .name = "Analog-TV Switch",
702 .info = snd_ctl_boolean_mono_info,
703 .get = snd_cx88_switch_get,
704 .put = snd_cx88_switch_put,
705 .private_value = (1<<6),
706};
707
708static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
709 struct snd_ctl_elem_value *value)
710{
711 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
712 struct cx88_core *core = chip->core;
713 s32 val;
714
715 val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS);
716 value->value.integer.value[0] = val ? 1 : 0;
717 return 0;
718}
719
720static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
721 struct snd_ctl_elem_value *value)
722{
723 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
724 struct cx88_core *core = chip->core;
725 struct v4l2_control client_ctl;
726
727 memset(&client_ctl, 0, sizeof(client_ctl));
728 client_ctl.value = 0 != value->value.integer.value[0];
729 client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
730 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
731
732 return 0;
733}
734
735static struct snd_kcontrol_new snd_cx88_alc_switch = {
736 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
737 .name = "Line-In ALC Switch",
738 .info = snd_ctl_boolean_mono_info,
739 .get = snd_cx88_alc_get,
740 .put = snd_cx88_alc_put,
741};
742
743/****************************************************************************
744 Basic Flow for Sound Devices
745 ****************************************************************************/
746
747/*
748 * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
749 * Only boards with eeprom and byte 1 at eeprom=1 have it
750 */
751
752static const struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = {
753 {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
754 {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
755 {0, }
756};
757MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
758
759/*
760 * Chip-specific destructor
761 */
762
763static int snd_cx88_free(snd_cx88_card_t *chip)
764{
765
766 if (chip->irq >= 0)
767 free_irq(chip->irq, chip);
768
769 cx88_core_put(chip->core,chip->pci);
770
771 pci_disable_device(chip->pci);
772 return 0;
773}
774
775/*
776 * Component Destructor
777 */
778static void snd_cx88_dev_free(struct snd_card * card)
779{
780 snd_cx88_card_t *chip = card->private_data;
781
782 snd_cx88_free(chip);
783}
784
785
786/*
787 * Alsa Constructor - Component probe
788 */
789
790static int devno;
791static int __devinit snd_cx88_create(struct snd_card *card,
792 struct pci_dev *pci,
793 snd_cx88_card_t **rchip,
794 struct cx88_core **core_ptr)
795{
796 snd_cx88_card_t *chip;
797 struct cx88_core *core;
798 int err;
799 unsigned char pci_lat;
800
801 *rchip = NULL;
802
803 err = pci_enable_device(pci);
804 if (err < 0)
805 return err;
806
807 pci_set_master(pci);
808
809 chip = card->private_data;
810
811 core = cx88_core_get(pci);
812 if (NULL == core) {
813 err = -EINVAL;
814 return err;
815 }
816
817 if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) {
818 dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
819 err = -EIO;
820 cx88_core_put(core, pci);
821 return err;
822 }
823
824
825 /* pci init */
826 chip->card = card;
827 chip->pci = pci;
828 chip->irq = -1;
829 spin_lock_init(&chip->reg_lock);
830
831 chip->core = core;
832
833 /* get irq */
834 err = request_irq(chip->pci->irq, cx8801_irq,
835 IRQF_SHARED | IRQF_DISABLED, chip->core->name, chip);
836 if (err < 0) {
837 dprintk(0, "%s: can't get IRQ %d\n",
838 chip->core->name, chip->pci->irq);
839 return err;
840 }
841
842 /* print pci info */
843 pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat);
844
845 dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, "
846 "latency: %d, mmio: 0x%llx\n", core->name, devno,
847 pci_name(pci), pci->revision, pci->irq,
848 pci_lat, (unsigned long long)pci_resource_start(pci,0));
849
850 chip->irq = pci->irq;
851 synchronize_irq(chip->irq);
852
853 snd_card_set_dev(card, &pci->dev);
854
855 *rchip = chip;
856 *core_ptr = core;
857
858 return 0;
859}
860
861static int __devinit cx88_audio_initdev(struct pci_dev *pci,
862 const struct pci_device_id *pci_id)
863{
864 struct snd_card *card;
865 snd_cx88_card_t *chip;
866 struct cx88_core *core = NULL;
867 int err;
868
869 if (devno >= SNDRV_CARDS)
870 return (-ENODEV);
871
872 if (!enable[devno]) {
873 ++devno;
874 return (-ENOENT);
875 }
876
877 err = snd_card_create(index[devno], id[devno], THIS_MODULE,
878 sizeof(snd_cx88_card_t), &card);
879 if (err < 0)
880 return err;
881
882 card->private_free = snd_cx88_dev_free;
883
884 err = snd_cx88_create(card, pci, &chip, &core);
885 if (err < 0)
886 goto error;
887
888 err = snd_cx88_pcm(chip, 0, "CX88 Digital");
889 if (err < 0)
890 goto error;
891
892 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_volume, chip));
893 if (err < 0)
894 goto error;
895 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_dac_switch, chip));
896 if (err < 0)
897 goto error;
898 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_source_switch, chip));
899 if (err < 0)
900 goto error;
901
902 /* If there's a wm8775 then add a Line-In ALC switch */
903 if (core->board.audio_chip == V4L2_IDENT_WM8775)
904 snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip));
905
906 strcpy (card->driver, "CX88x");
907 sprintf(card->shortname, "Conexant CX%x", pci->device);
908 sprintf(card->longname, "%s at %#llx",
909 card->shortname,(unsigned long long)pci_resource_start(pci, 0));
910 strcpy (card->mixername, "CX88");
911
912 dprintk (0, "%s/%i: ALSA support for cx2388x boards\n",
913 card->driver,devno);
914
915 err = snd_card_register(card);
916 if (err < 0)
917 goto error;
918 pci_set_drvdata(pci,card);
919
920 devno++;
921 return 0;
922
923error:
924 snd_card_free(card);
925 return err;
926}
927/*
928 * ALSA destructor
929 */
930static void __devexit cx88_audio_finidev(struct pci_dev *pci)
931{
932 struct cx88_audio_dev *card = pci_get_drvdata(pci);
933
934 snd_card_free((void *)card);
935
936 pci_set_drvdata(pci, NULL);
937
938 devno--;
939}
940
941/*
942 * PCI driver definition
943 */
944
945static struct pci_driver cx88_audio_pci_driver = {
946 .name = "cx88_audio",
947 .id_table = cx88_audio_pci_tbl,
948 .probe = cx88_audio_initdev,
949 .remove = __devexit_p(cx88_audio_finidev),
950};
951
952/****************************************************************************
953 LINUX MODULE INIT
954 ****************************************************************************/
955
956/*
957 * module init
958 */
959static int __init cx88_audio_init(void)
960{
961 printk(KERN_INFO "cx2388x alsa driver version %s loaded\n",
962 CX88_VERSION);
963 return pci_register_driver(&cx88_audio_pci_driver);
964}
965
966/*
967 * module remove
968 */
969static void __exit cx88_audio_fini(void)
970{
971 pci_unregister_driver(&cx88_audio_pci_driver);
972}
973
974module_init(cx88_audio_init);
975module_exit(cx88_audio_fini);
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
new file mode 100644
index 000000000000..def363fb71c0
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -0,0 +1,1299 @@
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/v4l2-event.h>
39#include <media/cx2341x.h>
40
41#include "cx88.h"
42
43MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
44MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
45MODULE_LICENSE("GPL");
46MODULE_VERSION(CX88_VERSION);
47
48static unsigned int mpegbufs = 32;
49module_param(mpegbufs,int,0644);
50MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
51
52static unsigned int debug;
53module_param(debug,int,0644);
54MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
55
56#define dprintk(level,fmt, arg...) if (debug >= level) \
57 printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
58
59
60/* ------------------------------------------------------------------ */
61
62#define BLACKBIRD_FIRM_IMAGE_SIZE 376836
63
64/* defines below are from ivtv-driver.h */
65
66#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
67
68/* Firmware API commands */
69#define IVTV_API_STD_TIMEOUT 500
70
71enum blackbird_capture_type {
72 BLACKBIRD_MPEG_CAPTURE,
73 BLACKBIRD_RAW_CAPTURE,
74 BLACKBIRD_RAW_PASSTHRU_CAPTURE
75};
76enum blackbird_capture_bits {
77 BLACKBIRD_RAW_BITS_NONE = 0x00,
78 BLACKBIRD_RAW_BITS_YUV_CAPTURE = 0x01,
79 BLACKBIRD_RAW_BITS_PCM_CAPTURE = 0x02,
80 BLACKBIRD_RAW_BITS_VBI_CAPTURE = 0x04,
81 BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
82 BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE = 0x10
83};
84enum blackbird_capture_end {
85 BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
86 BLACKBIRD_END_NOW, /* stop immediately, no irq */
87};
88enum blackbird_framerate {
89 BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
90 BLACKBIRD_FRAMERATE_PAL_25 /* PAL: 25fps */
91};
92enum blackbird_stream_port {
93 BLACKBIRD_OUTPUT_PORT_MEMORY,
94 BLACKBIRD_OUTPUT_PORT_STREAMING,
95 BLACKBIRD_OUTPUT_PORT_SERIAL
96};
97enum blackbird_data_xfer_status {
98 BLACKBIRD_MORE_BUFFERS_FOLLOW,
99 BLACKBIRD_LAST_BUFFER,
100};
101enum blackbird_picture_mask {
102 BLACKBIRD_PICTURE_MASK_NONE,
103 BLACKBIRD_PICTURE_MASK_I_FRAMES,
104 BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
105 BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
106};
107enum blackbird_vbi_mode_bits {
108 BLACKBIRD_VBI_BITS_SLICED,
109 BLACKBIRD_VBI_BITS_RAW,
110};
111enum blackbird_vbi_insertion_bits {
112 BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
113 BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
114 BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
115 BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
116 BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
117};
118enum blackbird_dma_unit {
119 BLACKBIRD_DMA_BYTES,
120 BLACKBIRD_DMA_FRAMES,
121};
122enum blackbird_dma_transfer_status_bits {
123 BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
124 BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
125 BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
126};
127enum blackbird_pause {
128 BLACKBIRD_PAUSE_ENCODING,
129 BLACKBIRD_RESUME_ENCODING,
130};
131enum blackbird_copyright {
132 BLACKBIRD_COPYRIGHT_OFF,
133 BLACKBIRD_COPYRIGHT_ON,
134};
135enum blackbird_notification_type {
136 BLACKBIRD_NOTIFICATION_REFRESH,
137};
138enum blackbird_notification_status {
139 BLACKBIRD_NOTIFICATION_OFF,
140 BLACKBIRD_NOTIFICATION_ON,
141};
142enum blackbird_notification_mailbox {
143 BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
144};
145enum blackbird_field1_lines {
146 BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
147 BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
148 BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
149};
150enum blackbird_field2_lines {
151 BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
152 BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
153 BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
154};
155enum blackbird_custom_data_type {
156 BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
157 BLACKBIRD_CUSTOM_PRIVATE_PACKET,
158};
159enum blackbird_mute {
160 BLACKBIRD_UNMUTE,
161 BLACKBIRD_MUTE,
162};
163enum blackbird_mute_video_mask {
164 BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
165 BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
166 BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
167};
168enum blackbird_mute_video_shift {
169 BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
170 BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
171 BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
172};
173
174/* Registers */
175#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
176#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC /*| IVTV_REG_OFFSET*/)
177#define IVTV_REG_SPU (0x9050 /*| IVTV_REG_OFFSET*/)
178#define IVTV_REG_HW_BLOCKS (0x9054 /*| IVTV_REG_OFFSET*/)
179#define IVTV_REG_VPU (0x9058 /*| IVTV_REG_OFFSET*/)
180#define IVTV_REG_APU (0xA064 /*| IVTV_REG_OFFSET*/)
181
182/* ------------------------------------------------------------------ */
183
184static void host_setup(struct cx88_core *core)
185{
186 /* toggle reset of the host */
187 cx_write(MO_GPHST_SOFT_RST, 1);
188 udelay(100);
189 cx_write(MO_GPHST_SOFT_RST, 0);
190 udelay(100);
191
192 /* host port setup */
193 cx_write(MO_GPHST_WSC, 0x44444444U);
194 cx_write(MO_GPHST_XFR, 0);
195 cx_write(MO_GPHST_WDTH, 15);
196 cx_write(MO_GPHST_HDSHK, 0);
197 cx_write(MO_GPHST_MUX16, 0x44448888U);
198 cx_write(MO_GPHST_MODE, 0);
199}
200
201/* ------------------------------------------------------------------ */
202
203#define P1_MDATA0 0x390000
204#define P1_MDATA1 0x390001
205#define P1_MDATA2 0x390002
206#define P1_MDATA3 0x390003
207#define P1_MADDR2 0x390004
208#define P1_MADDR1 0x390005
209#define P1_MADDR0 0x390006
210#define P1_RDATA0 0x390008
211#define P1_RDATA1 0x390009
212#define P1_RDATA2 0x39000A
213#define P1_RDATA3 0x39000B
214#define P1_RADDR0 0x39000C
215#define P1_RADDR1 0x39000D
216#define P1_RRDWR 0x39000E
217
218static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state)
219{
220 unsigned long timeout = jiffies + msecs_to_jiffies(1);
221 u32 gpio0,need;
222
223 need = state ? 2 : 0;
224 for (;;) {
225 gpio0 = cx_read(MO_GP0_IO) & 2;
226 if (need == gpio0)
227 return 0;
228 if (time_after(jiffies,timeout))
229 return -1;
230 udelay(1);
231 }
232}
233
234static int memory_write(struct cx88_core *core, u32 address, u32 value)
235{
236 /* Warning: address is dword address (4 bytes) */
237 cx_writeb(P1_MDATA0, (unsigned int)value);
238 cx_writeb(P1_MDATA1, (unsigned int)(value >> 8));
239 cx_writeb(P1_MDATA2, (unsigned int)(value >> 16));
240 cx_writeb(P1_MDATA3, (unsigned int)(value >> 24));
241 cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) | 0x40);
242 cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
243 cx_writeb(P1_MADDR0, (unsigned int)address);
244 cx_read(P1_MDATA0);
245 cx_read(P1_MADDR0);
246
247 return wait_ready_gpio0_bit1(core,1);
248}
249
250static int memory_read(struct cx88_core *core, u32 address, u32 *value)
251{
252 int retval;
253 u32 val;
254
255 /* Warning: address is dword address (4 bytes) */
256 cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) & ~0xC0);
257 cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
258 cx_writeb(P1_MADDR0, (unsigned int)address);
259 cx_read(P1_MADDR0);
260
261 retval = wait_ready_gpio0_bit1(core,1);
262
263 cx_writeb(P1_MDATA3, 0);
264 val = (unsigned char)cx_read(P1_MDATA3) << 24;
265 cx_writeb(P1_MDATA2, 0);
266 val |= (unsigned char)cx_read(P1_MDATA2) << 16;
267 cx_writeb(P1_MDATA1, 0);
268 val |= (unsigned char)cx_read(P1_MDATA1) << 8;
269 cx_writeb(P1_MDATA0, 0);
270 val |= (unsigned char)cx_read(P1_MDATA0);
271
272 *value = val;
273 return retval;
274}
275
276static int register_write(struct cx88_core *core, u32 address, u32 value)
277{
278 cx_writeb(P1_RDATA0, (unsigned int)value);
279 cx_writeb(P1_RDATA1, (unsigned int)(value >> 8));
280 cx_writeb(P1_RDATA2, (unsigned int)(value >> 16));
281 cx_writeb(P1_RDATA3, (unsigned int)(value >> 24));
282 cx_writeb(P1_RADDR0, (unsigned int)address);
283 cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
284 cx_writeb(P1_RRDWR, 1);
285 cx_read(P1_RDATA0);
286 cx_read(P1_RADDR0);
287
288 return wait_ready_gpio0_bit1(core,1);
289}
290
291
292static int register_read(struct cx88_core *core, u32 address, u32 *value)
293{
294 int retval;
295 u32 val;
296
297 cx_writeb(P1_RADDR0, (unsigned int)address);
298 cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
299 cx_writeb(P1_RRDWR, 0);
300 cx_read(P1_RADDR0);
301
302 retval = wait_ready_gpio0_bit1(core,1);
303 val = (unsigned char)cx_read(P1_RDATA0);
304 val |= (unsigned char)cx_read(P1_RDATA1) << 8;
305 val |= (unsigned char)cx_read(P1_RDATA2) << 16;
306 val |= (unsigned char)cx_read(P1_RDATA3) << 24;
307
308 *value = val;
309 return retval;
310}
311
312/* ------------------------------------------------------------------ */
313
314static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
315{
316 struct cx8802_dev *dev = priv;
317 unsigned long timeout;
318 u32 value, flag, retval;
319 int i;
320
321 dprintk(1,"%s: 0x%X\n", __func__, command);
322
323 /* this may not be 100% safe if we can't read any memory location
324 without side effects */
325 memory_read(dev->core, dev->mailbox - 4, &value);
326 if (value != 0x12345678) {
327 dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
328 return -1;
329 }
330
331 memory_read(dev->core, dev->mailbox, &flag);
332 if (flag) {
333 dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
334 return -1;
335 }
336
337 flag |= 1; /* tell 'em we're working on it */
338 memory_write(dev->core, dev->mailbox, flag);
339
340 /* write command + args + fill remaining with zeros */
341 memory_write(dev->core, dev->mailbox + 1, command); /* command code */
342 memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
343 for (i = 0; i < in; i++) {
344 memory_write(dev->core, dev->mailbox + 4 + i, data[i]);
345 dprintk(1, "API Input %d = %d\n", i, data[i]);
346 }
347 for (; i < CX2341X_MBOX_MAX_DATA; i++)
348 memory_write(dev->core, dev->mailbox + 4 + i, 0);
349
350 flag |= 3; /* tell 'em we're done writing */
351 memory_write(dev->core, dev->mailbox, flag);
352
353 /* wait for firmware to handle the API command */
354 timeout = jiffies + msecs_to_jiffies(10);
355 for (;;) {
356 memory_read(dev->core, dev->mailbox, &flag);
357 if (0 != (flag & 4))
358 break;
359 if (time_after(jiffies,timeout)) {
360 dprintk(0, "ERROR: API Mailbox timeout\n");
361 return -1;
362 }
363 udelay(10);
364 }
365
366 /* read output values */
367 for (i = 0; i < out; i++) {
368 memory_read(dev->core, dev->mailbox + 4 + i, data + i);
369 dprintk(1, "API Output %d = %d\n", i, data[i]);
370 }
371
372 memory_read(dev->core, dev->mailbox + 2, &retval);
373 dprintk(1, "API result = %d\n",retval);
374
375 flag = 0;
376 memory_write(dev->core, dev->mailbox, flag);
377 return retval;
378}
379/* ------------------------------------------------------------------ */
380
381/* We don't need to call the API often, so using just one mailbox will probably suffice */
382static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
383 u32 inputcnt, u32 outputcnt, ...)
384{
385 u32 data[CX2341X_MBOX_MAX_DATA];
386 va_list vargs;
387 int i, err;
388
389 va_start(vargs, outputcnt);
390
391 for (i = 0; i < inputcnt; i++) {
392 data[i] = va_arg(vargs, int);
393 }
394 err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data);
395 for (i = 0; i < outputcnt; i++) {
396 int *vptr = va_arg(vargs, int *);
397 *vptr = data[i];
398 }
399 va_end(vargs);
400 return err;
401}
402
403static int blackbird_find_mailbox(struct cx8802_dev *dev)
404{
405 u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456};
406 int signaturecnt=0;
407 u32 value;
408 int i;
409
410 for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
411 memory_read(dev->core, i, &value);
412 if (value == signature[signaturecnt])
413 signaturecnt++;
414 else
415 signaturecnt = 0;
416 if (4 == signaturecnt) {
417 dprintk(1, "Mailbox signature found\n");
418 return i+1;
419 }
420 }
421 dprintk(0, "Mailbox signature values not found!\n");
422 return -1;
423}
424
425static int blackbird_load_firmware(struct cx8802_dev *dev)
426{
427 static const unsigned char magic[8] = {
428 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
429 };
430 const struct firmware *firmware;
431 int i, retval = 0;
432 u32 value = 0;
433 u32 checksum = 0;
434 u32 *dataptr;
435
436 retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
437 retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
438 retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640);
439 retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
440 msleep(1);
441 retval |= register_write(dev->core, IVTV_REG_APU, 0);
442
443 if (retval < 0)
444 dprintk(0, "Error with register_write\n");
445
446 retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
447 &dev->pci->dev);
448
449
450 if (retval != 0) {
451 dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
452 CX2341X_FIRM_ENC_FILENAME);
453 dprintk(0, "Please fix your hotplug setup, the board will "
454 "not work without firmware loaded!\n");
455 return -1;
456 }
457
458 if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
459 dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
460 firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
461 release_firmware(firmware);
462 return -1;
463 }
464
465 if (0 != memcmp(firmware->data, magic, 8)) {
466 dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
467 release_firmware(firmware);
468 return -1;
469 }
470
471 /* transfer to the chip */
472 dprintk(1,"Loading firmware ...\n");
473 dataptr = (u32*)firmware->data;
474 for (i = 0; i < (firmware->size >> 2); i++) {
475 value = le32_to_cpu(*dataptr);
476 checksum += ~value;
477 memory_write(dev->core, i, value);
478 dataptr++;
479 }
480
481 /* read back to verify with the checksum */
482 for (i--; i >= 0; i--) {
483 memory_read(dev->core, i, &value);
484 checksum -= ~value;
485 }
486 if (checksum) {
487 dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
488 release_firmware(firmware);
489 return -1;
490 }
491 release_firmware(firmware);
492 dprintk(0, "Firmware upload successful.\n");
493
494 retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
495 retval |= register_read(dev->core, IVTV_REG_SPU, &value);
496 retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE);
497 msleep(1);
498
499 retval |= register_read(dev->core, IVTV_REG_VPU, &value);
500 retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8);
501
502 if (retval < 0)
503 dprintk(0, "Error with register_write\n");
504 return 0;
505}
506
507/**
508 Settings used by the windows tv app for PVR2000:
509=================================================================================================================
510Profile | Codec | Resolution | CBR/VBR | Video Qlty | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
511-----------------------------------------------------------------------------------------------------------------
512MPEG-1 | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 2000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
513MPEG-2 | MPEG2 | 720x576PAL | VBR | 600 :Good | 4000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
514VCD | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 1150 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
515DVD | MPEG2 | 720x576PAL | VBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
516DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
517=================================================================================================================
518*DB: "DirectBurn"
519*/
520
521static void blackbird_codec_settings(struct cx8802_dev *dev)
522{
523 /* assign frame size */
524 blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
525 dev->height, dev->width);
526
527 dev->cxhdl.width = dev->width;
528 dev->cxhdl.height = dev->height;
529 cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
530 cx2341x_handler_setup(&dev->cxhdl);
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 cx2341x_handler_set_busy(&dev->cxhdl, 1);
622
623 /* start capturing to the host interface */
624 blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
625 BLACKBIRD_MPEG_CAPTURE,
626 BLACKBIRD_RAW_BITS_NONE
627 );
628
629 dev->mpeg_active = 1;
630 return 0;
631}
632
633static int blackbird_stop_codec(struct cx8802_dev *dev)
634{
635 blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
636 BLACKBIRD_END_NOW,
637 BLACKBIRD_MPEG_CAPTURE,
638 BLACKBIRD_RAW_BITS_NONE
639 );
640
641 cx2341x_handler_set_busy(&dev->cxhdl, 0);
642
643 dev->mpeg_active = 0;
644 return 0;
645}
646
647/* ------------------------------------------------------------------ */
648
649static int bb_buf_setup(struct videobuf_queue *q,
650 unsigned int *count, unsigned int *size)
651{
652 struct cx8802_fh *fh = q->priv_data;
653
654 fh->dev->ts_packet_size = 188 * 4; /* was: 512 */
655 fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
656
657 *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
658 *count = fh->dev->ts_packet_count;
659 return 0;
660}
661
662static int
663bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
664 enum v4l2_field field)
665{
666 struct cx8802_fh *fh = q->priv_data;
667 return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
668}
669
670static void
671bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
672{
673 struct cx8802_fh *fh = q->priv_data;
674 cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
675}
676
677static void
678bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
679{
680 cx88_free_buffer(q, (struct cx88_buffer*)vb);
681}
682
683static struct videobuf_queue_ops blackbird_qops = {
684 .buf_setup = bb_buf_setup,
685 .buf_prepare = bb_buf_prepare,
686 .buf_queue = bb_buf_queue,
687 .buf_release = bb_buf_release,
688};
689
690/* ------------------------------------------------------------------ */
691
692static int vidioc_querycap(struct file *file, void *priv,
693 struct v4l2_capability *cap)
694{
695 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
696 struct cx88_core *core = dev->core;
697
698 strcpy(cap->driver, "cx88_blackbird");
699 sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
700 cx88_querycap(file, core, cap);
701 return 0;
702}
703
704static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
705 struct v4l2_fmtdesc *f)
706{
707 if (f->index != 0)
708 return -EINVAL;
709
710 strlcpy(f->description, "MPEG", sizeof(f->description));
711 f->pixelformat = V4L2_PIX_FMT_MPEG;
712 f->flags = V4L2_FMT_FLAG_COMPRESSED;
713 return 0;
714}
715
716static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
717 struct v4l2_format *f)
718{
719 struct cx8802_fh *fh = priv;
720 struct cx8802_dev *dev = fh->dev;
721
722 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
723 f->fmt.pix.bytesperline = 0;
724 f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
725 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
726 f->fmt.pix.width = dev->width;
727 f->fmt.pix.height = dev->height;
728 f->fmt.pix.field = fh->mpegq.field;
729 dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
730 dev->width, dev->height, fh->mpegq.field );
731 return 0;
732}
733
734static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
735 struct v4l2_format *f)
736{
737 struct cx8802_fh *fh = priv;
738 struct cx8802_dev *dev = fh->dev;
739
740 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
741 f->fmt.pix.bytesperline = 0;
742 f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
743 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
744 dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
745 dev->width, dev->height, fh->mpegq.field );
746 return 0;
747}
748
749static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
750 struct v4l2_format *f)
751{
752 struct cx8802_fh *fh = priv;
753 struct cx8802_dev *dev = fh->dev;
754 struct cx88_core *core = dev->core;
755
756 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
757 f->fmt.pix.bytesperline = 0;
758 f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
759 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
760 dev->width = f->fmt.pix.width;
761 dev->height = f->fmt.pix.height;
762 fh->mpegq.field = f->fmt.pix.field;
763 cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
764 blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
765 f->fmt.pix.height, f->fmt.pix.width);
766 dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
767 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
768 return 0;
769}
770
771static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
772{
773 struct cx8802_fh *fh = priv;
774 return (videobuf_reqbufs(&fh->mpegq, p));
775}
776
777static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
778{
779 struct cx8802_fh *fh = priv;
780 return (videobuf_querybuf(&fh->mpegq, p));
781}
782
783static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
784{
785 struct cx8802_fh *fh = priv;
786 return (videobuf_qbuf(&fh->mpegq, p));
787}
788
789static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
790{
791 struct cx8802_fh *fh = priv;
792 return (videobuf_dqbuf(&fh->mpegq, p,
793 file->f_flags & O_NONBLOCK));
794}
795
796static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
797{
798 struct cx8802_fh *fh = priv;
799 struct cx8802_dev *dev = fh->dev;
800
801 if (!dev->mpeg_active)
802 blackbird_start_codec(file, fh);
803 return videobuf_streamon(&fh->mpegq);
804}
805
806static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
807{
808 struct cx8802_fh *fh = priv;
809 struct cx8802_dev *dev = fh->dev;
810
811 if (dev->mpeg_active)
812 blackbird_stop_codec(dev);
813 return videobuf_streamoff(&fh->mpegq);
814}
815
816static int vidioc_s_frequency (struct file *file, void *priv,
817 struct v4l2_frequency *f)
818{
819 struct cx8802_fh *fh = priv;
820 struct cx8802_dev *dev = fh->dev;
821 struct cx88_core *core = dev->core;
822
823 if (unlikely(UNSET == core->board.tuner_type))
824 return -EINVAL;
825 if (unlikely(f->tuner != 0))
826 return -EINVAL;
827 if (dev->mpeg_active)
828 blackbird_stop_codec(dev);
829
830 cx88_set_freq (core,f);
831 blackbird_initialize_codec(dev);
832 cx88_set_scale(dev->core, dev->width, dev->height,
833 fh->mpegq.field);
834 return 0;
835}
836
837static int vidioc_log_status (struct file *file, void *priv)
838{
839 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
840 struct cx88_core *core = dev->core;
841 char name[32 + 2];
842
843 snprintf(name, sizeof(name), "%s/2", core->name);
844 call_all(core, core, log_status);
845 v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
846 return 0;
847}
848
849static int vidioc_enum_input (struct file *file, void *priv,
850 struct v4l2_input *i)
851{
852 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
853 return cx88_enum_input (core,i);
854}
855
856static int vidioc_g_frequency (struct file *file, void *priv,
857 struct v4l2_frequency *f)
858{
859 struct cx8802_fh *fh = priv;
860 struct cx88_core *core = fh->dev->core;
861
862 if (unlikely(UNSET == core->board.tuner_type))
863 return -EINVAL;
864 if (unlikely(f->tuner != 0))
865 return -EINVAL;
866
867 f->frequency = core->freq;
868 call_all(core, tuner, g_frequency, f);
869
870 return 0;
871}
872
873static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
874{
875 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
876
877 *i = core->input;
878 return 0;
879}
880
881static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
882{
883 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
884
885 if (i >= 4)
886 return -EINVAL;
887 if (0 == INPUT(i).type)
888 return -EINVAL;
889
890 mutex_lock(&core->lock);
891 cx88_newstation(core);
892 cx88_video_mux(core,i);
893 mutex_unlock(&core->lock);
894 return 0;
895}
896
897static int vidioc_g_tuner (struct file *file, void *priv,
898 struct v4l2_tuner *t)
899{
900 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
901 u32 reg;
902
903 if (unlikely(UNSET == core->board.tuner_type))
904 return -EINVAL;
905 if (0 != t->index)
906 return -EINVAL;
907
908 strcpy(t->name, "Television");
909 t->capability = V4L2_TUNER_CAP_NORM;
910 t->rangehigh = 0xffffffffUL;
911 call_all(core, tuner, g_tuner, t);
912
913 cx88_get_stereo(core ,t);
914 reg = cx_read(MO_DEVICE_STATUS);
915 t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
916 return 0;
917}
918
919static int vidioc_s_tuner (struct file *file, void *priv,
920 struct v4l2_tuner *t)
921{
922 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
923
924 if (UNSET == core->board.tuner_type)
925 return -EINVAL;
926 if (0 != t->index)
927 return -EINVAL;
928
929 cx88_set_stereo(core, t->audmode, 1);
930 return 0;
931}
932
933static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
934{
935 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
936
937 *tvnorm = core->tvnorm;
938 return 0;
939}
940
941static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
942{
943 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
944
945 mutex_lock(&core->lock);
946 cx88_set_tvnorm(core,*id);
947 mutex_unlock(&core->lock);
948 return 0;
949}
950
951/* FIXME: cx88_ioctl_hook not implemented */
952
953static int mpeg_open(struct file *file)
954{
955 struct video_device *vdev = video_devdata(file);
956 struct cx8802_dev *dev = video_drvdata(file);
957 struct cx8802_fh *fh;
958 struct cx8802_driver *drv = NULL;
959 int err;
960
961 dprintk( 1, "%s\n", __func__);
962
963 mutex_lock(&dev->core->lock);
964
965 /* Make sure we can acquire the hardware */
966 drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
967 if (!drv) {
968 dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
969 mutex_unlock(&dev->core->lock);
970 return -ENODEV;
971 }
972
973 err = drv->request_acquire(drv);
974 if (err != 0) {
975 dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
976 mutex_unlock(&dev->core->lock);
977 return err;
978 }
979
980 if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) {
981 drv->request_release(drv);
982 mutex_unlock(&dev->core->lock);
983 return -EINVAL;
984 }
985 dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
986
987 /* allocate + initialize per filehandle data */
988 fh = kzalloc(sizeof(*fh),GFP_KERNEL);
989 if (NULL == fh) {
990 drv->request_release(drv);
991 mutex_unlock(&dev->core->lock);
992 return -ENOMEM;
993 }
994 v4l2_fh_init(&fh->fh, vdev);
995 file->private_data = fh;
996 fh->dev = dev;
997
998 videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
999 &dev->pci->dev, &dev->slock,
1000 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1001 V4L2_FIELD_INTERLACED,
1002 sizeof(struct cx88_buffer),
1003 fh, NULL);
1004
1005 /* FIXME: locking against other video device */
1006 cx88_set_scale(dev->core, dev->width, dev->height,
1007 fh->mpegq.field);
1008
1009 dev->core->mpeg_users++;
1010 mutex_unlock(&dev->core->lock);
1011 v4l2_fh_add(&fh->fh);
1012 return 0;
1013}
1014
1015static int mpeg_release(struct file *file)
1016{
1017 struct cx8802_fh *fh = file->private_data;
1018 struct cx8802_dev *dev = fh->dev;
1019 struct cx8802_driver *drv = NULL;
1020
1021 mutex_lock(&dev->core->lock);
1022
1023 if (dev->mpeg_active && dev->core->mpeg_users == 1)
1024 blackbird_stop_codec(dev);
1025
1026 cx8802_cancel_buffers(fh->dev);
1027 /* stop mpeg capture */
1028 videobuf_stop(&fh->mpegq);
1029
1030 videobuf_mmap_free(&fh->mpegq);
1031
1032 v4l2_fh_del(&fh->fh);
1033 v4l2_fh_exit(&fh->fh);
1034 file->private_data = NULL;
1035 kfree(fh);
1036
1037 /* Make sure we release the hardware */
1038 drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
1039 WARN_ON(!drv);
1040 if (drv)
1041 drv->request_release(drv);
1042
1043 dev->core->mpeg_users--;
1044
1045 mutex_unlock(&dev->core->lock);
1046
1047 return 0;
1048}
1049
1050static ssize_t
1051mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1052{
1053 struct cx8802_fh *fh = file->private_data;
1054 struct cx8802_dev *dev = fh->dev;
1055
1056 if (!dev->mpeg_active)
1057 blackbird_start_codec(file, fh);
1058
1059 return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
1060 file->f_flags & O_NONBLOCK);
1061}
1062
1063static unsigned int
1064mpeg_poll(struct file *file, struct poll_table_struct *wait)
1065{
1066 unsigned long req_events = poll_requested_events(wait);
1067 struct cx8802_fh *fh = file->private_data;
1068 struct cx8802_dev *dev = fh->dev;
1069
1070 if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
1071 blackbird_start_codec(file, fh);
1072
1073 return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
1074}
1075
1076static int
1077mpeg_mmap(struct file *file, struct vm_area_struct * vma)
1078{
1079 struct cx8802_fh *fh = file->private_data;
1080
1081 return videobuf_mmap_mapper(&fh->mpegq, vma);
1082}
1083
1084static const struct v4l2_file_operations mpeg_fops =
1085{
1086 .owner = THIS_MODULE,
1087 .open = mpeg_open,
1088 .release = mpeg_release,
1089 .read = mpeg_read,
1090 .poll = mpeg_poll,
1091 .mmap = mpeg_mmap,
1092 .unlocked_ioctl = video_ioctl2,
1093};
1094
1095static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
1096 .vidioc_querycap = vidioc_querycap,
1097 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1098 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1099 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1100 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1101 .vidioc_reqbufs = vidioc_reqbufs,
1102 .vidioc_querybuf = vidioc_querybuf,
1103 .vidioc_qbuf = vidioc_qbuf,
1104 .vidioc_dqbuf = vidioc_dqbuf,
1105 .vidioc_streamon = vidioc_streamon,
1106 .vidioc_streamoff = vidioc_streamoff,
1107 .vidioc_s_frequency = vidioc_s_frequency,
1108 .vidioc_log_status = vidioc_log_status,
1109 .vidioc_enum_input = vidioc_enum_input,
1110 .vidioc_g_frequency = vidioc_g_frequency,
1111 .vidioc_g_input = vidioc_g_input,
1112 .vidioc_s_input = vidioc_s_input,
1113 .vidioc_g_tuner = vidioc_g_tuner,
1114 .vidioc_s_tuner = vidioc_s_tuner,
1115 .vidioc_g_std = vidioc_g_std,
1116 .vidioc_s_std = vidioc_s_std,
1117 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1118 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1119};
1120
1121static struct video_device cx8802_mpeg_template = {
1122 .name = "cx8802",
1123 .fops = &mpeg_fops,
1124 .ioctl_ops = &mpeg_ioctl_ops,
1125 .tvnorms = CX88_NORMS,
1126};
1127
1128/* ------------------------------------------------------------------ */
1129
1130/* The CX8802 MPEG API will call this when we can use the hardware */
1131static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
1132{
1133 struct cx88_core *core = drv->core;
1134 int err = 0;
1135
1136 switch (core->boardnr) {
1137 case CX88_BOARD_HAUPPAUGE_HVR1300:
1138 /* By default, core setup will leave the cx22702 out of reset, on the bus.
1139 * We left the hardware on power up with the cx22702 active.
1140 * We're being given access to re-arrange the GPIOs.
1141 * Take the bus off the cx22702 and put the cx23416 on it.
1142 */
1143 /* Toggle reset on cx22702 leaving i2c active */
1144 cx_set(MO_GP0_IO, 0x00000080);
1145 udelay(1000);
1146 cx_clear(MO_GP0_IO, 0x00000080);
1147 udelay(50);
1148 cx_set(MO_GP0_IO, 0x00000080);
1149 udelay(1000);
1150 /* tri-state the cx22702 pins */
1151 cx_set(MO_GP0_IO, 0x00000004);
1152 udelay(1000);
1153 break;
1154 default:
1155 err = -ENODEV;
1156 }
1157 return err;
1158}
1159
1160/* The CX8802 MPEG API will call this when we need to release the hardware */
1161static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
1162{
1163 struct cx88_core *core = drv->core;
1164 int err = 0;
1165
1166 switch (core->boardnr) {
1167 case CX88_BOARD_HAUPPAUGE_HVR1300:
1168 /* Exit leaving the cx23416 on the bus */
1169 break;
1170 default:
1171 err = -ENODEV;
1172 }
1173 return err;
1174}
1175
1176static void blackbird_unregister_video(struct cx8802_dev *dev)
1177{
1178 if (dev->mpeg_dev) {
1179 if (video_is_registered(dev->mpeg_dev))
1180 video_unregister_device(dev->mpeg_dev);
1181 else
1182 video_device_release(dev->mpeg_dev);
1183 dev->mpeg_dev = NULL;
1184 }
1185}
1186
1187static int blackbird_register_video(struct cx8802_dev *dev)
1188{
1189 int err;
1190
1191 dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
1192 &cx8802_mpeg_template,"mpeg");
1193 dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
1194 video_set_drvdata(dev->mpeg_dev, dev);
1195 err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
1196 if (err < 0) {
1197 printk(KERN_INFO "%s/2: can't register mpeg device\n",
1198 dev->core->name);
1199 return err;
1200 }
1201 printk(KERN_INFO "%s/2: registered device %s [mpeg]\n",
1202 dev->core->name, video_device_node_name(dev->mpeg_dev));
1203 return 0;
1204}
1205
1206/* ----------------------------------------------------------- */
1207
1208static int cx8802_blackbird_probe(struct cx8802_driver *drv)
1209{
1210 struct cx88_core *core = drv->core;
1211 struct cx8802_dev *dev = core->dvbdev;
1212 int err;
1213
1214 dprintk( 1, "%s\n", __func__);
1215 dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
1216 core->boardnr,
1217 core->name,
1218 core->pci_bus,
1219 core->pci_slot);
1220
1221 err = -ENODEV;
1222 if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
1223 goto fail_core;
1224
1225 dev->width = 720;
1226 if (core->tvnorm & V4L2_STD_525_60) {
1227 dev->height = 480;
1228 } else {
1229 dev->height = 576;
1230 }
1231 dev->cxhdl.port = CX2341X_PORT_STREAMING;
1232 dev->cxhdl.width = dev->width;
1233 dev->cxhdl.height = dev->height;
1234 dev->cxhdl.func = blackbird_mbox_func;
1235 dev->cxhdl.priv = dev;
1236 err = cx2341x_handler_init(&dev->cxhdl, 36);
1237 if (err)
1238 goto fail_core;
1239 v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL);
1240
1241 /* blackbird stuff */
1242 printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
1243 core->name);
1244 host_setup(dev->core);
1245
1246 blackbird_initialize_codec(dev);
1247
1248 /* initial device configuration: needed ? */
1249// init_controls(core);
1250 cx88_set_tvnorm(core,core->tvnorm);
1251 cx88_video_mux(core,0);
1252 cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
1253 cx2341x_handler_setup(&dev->cxhdl);
1254 blackbird_register_video(dev);
1255
1256 return 0;
1257
1258 fail_core:
1259 return err;
1260}
1261
1262static int cx8802_blackbird_remove(struct cx8802_driver *drv)
1263{
1264 struct cx88_core *core = drv->core;
1265 struct cx8802_dev *dev = core->dvbdev;
1266
1267 /* blackbird */
1268 blackbird_unregister_video(drv->core->dvbdev);
1269 v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
1270
1271 return 0;
1272}
1273
1274static struct cx8802_driver cx8802_blackbird_driver = {
1275 .type_id = CX88_MPEG_BLACKBIRD,
1276 .hw_access = CX8802_DRVCTL_SHARED,
1277 .probe = cx8802_blackbird_probe,
1278 .remove = cx8802_blackbird_remove,
1279 .advise_acquire = cx8802_blackbird_advise_acquire,
1280 .advise_release = cx8802_blackbird_advise_release,
1281};
1282
1283static int __init blackbird_init(void)
1284{
1285 printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n",
1286 CX88_VERSION);
1287 return cx8802_register_driver(&cx8802_blackbird_driver);
1288}
1289
1290static void __exit blackbird_fini(void)
1291{
1292 cx8802_unregister_driver(&cx8802_blackbird_driver);
1293}
1294
1295module_init(blackbird_init);
1296module_exit(blackbird_fini);
1297
1298module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
1299MODULE_PARM_DESC(debug,"enable debug messages [video]");
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
new file mode 100644
index 000000000000..0c255248cbcd
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -0,0 +1,3811 @@
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_FMD1216MEX_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 = UNSET,
1577 .radio_addr = ADDR_UNSET,
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 = UNSET,
1615 .radio_addr = ADDR_UNSET,
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_WINFAST_TV2000_XP_GLOBAL_6F36] = {
1647 .name = "Leadtek TV2000 XP Global (SC4100)",
1648 .tuner_type = TUNER_XC4000,
1649 .tuner_addr = 0x61,
1650 .radio_type = UNSET,
1651 .radio_addr = ADDR_UNSET,
1652 .input = { {
1653 .type = CX88_VMUX_TELEVISION,
1654 .vmux = 0,
1655 .gpio0 = 0x0400, /* pin 2 = 0 */
1656 .gpio1 = 0x0000,
1657 .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */
1658 .gpio3 = 0x0000,
1659 }, {
1660 .type = CX88_VMUX_COMPOSITE1,
1661 .vmux = 1,
1662 .gpio0 = 0x0400, /* pin 2 = 0 */
1663 .gpio1 = 0x0000,
1664 .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */
1665 .gpio3 = 0x0000,
1666 }, {
1667 .type = CX88_VMUX_SVIDEO,
1668 .vmux = 2,
1669 .gpio0 = 0x0400, /* pin 2 = 0 */
1670 .gpio1 = 0x0000,
1671 .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */
1672 .gpio3 = 0x0000,
1673 } },
1674 .radio = {
1675 .type = CX88_RADIO,
1676 .gpio0 = 0x0400, /* pin 2 = 0 */
1677 .gpio1 = 0x0000,
1678 .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */
1679 .gpio3 = 0x0000,
1680 },
1681 },
1682 [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43] = {
1683 .name = "Leadtek TV2000 XP Global (XC4100)",
1684 .tuner_type = TUNER_XC4000,
1685 .tuner_addr = 0x61,
1686 .radio_type = UNSET,
1687 .radio_addr = ADDR_UNSET,
1688 .input = { {
1689 .type = CX88_VMUX_TELEVISION,
1690 .vmux = 0,
1691 .gpio0 = 0x0400, /* pin 2 = 0 */
1692 .gpio1 = 0x6040, /* pin 14 = 1, pin 13 = 0 */
1693 .gpio2 = 0x0000,
1694 .gpio3 = 0x0000,
1695 }, {
1696 .type = CX88_VMUX_COMPOSITE1,
1697 .vmux = 1,
1698 .gpio0 = 0x0400, /* pin 2 = 0 */
1699 .gpio1 = 0x6060, /* pin 14 = 1, pin 13 = 1 */
1700 .gpio2 = 0x0000,
1701 .gpio3 = 0x0000,
1702 }, {
1703 .type = CX88_VMUX_SVIDEO,
1704 .vmux = 2,
1705 .gpio0 = 0x0400, /* pin 2 = 0 */
1706 .gpio1 = 0x6060, /* pin 14 = 1, pin 13 = 1 */
1707 .gpio2 = 0x0000,
1708 .gpio3 = 0x0000,
1709 } },
1710 .radio = {
1711 .type = CX88_RADIO,
1712 .gpio0 = 0x0400, /* pin 2 = 0 */
1713 .gpio1 = 0x6000, /* pin 14 = 1, pin 13 = 0 */
1714 .gpio2 = 0x0000,
1715 .gpio3 = 0x0000,
1716 },
1717 },
1718 [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
1719 .name = "PowerColor RA330", /* Long names may confuse LIRC. */
1720 .tuner_type = TUNER_XC2028,
1721 .tuner_addr = 0x61,
1722 .input = { {
1723 .type = CX88_VMUX_DEBUG,
1724 .vmux = 3, /* Due to the way the cx88 driver is written, */
1725 .gpio0 = 0x00ff, /* there is no way to deactivate audio pass- */
1726 .gpio1 = 0xf39d, /* through without this entry. Furthermore, if */
1727 .gpio3 = 0x0000, /* the TV mux entry is first, you get audio */
1728 }, { /* from the tuner on boot for a little while. */
1729 .type = CX88_VMUX_TELEVISION,
1730 .vmux = 0,
1731 .gpio0 = 0x00ff,
1732 .gpio1 = 0xf35d,
1733 .gpio3 = 0x0000,
1734 }, {
1735 .type = CX88_VMUX_COMPOSITE1,
1736 .vmux = 1,
1737 .gpio0 = 0x00ff,
1738 .gpio1 = 0xf37d,
1739 .gpio3 = 0x0000,
1740 }, {
1741 .type = CX88_VMUX_SVIDEO,
1742 .vmux = 2,
1743 .gpio0 = 0x000ff,
1744 .gpio1 = 0x0f37d,
1745 .gpio3 = 0x00000,
1746 } },
1747 .radio = {
1748 .type = CX88_RADIO,
1749 .gpio0 = 0x000ff,
1750 .gpio1 = 0x0f35d,
1751 .gpio3 = 0x00000,
1752 },
1753 },
1754 [CX88_BOARD_GENIATECH_X8000_MT] = {
1755 /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */
1756 .name = "Geniatech X8000-MT DVBT",
1757 .tuner_type = TUNER_XC2028,
1758 .tuner_addr = 0x61,
1759 .input = { {
1760 .type = CX88_VMUX_TELEVISION,
1761 .vmux = 0,
1762 .gpio0 = 0x00000000,
1763 .gpio1 = 0x00e3e341,
1764 .gpio2 = 0x00000000,
1765 .gpio3 = 0x00000000,
1766 }, {
1767 .type = CX88_VMUX_COMPOSITE1,
1768 .vmux = 1,
1769 .gpio0 = 0x00000000,
1770 .gpio1 = 0x00e3e361,
1771 .gpio2 = 0x00000000,
1772 .gpio3 = 0x00000000,
1773 }, {
1774 .type = CX88_VMUX_SVIDEO,
1775 .vmux = 2,
1776 .gpio0 = 0x00000000,
1777 .gpio1 = 0x00e3e361,
1778 .gpio2 = 0x00000000,
1779 .gpio3 = 0x00000000,
1780 } },
1781 .radio = {
1782 .type = CX88_RADIO,
1783 .gpio0 = 0x00000000,
1784 .gpio1 = 0x00e3e341,
1785 .gpio2 = 0x00000000,
1786 .gpio3 = 0x00000000,
1787 },
1788 .mpeg = CX88_MPEG_DVB,
1789 },
1790 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
1791 .name = "DViCO FusionHDTV DVB-T PRO",
1792 .tuner_type = TUNER_XC2028,
1793 .tuner_addr = 0x61,
1794 .radio_type = UNSET,
1795 .radio_addr = ADDR_UNSET,
1796 .input = { {
1797 .type = CX88_VMUX_COMPOSITE1,
1798 .vmux = 1,
1799 .gpio0 = 0x000067df,
1800 }, {
1801 .type = CX88_VMUX_SVIDEO,
1802 .vmux = 2,
1803 .gpio0 = 0x000067df,
1804 } },
1805 .mpeg = CX88_MPEG_DVB,
1806 },
1807 [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = {
1808 .name = "DViCO FusionHDTV 7 Gold",
1809 .tuner_type = TUNER_XC5000,
1810 .radio_type = UNSET,
1811 .tuner_addr = ADDR_UNSET,
1812 .radio_addr = ADDR_UNSET,
1813 .input = {{
1814 .type = CX88_VMUX_TELEVISION,
1815 .vmux = 0,
1816 .gpio0 = 0x10df,
1817 },{
1818 .type = CX88_VMUX_COMPOSITE1,
1819 .vmux = 1,
1820 .gpio0 = 0x16d9,
1821 },{
1822 .type = CX88_VMUX_SVIDEO,
1823 .vmux = 2,
1824 .gpio0 = 0x16d9,
1825 }},
1826 .mpeg = CX88_MPEG_DVB,
1827 },
1828 [CX88_BOARD_PROLINK_PV_8000GT] = {
1829 .name = "Prolink Pixelview MPEG 8000GT",
1830 .tuner_type = TUNER_XC2028,
1831 .tuner_addr = 0x61,
1832 .input = { {
1833 .type = CX88_VMUX_TELEVISION,
1834 .vmux = 0,
1835 .gpio0 = 0x0ff,
1836 .gpio2 = 0x0cfb,
1837 }, {
1838 .type = CX88_VMUX_COMPOSITE1,
1839 .vmux = 1,
1840 .gpio2 = 0x0cfb,
1841 }, {
1842 .type = CX88_VMUX_SVIDEO,
1843 .vmux = 2,
1844 .gpio2 = 0x0cfb,
1845 } },
1846 .radio = {
1847 .type = CX88_RADIO,
1848 .gpio2 = 0x0cfb,
1849 },
1850 },
1851 [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = {
1852 .name = "Prolink Pixelview Global Extreme",
1853 .tuner_type = TUNER_XC2028,
1854 .tuner_addr = 0x61,
1855 .input = { {
1856 .type = CX88_VMUX_TELEVISION,
1857 .vmux = 0,
1858 .gpio0 = 0x04fb,
1859 .gpio1 = 0x04080,
1860 .gpio2 = 0x0cf7,
1861 }, {
1862 .type = CX88_VMUX_COMPOSITE1,
1863 .vmux = 1,
1864 .gpio0 = 0x04fb,
1865 .gpio1 = 0x04080,
1866 .gpio2 = 0x0cfb,
1867 }, {
1868 .type = CX88_VMUX_SVIDEO,
1869 .vmux = 2,
1870 .gpio0 = 0x04fb,
1871 .gpio1 = 0x04080,
1872 .gpio2 = 0x0cfb,
1873 } },
1874 .radio = {
1875 .type = CX88_RADIO,
1876 .gpio0 = 0x04ff,
1877 .gpio1 = 0x04080,
1878 .gpio2 = 0x0cf7,
1879 },
1880 },
1881 /* Both radio, analog and ATSC work with this board.
1882 However, for analog to work, s5h1409 gate should be open,
1883 otherwise, tuner-xc3028 won't be detected.
1884 A proper fix require using the newer i2c methods to add
1885 tuner-xc3028 without doing an i2c probe.
1886 */
1887 [CX88_BOARD_KWORLD_ATSC_120] = {
1888 .name = "Kworld PlusTV HD PCI 120 (ATSC 120)",
1889 .tuner_type = TUNER_XC2028,
1890 .radio_type = UNSET,
1891 .tuner_addr = ADDR_UNSET,
1892 .radio_addr = ADDR_UNSET,
1893 .input = { {
1894 .type = CX88_VMUX_TELEVISION,
1895 .vmux = 0,
1896 .gpio0 = 0x000000ff,
1897 .gpio1 = 0x0000f35d,
1898 .gpio2 = 0x00000000,
1899 }, {
1900 .type = CX88_VMUX_COMPOSITE1,
1901 .vmux = 1,
1902 .gpio0 = 0x000000ff,
1903 .gpio1 = 0x0000f37e,
1904 .gpio2 = 0x00000000,
1905 }, {
1906 .type = CX88_VMUX_SVIDEO,
1907 .vmux = 2,
1908 .gpio0 = 0x000000ff,
1909 .gpio1 = 0x0000f37e,
1910 .gpio2 = 0x00000000,
1911 } },
1912 .radio = {
1913 .type = CX88_RADIO,
1914 .gpio0 = 0x000000ff,
1915 .gpio1 = 0x0000f35d,
1916 .gpio2 = 0x00000000,
1917 },
1918 .mpeg = CX88_MPEG_DVB,
1919 },
1920 [CX88_BOARD_HAUPPAUGE_HVR4000] = {
1921 .name = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid",
1922 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
1923 .radio_type = UNSET,
1924 .tuner_addr = ADDR_UNSET,
1925 .radio_addr = ADDR_UNSET,
1926 .tda9887_conf = TDA9887_PRESENT,
1927 .audio_chip = V4L2_IDENT_WM8775,
1928 /*
1929 * GPIO0 (WINTV2000)
1930 *
1931 * Analogue SAT DVB-T
1932 * Antenna 0xc4bf 0xc4bb
1933 * Composite 0xc4bf 0xc4bb
1934 * S-Video 0xc4bf 0xc4bb
1935 * Composite1 0xc4ff 0xc4fb
1936 * S-Video1 0xc4ff 0xc4fb
1937 *
1938 * BIT VALUE FUNCTION GP{x}_IO
1939 * 0 1 I:?
1940 * 1 1 I:?
1941 * 2 1 O:MPEG PORT 0=DVB-T 1=DVB-S
1942 * 3 1 I:?
1943 * 4 1 I:?
1944 * 5 1 I:?
1945 * 6 0 O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION
1946 * 7 1 O:DVB-T DEMOD RESET LOW
1947 *
1948 * BIT VALUE FUNCTION GP{x}_OE
1949 * 8 0 I
1950 * 9 0 I
1951 * a 1 O
1952 * b 0 I
1953 * c 0 I
1954 * d 0 I
1955 * e 1 O
1956 * f 1 O
1957 *
1958 * WM8775 ADC
1959 *
1960 * 1: TV Audio / FM Mono
1961 * 2: Line-In
1962 * 3: Line-In Expansion
1963 * 4: FM Stereo
1964 */
1965 .input = {{
1966 .type = CX88_VMUX_TELEVISION,
1967 .vmux = 0,
1968 .gpio0 = 0xc4bf,
1969 /* 1: TV Audio / FM Mono */
1970 .audioroute = 1,
1971 }, {
1972 .type = CX88_VMUX_COMPOSITE1,
1973 .vmux = 1,
1974 .gpio0 = 0xc4bf,
1975 /* 2: Line-In */
1976 .audioroute = 2,
1977 }, {
1978 .type = CX88_VMUX_SVIDEO,
1979 .vmux = 2,
1980 .gpio0 = 0xc4bf,
1981 /* 2: Line-In */
1982 .audioroute = 2,
1983 } },
1984 .radio = {
1985 .type = CX88_RADIO,
1986 .gpio0 = 0xc4bf,
1987 /* 4: FM Stereo */
1988 .audioroute = 8,
1989 },
1990 .mpeg = CX88_MPEG_DVB,
1991 .num_frontends = 2,
1992 },
1993 [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = {
1994 .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2",
1995 .tuner_type = UNSET,
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 } },
2003 .mpeg = CX88_MPEG_DVB,
2004 },
2005 [CX88_BOARD_TEVII_S420] = {
2006 .name = "TeVii S420 DVB-S",
2007 .tuner_type = UNSET,
2008 .radio_type = UNSET,
2009 .tuner_addr = ADDR_UNSET,
2010 .radio_addr = ADDR_UNSET,
2011 .input = {{
2012 .type = CX88_VMUX_DVB,
2013 .vmux = 0,
2014 } },
2015 .mpeg = CX88_MPEG_DVB,
2016 },
2017 [CX88_BOARD_TEVII_S460] = {
2018 .name = "TeVii S460 DVB-S/S2",
2019 .tuner_type = UNSET,
2020 .radio_type = UNSET,
2021 .tuner_addr = ADDR_UNSET,
2022 .radio_addr = ADDR_UNSET,
2023 .input = {{
2024 .type = CX88_VMUX_DVB,
2025 .vmux = 0,
2026 } },
2027 .mpeg = CX88_MPEG_DVB,
2028 },
2029 [CX88_BOARD_TEVII_S464] = {
2030 .name = "TeVii S464 DVB-S/S2",
2031 .tuner_type = UNSET,
2032 .radio_type = UNSET,
2033 .tuner_addr = ADDR_UNSET,
2034 .radio_addr = ADDR_UNSET,
2035 .input = {{
2036 .type = CX88_VMUX_DVB,
2037 .vmux = 0,
2038 } },
2039 .mpeg = CX88_MPEG_DVB,
2040 },
2041 [CX88_BOARD_OMICOM_SS4_PCI] = {
2042 .name = "Omicom SS4 DVB-S/S2 PCI",
2043 .tuner_type = UNSET,
2044 .radio_type = UNSET,
2045 .tuner_addr = ADDR_UNSET,
2046 .radio_addr = ADDR_UNSET,
2047 .input = {{
2048 .type = CX88_VMUX_DVB,
2049 .vmux = 0,
2050 } },
2051 .mpeg = CX88_MPEG_DVB,
2052 },
2053 [CX88_BOARD_TBS_8910] = {
2054 .name = "TBS 8910 DVB-S",
2055 .tuner_type = UNSET,
2056 .radio_type = UNSET,
2057 .tuner_addr = ADDR_UNSET,
2058 .radio_addr = ADDR_UNSET,
2059 .input = {{
2060 .type = CX88_VMUX_DVB,
2061 .vmux = 0,
2062 } },
2063 .mpeg = CX88_MPEG_DVB,
2064 },
2065 [CX88_BOARD_TBS_8920] = {
2066 .name = "TBS 8920 DVB-S/S2",
2067 .tuner_type = TUNER_ABSENT,
2068 .radio_type = UNSET,
2069 .tuner_addr = ADDR_UNSET,
2070 .radio_addr = ADDR_UNSET,
2071 .input = {{
2072 .type = CX88_VMUX_DVB,
2073 .vmux = 0,
2074 .gpio0 = 0x8080,
2075 } },
2076 .mpeg = CX88_MPEG_DVB,
2077 },
2078 [CX88_BOARD_PROF_6200] = {
2079 .name = "Prof 6200 DVB-S",
2080 .tuner_type = UNSET,
2081 .radio_type = UNSET,
2082 .tuner_addr = ADDR_UNSET,
2083 .radio_addr = ADDR_UNSET,
2084 .input = {{
2085 .type = CX88_VMUX_DVB,
2086 .vmux = 0,
2087 } },
2088 .mpeg = CX88_MPEG_DVB,
2089 },
2090 [CX88_BOARD_PROF_7300] = {
2091 .name = "PROF 7300 DVB-S/S2",
2092 .tuner_type = UNSET,
2093 .radio_type = UNSET,
2094 .tuner_addr = ADDR_UNSET,
2095 .radio_addr = ADDR_UNSET,
2096 .input = {{
2097 .type = CX88_VMUX_DVB,
2098 .vmux = 0,
2099 } },
2100 .mpeg = CX88_MPEG_DVB,
2101 },
2102 [CX88_BOARD_SATTRADE_ST4200] = {
2103 .name = "SATTRADE ST4200 DVB-S/S2",
2104 .tuner_type = UNSET,
2105 .radio_type = UNSET,
2106 .tuner_addr = ADDR_UNSET,
2107 .radio_addr = ADDR_UNSET,
2108 .input = {{
2109 .type = CX88_VMUX_DVB,
2110 .vmux = 0,
2111 } },
2112 .mpeg = CX88_MPEG_DVB,
2113 },
2114 [CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII] = {
2115 .name = "Terratec Cinergy HT PCI MKII",
2116 .tuner_type = TUNER_XC2028,
2117 .tuner_addr = 0x61,
2118 .radio_type = UNSET,
2119 .radio_addr = ADDR_UNSET,
2120 .input = { {
2121 .type = CX88_VMUX_TELEVISION,
2122 .vmux = 0,
2123 .gpio0 = 0x004ff,
2124 .gpio1 = 0x010ff,
2125 .gpio2 = 0x00001,
2126 }, {
2127 .type = CX88_VMUX_COMPOSITE1,
2128 .vmux = 1,
2129 .gpio0 = 0x004fb,
2130 .gpio1 = 0x010ef,
2131 .audioroute = 1,
2132 }, {
2133 .type = CX88_VMUX_SVIDEO,
2134 .vmux = 2,
2135 .gpio0 = 0x004fb,
2136 .gpio1 = 0x010ef,
2137 .audioroute = 1,
2138 } },
2139 .radio = {
2140 .type = CX88_RADIO,
2141 .gpio0 = 0x004ff,
2142 .gpio1 = 0x010ff,
2143 .gpio2 = 0x0ff,
2144 },
2145 .mpeg = CX88_MPEG_DVB,
2146 },
2147 [CX88_BOARD_HAUPPAUGE_IRONLY] = {
2148 .name = "Hauppauge WinTV-IR Only",
2149 .tuner_type = UNSET,
2150 .radio_type = UNSET,
2151 .tuner_addr = ADDR_UNSET,
2152 .radio_addr = ADDR_UNSET,
2153 },
2154 [CX88_BOARD_WINFAST_DTV1800H] = {
2155 .name = "Leadtek WinFast DTV1800 Hybrid",
2156 .tuner_type = TUNER_XC2028,
2157 .radio_type = UNSET,
2158 .tuner_addr = 0x61,
2159 .radio_addr = ADDR_UNSET,
2160 /*
2161 * GPIO setting
2162 *
2163 * 2: mute (0=off,1=on)
2164 * 12: tuner reset pin
2165 * 13: audio source (0=tuner audio,1=line in)
2166 * 14: FM (0=on,1=off ???)
2167 */
2168 .input = {{
2169 .type = CX88_VMUX_TELEVISION,
2170 .vmux = 0,
2171 .gpio0 = 0x0400, /* pin 2 = 0 */
2172 .gpio1 = 0x6040, /* pin 13 = 0, pin 14 = 1 */
2173 .gpio2 = 0x0000,
2174 }, {
2175 .type = CX88_VMUX_COMPOSITE1,
2176 .vmux = 1,
2177 .gpio0 = 0x0400, /* pin 2 = 0 */
2178 .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
2179 .gpio2 = 0x0000,
2180 }, {
2181 .type = CX88_VMUX_SVIDEO,
2182 .vmux = 2,
2183 .gpio0 = 0x0400, /* pin 2 = 0 */
2184 .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
2185 .gpio2 = 0x0000,
2186 } },
2187 .radio = {
2188 .type = CX88_RADIO,
2189 .gpio0 = 0x0400, /* pin 2 = 0 */
2190 .gpio1 = 0x6000, /* pin 13 = 0, pin 14 = 0 */
2191 .gpio2 = 0x0000,
2192 },
2193 .mpeg = CX88_MPEG_DVB,
2194 },
2195 [CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
2196 .name = "Leadtek WinFast DTV1800 H (XC4000)",
2197 .tuner_type = TUNER_XC4000,
2198 .radio_type = UNSET,
2199 .tuner_addr = 0x61,
2200 .radio_addr = ADDR_UNSET,
2201 /*
2202 * GPIO setting
2203 *
2204 * 2: mute (0=off,1=on)
2205 * 12: tuner reset pin
2206 * 13: audio source (0=tuner audio,1=line in)
2207 * 14: FM (0=on,1=off ???)
2208 */
2209 .input = {{
2210 .type = CX88_VMUX_TELEVISION,
2211 .vmux = 0,
2212 .gpio0 = 0x0400, /* pin 2 = 0 */
2213 .gpio1 = 0x6040, /* pin 13 = 0, pin 14 = 1 */
2214 .gpio2 = 0x0000,
2215 }, {
2216 .type = CX88_VMUX_COMPOSITE1,
2217 .vmux = 1,
2218 .gpio0 = 0x0400, /* pin 2 = 0 */
2219 .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
2220 .gpio2 = 0x0000,
2221 }, {
2222 .type = CX88_VMUX_SVIDEO,
2223 .vmux = 2,
2224 .gpio0 = 0x0400, /* pin 2 = 0 */
2225 .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
2226 .gpio2 = 0x0000,
2227 }},
2228 .radio = {
2229 .type = CX88_RADIO,
2230 .gpio0 = 0x0400, /* pin 2 = 0 */
2231 .gpio1 = 0x6000, /* pin 13 = 0, pin 14 = 0 */
2232 .gpio2 = 0x0000,
2233 },
2234 .mpeg = CX88_MPEG_DVB,
2235 },
2236 [CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
2237 .name = "Leadtek WinFast DTV2000 H PLUS",
2238 .tuner_type = TUNER_XC4000,
2239 .radio_type = UNSET,
2240 .tuner_addr = 0x61,
2241 .radio_addr = ADDR_UNSET,
2242 /*
2243 * GPIO
2244 * 2: 1: mute audio
2245 * 12: 0: reset XC4000
2246 * 13: 1: audio input is line in (0: tuner)
2247 * 14: 0: FM radio
2248 * 16: 0: RF input is cable
2249 */
2250 .input = {{
2251 .type = CX88_VMUX_TELEVISION,
2252 .vmux = 0,
2253 .gpio0 = 0x0403,
2254 .gpio1 = 0xF0D7,
2255 .gpio2 = 0x0101,
2256 .gpio3 = 0x0000,
2257 }, {
2258 .type = CX88_VMUX_CABLE,
2259 .vmux = 0,
2260 .gpio0 = 0x0403,
2261 .gpio1 = 0xF0D7,
2262 .gpio2 = 0x0100,
2263 .gpio3 = 0x0000,
2264 }, {
2265 .type = CX88_VMUX_COMPOSITE1,
2266 .vmux = 1,
2267 .gpio0 = 0x0403, /* was 0x0407 */
2268 .gpio1 = 0xF0F7,
2269 .gpio2 = 0x0101,
2270 .gpio3 = 0x0000,
2271 }, {
2272 .type = CX88_VMUX_SVIDEO,
2273 .vmux = 2,
2274 .gpio0 = 0x0403, /* was 0x0407 */
2275 .gpio1 = 0xF0F7,
2276 .gpio2 = 0x0101,
2277 .gpio3 = 0x0000,
2278 }},
2279 .radio = {
2280 .type = CX88_RADIO,
2281 .gpio0 = 0x0403,
2282 .gpio1 = 0xF097,
2283 .gpio2 = 0x0100,
2284 .gpio3 = 0x0000,
2285 },
2286 .mpeg = CX88_MPEG_DVB,
2287 },
2288 [CX88_BOARD_PROF_7301] = {
2289 .name = "Prof 7301 DVB-S/S2",
2290 .tuner_type = UNSET,
2291 .radio_type = UNSET,
2292 .tuner_addr = ADDR_UNSET,
2293 .radio_addr = ADDR_UNSET,
2294 .input = { {
2295 .type = CX88_VMUX_DVB,
2296 .vmux = 0,
2297 } },
2298 .mpeg = CX88_MPEG_DVB,
2299 },
2300 [CX88_BOARD_TWINHAN_VP1027_DVBS] = {
2301 .name = "Twinhan VP-1027 DVB-S",
2302 .tuner_type = TUNER_ABSENT,
2303 .radio_type = UNSET,
2304 .tuner_addr = ADDR_UNSET,
2305 .radio_addr = ADDR_UNSET,
2306 .input = {{
2307 .type = CX88_VMUX_DVB,
2308 .vmux = 0,
2309 } },
2310 .mpeg = CX88_MPEG_DVB,
2311 },
2312};
2313
2314/* ------------------------------------------------------------------ */
2315/* PCI subsystem IDs */
2316
2317static const struct cx88_subid cx88_subids[] = {
2318 {
2319 .subvendor = 0x0070,
2320 .subdevice = 0x3400,
2321 .card = CX88_BOARD_HAUPPAUGE,
2322 },{
2323 .subvendor = 0x0070,
2324 .subdevice = 0x3401,
2325 .card = CX88_BOARD_HAUPPAUGE,
2326 },{
2327 .subvendor = 0x14c7,
2328 .subdevice = 0x0106,
2329 .card = CX88_BOARD_GDI,
2330 },{
2331 .subvendor = 0x14c7,
2332 .subdevice = 0x0107, /* with mpeg encoder */
2333 .card = CX88_BOARD_GDI,
2334 },{
2335 .subvendor = PCI_VENDOR_ID_ATI,
2336 .subdevice = 0x00f8,
2337 .card = CX88_BOARD_ATI_WONDER_PRO,
2338 }, {
2339 .subvendor = PCI_VENDOR_ID_ATI,
2340 .subdevice = 0x00f9,
2341 .card = CX88_BOARD_ATI_WONDER_PRO,
2342 }, {
2343 .subvendor = 0x107d,
2344 .subdevice = 0x6611,
2345 .card = CX88_BOARD_WINFAST2000XP_EXPERT,
2346 },{
2347 .subvendor = 0x107d,
2348 .subdevice = 0x6613, /* NTSC */
2349 .card = CX88_BOARD_WINFAST2000XP_EXPERT,
2350 },{
2351 .subvendor = 0x107d,
2352 .subdevice = 0x6620,
2353 .card = CX88_BOARD_WINFAST_DV2000,
2354 },{
2355 .subvendor = 0x107d,
2356 .subdevice = 0x663b,
2357 .card = CX88_BOARD_LEADTEK_PVR2000,
2358 },{
2359 .subvendor = 0x107d,
2360 .subdevice = 0x663c,
2361 .card = CX88_BOARD_LEADTEK_PVR2000,
2362 },{
2363 .subvendor = 0x1461,
2364 .subdevice = 0x000b,
2365 .card = CX88_BOARD_AVERTV_STUDIO_303,
2366 },{
2367 .subvendor = 0x1462,
2368 .subdevice = 0x8606,
2369 .card = CX88_BOARD_MSI_TVANYWHERE_MASTER,
2370 },{
2371 .subvendor = 0x10fc,
2372 .subdevice = 0xd003,
2373 .card = CX88_BOARD_IODATA_GVVCP3PCI,
2374 },{
2375 .subvendor = 0x1043,
2376 .subdevice = 0x4823, /* with mpeg encoder */
2377 .card = CX88_BOARD_ASUS_PVR_416,
2378 },{
2379 .subvendor = 0x17de,
2380 .subdevice = 0x08a6,
2381 .card = CX88_BOARD_KWORLD_DVB_T,
2382 },{
2383 .subvendor = 0x18ac,
2384 .subdevice = 0xd810,
2385 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
2386 },{
2387 .subvendor = 0x18ac,
2388 .subdevice = 0xd820,
2389 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T,
2390 },{
2391 .subvendor = 0x18ac,
2392 .subdevice = 0xdb00,
2393 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1,
2394 },{
2395 .subvendor = 0x0070,
2396 .subdevice = 0x9002,
2397 .card = CX88_BOARD_HAUPPAUGE_DVB_T1,
2398 },{
2399 .subvendor = 0x14f1,
2400 .subdevice = 0x0187,
2401 .card = CX88_BOARD_CONEXANT_DVB_T1,
2402 },{
2403 .subvendor = 0x1540,
2404 .subdevice = 0x2580,
2405 .card = CX88_BOARD_PROVIDEO_PV259,
2406 },{
2407 .subvendor = 0x18ac,
2408 .subdevice = 0xdb10,
2409 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
2410 },{
2411 .subvendor = 0x1554,
2412 .subdevice = 0x4811,
2413 .card = CX88_BOARD_PIXELVIEW,
2414 },{
2415 .subvendor = 0x7063,
2416 .subdevice = 0x3000, /* HD-3000 card */
2417 .card = CX88_BOARD_PCHDTV_HD3000,
2418 },{
2419 .subvendor = 0x17de,
2420 .subdevice = 0xa8a6,
2421 .card = CX88_BOARD_DNTV_LIVE_DVB_T,
2422 },{
2423 .subvendor = 0x0070,
2424 .subdevice = 0x2801,
2425 .card = CX88_BOARD_HAUPPAUGE_ROSLYN,
2426 },{
2427 .subvendor = 0x14f1,
2428 .subdevice = 0x0342,
2429 .card = CX88_BOARD_DIGITALLOGIC_MEC,
2430 },{
2431 .subvendor = 0x10fc,
2432 .subdevice = 0xd035,
2433 .card = CX88_BOARD_IODATA_GVBCTV7E,
2434 },{
2435 .subvendor = 0x1421,
2436 .subdevice = 0x0334,
2437 .card = CX88_BOARD_ADSTECH_DVB_T_PCI,
2438 },{
2439 .subvendor = 0x153b,
2440 .subdevice = 0x1166,
2441 .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1,
2442 },{
2443 .subvendor = 0x18ac,
2444 .subdevice = 0xd500,
2445 .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD,
2446 },{
2447 .subvendor = 0x1461,
2448 .subdevice = 0x8011,
2449 .card = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550,
2450 },{
2451 .subvendor = PCI_VENDOR_ID_ATI,
2452 .subdevice = 0xa101,
2453 .card = CX88_BOARD_ATI_HDTVWONDER,
2454 },{
2455 .subvendor = 0x107d,
2456 .subdevice = 0x665f,
2457 .card = CX88_BOARD_WINFAST_DTV1000,
2458 },{
2459 .subvendor = 0x1461,
2460 .subdevice = 0x000a,
2461 .card = CX88_BOARD_AVERTV_303,
2462 },{
2463 .subvendor = 0x0070,
2464 .subdevice = 0x9200,
2465 .card = CX88_BOARD_HAUPPAUGE_NOVASE2_S1,
2466 },{
2467 .subvendor = 0x0070,
2468 .subdevice = 0x9201,
2469 .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
2470 },{
2471 .subvendor = 0x0070,
2472 .subdevice = 0x9202,
2473 .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
2474 },{
2475 .subvendor = 0x17de,
2476 .subdevice = 0x08b2,
2477 .card = CX88_BOARD_KWORLD_DVBS_100,
2478 },{
2479 .subvendor = 0x0070,
2480 .subdevice = 0x9400,
2481 .card = CX88_BOARD_HAUPPAUGE_HVR1100,
2482 },{
2483 .subvendor = 0x0070,
2484 .subdevice = 0x9402,
2485 .card = CX88_BOARD_HAUPPAUGE_HVR1100,
2486 },{
2487 .subvendor = 0x0070,
2488 .subdevice = 0x9800,
2489 .card = CX88_BOARD_HAUPPAUGE_HVR1100LP,
2490 },{
2491 .subvendor = 0x0070,
2492 .subdevice = 0x9802,
2493 .card = CX88_BOARD_HAUPPAUGE_HVR1100LP,
2494 },{
2495 .subvendor = 0x0070,
2496 .subdevice = 0x9001,
2497 .card = CX88_BOARD_HAUPPAUGE_DVB_T1,
2498 },{
2499 .subvendor = 0x1822,
2500 .subdevice = 0x0025,
2501 .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
2502 },{
2503 .subvendor = 0x17de,
2504 .subdevice = 0x08a1,
2505 .card = CX88_BOARD_KWORLD_DVB_T_CX22702,
2506 },{
2507 .subvendor = 0x18ac,
2508 .subdevice = 0xdb50,
2509 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
2510 },{
2511 .subvendor = 0x18ac,
2512 .subdevice = 0xdb54,
2513 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
2514 /* Re-branded DViCO: DigitalNow DVB-T Dual */
2515 },{
2516 .subvendor = 0x18ac,
2517 .subdevice = 0xdb11,
2518 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
2519 /* Re-branded DViCO: UltraView DVB-T Plus */
2520 }, {
2521 .subvendor = 0x18ac,
2522 .subdevice = 0xdb30,
2523 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO,
2524 }, {
2525 .subvendor = 0x17de,
2526 .subdevice = 0x0840,
2527 .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
2528 },{
2529 .subvendor = 0x1421,
2530 .subdevice = 0x0305,
2531 .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
2532 },{
2533 .subvendor = 0x18ac,
2534 .subdevice = 0xdb40,
2535 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
2536 },{
2537 .subvendor = 0x18ac,
2538 .subdevice = 0xdb44,
2539 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
2540 },{
2541 .subvendor = 0x7063,
2542 .subdevice = 0x5500,
2543 .card = CX88_BOARD_PCHDTV_HD5500,
2544 },{
2545 .subvendor = 0x17de,
2546 .subdevice = 0x0841,
2547 .card = CX88_BOARD_KWORLD_MCE200_DELUXE,
2548 },{
2549 .subvendor = 0x1822,
2550 .subdevice = 0x0019,
2551 .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
2552 },{
2553 .subvendor = 0x1554,
2554 .subdevice = 0x4813,
2555 .card = CX88_BOARD_PIXELVIEW_PLAYTV_P7000,
2556 },{
2557 .subvendor = 0x14f1,
2558 .subdevice = 0x0842,
2559 .card = CX88_BOARD_NPGTECH_REALTV_TOP10FM,
2560 },{
2561 .subvendor = 0x107d,
2562 .subdevice = 0x665e,
2563 .card = CX88_BOARD_WINFAST_DTV2000H,
2564 },{
2565 .subvendor = 0x107d,
2566 .subdevice = 0x6f2b,
2567 .card = CX88_BOARD_WINFAST_DTV2000H_J,
2568 },{
2569 .subvendor = 0x18ac,
2570 .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */
2571 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
2572 },{
2573 .subvendor = 0x14f1,
2574 .subdevice = 0x0084,
2575 .card = CX88_BOARD_GENIATECH_DVBS,
2576 },{
2577 .subvendor = 0x0070,
2578 .subdevice = 0x1404,
2579 .card = CX88_BOARD_HAUPPAUGE_HVR3000,
2580 }, {
2581 .subvendor = 0x18ac,
2582 .subdevice = 0xdc00,
2583 .card = CX88_BOARD_SAMSUNG_SMT_7020,
2584 }, {
2585 .subvendor = 0x18ac,
2586 .subdevice = 0xdccd,
2587 .card = CX88_BOARD_SAMSUNG_SMT_7020,
2588 },{
2589 .subvendor = 0x1461,
2590 .subdevice = 0xc111, /* AverMedia M150-D */
2591 /* This board is known to work with the ASUS PVR416 config */
2592 .card = CX88_BOARD_ASUS_PVR_416,
2593 },{
2594 .subvendor = 0xc180,
2595 .subdevice = 0xc980,
2596 .card = CX88_BOARD_TE_DTV_250_OEM_SWANN,
2597 },{
2598 .subvendor = 0x0070,
2599 .subdevice = 0x9600,
2600 .card = CX88_BOARD_HAUPPAUGE_HVR1300,
2601 },{
2602 .subvendor = 0x0070,
2603 .subdevice = 0x9601,
2604 .card = CX88_BOARD_HAUPPAUGE_HVR1300,
2605 },{
2606 .subvendor = 0x0070,
2607 .subdevice = 0x9602,
2608 .card = CX88_BOARD_HAUPPAUGE_HVR1300,
2609 },{
2610 .subvendor = 0x107d,
2611 .subdevice = 0x6632,
2612 .card = CX88_BOARD_LEADTEK_PVR2000,
2613 },{
2614 .subvendor = 0x12ab,
2615 .subdevice = 0x2300, /* Club3D Zap TV2100 */
2616 .card = CX88_BOARD_KWORLD_DVB_T_CX22702,
2617 },{
2618 .subvendor = 0x0070,
2619 .subdevice = 0x9000,
2620 .card = CX88_BOARD_HAUPPAUGE_DVB_T1,
2621 },{
2622 .subvendor = 0x0070,
2623 .subdevice = 0x1400,
2624 .card = CX88_BOARD_HAUPPAUGE_HVR3000,
2625 },{
2626 .subvendor = 0x0070,
2627 .subdevice = 0x1401,
2628 .card = CX88_BOARD_HAUPPAUGE_HVR3000,
2629 },{
2630 .subvendor = 0x0070,
2631 .subdevice = 0x1402,
2632 .card = CX88_BOARD_HAUPPAUGE_HVR3000,
2633 },{
2634 .subvendor = 0x1421,
2635 .subdevice = 0x0341, /* ADS Tech InstantTV DVB-S */
2636 .card = CX88_BOARD_KWORLD_DVBS_100,
2637 },{
2638 .subvendor = 0x1421,
2639 .subdevice = 0x0390,
2640 .card = CX88_BOARD_ADSTECH_PTV_390,
2641 },{
2642 .subvendor = 0x11bd,
2643 .subdevice = 0x0051,
2644 .card = CX88_BOARD_PINNACLE_PCTV_HD_800i,
2645 }, {
2646 .subvendor = 0x18ac,
2647 .subdevice = 0xd530,
2648 .card = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO,
2649 }, {
2650 .subvendor = 0x12ab,
2651 .subdevice = 0x1788,
2652 .card = CX88_BOARD_PINNACLE_HYBRID_PCTV,
2653 }, {
2654 .subvendor = 0x14f1,
2655 .subdevice = 0xea3d,
2656 .card = CX88_BOARD_POWERCOLOR_REAL_ANGEL,
2657 }, {
2658 .subvendor = 0x107d,
2659 .subdevice = 0x6f18,
2660 .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
2661 }, {
2662 .subvendor = 0x14f1,
2663 .subdevice = 0x8852,
2664 .card = CX88_BOARD_GENIATECH_X8000_MT,
2665 }, {
2666 .subvendor = 0x18ac,
2667 .subdevice = 0xd610,
2668 .card = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD,
2669 }, {
2670 .subvendor = 0x1554,
2671 .subdevice = 0x4935,
2672 .card = CX88_BOARD_PROLINK_PV_8000GT,
2673 }, {
2674 .subvendor = 0x1554,
2675 .subdevice = 0x4976,
2676 .card = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME,
2677 }, {
2678 .subvendor = 0x17de,
2679 .subdevice = 0x08c1,
2680 .card = CX88_BOARD_KWORLD_ATSC_120,
2681 }, {
2682 .subvendor = 0x0070,
2683 .subdevice = 0x6900,
2684 .card = CX88_BOARD_HAUPPAUGE_HVR4000,
2685 }, {
2686 .subvendor = 0x0070,
2687 .subdevice = 0x6904,
2688 .card = CX88_BOARD_HAUPPAUGE_HVR4000,
2689 }, {
2690 .subvendor = 0x0070,
2691 .subdevice = 0x6902,
2692 .card = CX88_BOARD_HAUPPAUGE_HVR4000,
2693 }, {
2694 .subvendor = 0x0070,
2695 .subdevice = 0x6905,
2696 .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
2697 }, {
2698 .subvendor = 0x0070,
2699 .subdevice = 0x6906,
2700 .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
2701 }, {
2702 .subvendor = 0xd420,
2703 .subdevice = 0x9022,
2704 .card = CX88_BOARD_TEVII_S420,
2705 }, {
2706 .subvendor = 0xd460,
2707 .subdevice = 0x9022,
2708 .card = CX88_BOARD_TEVII_S460,
2709 }, {
2710 .subvendor = 0xd464,
2711 .subdevice = 0x9022,
2712 .card = CX88_BOARD_TEVII_S464,
2713 }, {
2714 .subvendor = 0xA044,
2715 .subdevice = 0x2011,
2716 .card = CX88_BOARD_OMICOM_SS4_PCI,
2717 }, {
2718 .subvendor = 0x8910,
2719 .subdevice = 0x8888,
2720 .card = CX88_BOARD_TBS_8910,
2721 }, {
2722 .subvendor = 0x8920,
2723 .subdevice = 0x8888,
2724 .card = CX88_BOARD_TBS_8920,
2725 }, {
2726 .subvendor = 0xb022,
2727 .subdevice = 0x3022,
2728 .card = CX88_BOARD_PROF_6200,
2729 }, {
2730 .subvendor = 0xB033,
2731 .subdevice = 0x3033,
2732 .card = CX88_BOARD_PROF_7300,
2733 }, {
2734 .subvendor = 0xb200,
2735 .subdevice = 0x4200,
2736 .card = CX88_BOARD_SATTRADE_ST4200,
2737 }, {
2738 .subvendor = 0x153b,
2739 .subdevice = 0x1177,
2740 .card = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII,
2741 }, {
2742 .subvendor = 0x0070,
2743 .subdevice = 0x9290,
2744 .card = CX88_BOARD_HAUPPAUGE_IRONLY,
2745 }, {
2746 .subvendor = 0x107d,
2747 .subdevice = 0x6654,
2748 .card = CX88_BOARD_WINFAST_DTV1800H,
2749 }, {
2750 /* WinFast DTV1800 H with XC4000 tuner */
2751 .subvendor = 0x107d,
2752 .subdevice = 0x6f38,
2753 .card = CX88_BOARD_WINFAST_DTV1800H_XC4000,
2754 }, {
2755 .subvendor = 0x107d,
2756 .subdevice = 0x6f42,
2757 .card = CX88_BOARD_WINFAST_DTV2000H_PLUS,
2758 }, {
2759 /* PVR2000 PAL Model [107d:6630] */
2760 .subvendor = 0x107d,
2761 .subdevice = 0x6630,
2762 .card = CX88_BOARD_LEADTEK_PVR2000,
2763 }, {
2764 /* PVR2000 PAL Model [107d:6638] */
2765 .subvendor = 0x107d,
2766 .subdevice = 0x6638,
2767 .card = CX88_BOARD_LEADTEK_PVR2000,
2768 }, {
2769 /* PVR2000 NTSC Model [107d:6631] */
2770 .subvendor = 0x107d,
2771 .subdevice = 0x6631,
2772 .card = CX88_BOARD_LEADTEK_PVR2000,
2773 }, {
2774 /* PVR2000 NTSC Model [107d:6637] */
2775 .subvendor = 0x107d,
2776 .subdevice = 0x6637,
2777 .card = CX88_BOARD_LEADTEK_PVR2000,
2778 }, {
2779 /* PVR2000 NTSC Model [107d:663d] */
2780 .subvendor = 0x107d,
2781 .subdevice = 0x663d,
2782 .card = CX88_BOARD_LEADTEK_PVR2000,
2783 }, {
2784 /* DV2000 NTSC Model [107d:6621] */
2785 .subvendor = 0x107d,
2786 .subdevice = 0x6621,
2787 .card = CX88_BOARD_WINFAST_DV2000,
2788 }, {
2789 /* TV2000 XP Global [107d:6618] */
2790 .subvendor = 0x107d,
2791 .subdevice = 0x6618,
2792 .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
2793 }, {
2794 /* TV2000 XP Global [107d:6618] */
2795 .subvendor = 0x107d,
2796 .subdevice = 0x6619,
2797 .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
2798 }, {
2799 /* WinFast TV2000 XP Global with XC4000 tuner */
2800 .subvendor = 0x107d,
2801 .subdevice = 0x6f36,
2802 .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36,
2803 }, {
2804 /* WinFast TV2000 XP Global with XC4000 tuner and different GPIOs */
2805 .subvendor = 0x107d,
2806 .subdevice = 0x6f43,
2807 .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43,
2808 }, {
2809 .subvendor = 0xb034,
2810 .subdevice = 0x3034,
2811 .card = CX88_BOARD_PROF_7301,
2812 }, {
2813 .subvendor = 0x1822,
2814 .subdevice = 0x0023,
2815 .card = CX88_BOARD_TWINHAN_VP1027_DVBS,
2816 },
2817};
2818
2819/* ----------------------------------------------------------------------- */
2820/* some leadtek specific stuff */
2821
2822static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
2823{
2824 if (eeprom_data[4] != 0x7d ||
2825 eeprom_data[5] != 0x10 ||
2826 eeprom_data[7] != 0x66) {
2827 warn_printk(core, "Leadtek eeprom invalid.\n");
2828 return;
2829 }
2830
2831 /* Terry Wu <terrywu2009@gmail.com> */
2832 switch (eeprom_data[6]) {
2833 case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */
2834 case 0x21: /* SSID 6621 for DV2000 NTSC Model */
2835 case 0x31: /* SSID 6631 for PVR2000 NTSC Model */
2836 case 0x37: /* SSID 6637 for PVR2000 NTSC Model */
2837 case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */
2838 core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3;
2839 break;
2840 default:
2841 core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
2842 break;
2843 }
2844
2845 info_printk(core, "Leadtek Winfast 2000XP Expert config: "
2846 "tuner=%d, eeprom[0]=0x%02x\n",
2847 core->board.tuner_type, eeprom_data[0]);
2848}
2849
2850static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
2851{
2852 struct tveeprom tv;
2853
2854 tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
2855 core->board.tuner_type = tv.tuner_type;
2856 core->tuner_formats = tv.tuner_formats;
2857 core->board.radio.type = tv.has_radio ? CX88_RADIO : 0;
2858
2859 /* Make sure we support the board model */
2860 switch (tv.model)
2861 {
2862 case 14009: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in) */
2863 case 14019: /* WinTV-HVR3000 (Retail, IR Blaster, b/panel video, 3.5mm audio in) */
2864 case 14029: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge) */
2865 case 14109: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - low profile) */
2866 case 14129: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge - LP) */
2867 case 14559: /* WinTV-HVR3000 (OEM, no IR, b/panel video, 3.5mm audio in) */
2868 case 14569: /* WinTV-HVR3000 (OEM, no IR, no back panel video) */
2869 case 14659: /* WinTV-HVR3000 (OEM, no IR, b/panel video, RCA audio in - Low profile) */
2870 case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */
2871 case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
2872 case 34519: /* WinTV-PCI-FM */
2873 case 69009:
2874 /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */
2875 case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */
2876 case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */
2877 case 69559:
2878 /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */
2879 case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */
2880 case 90002: /* Nova-T-PCI (9002) */
2881 case 92001: /* Nova-S-Plus (Video and IR) */
2882 case 92002: /* Nova-S-Plus (Video and IR) */
2883 case 90003: /* Nova-T-PCI (9002 No RF out) */
2884 case 90500: /* Nova-T-PCI (oem) */
2885 case 90501: /* Nova-T-PCI (oem/IR) */
2886 case 92000: /* Nova-SE2 (OEM, No Video or IR) */
2887 case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */
2888 case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
2889 case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
2890 case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */
2891 case 96019: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX/TX) */
2892 case 96559: /* WinTV-HVR1300 (PAL Video, MPEG Video no IR) */
2893 case 96569: /* WinTV-HVR1300 () */
2894 case 96659: /* WinTV-HVR1300 () */
2895 case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */
2896 /* known */
2897 break;
2898 case CX88_BOARD_SAMSUNG_SMT_7020:
2899 cx_set(MO_GP0_IO, 0x008989FF);
2900 break;
2901 default:
2902 warn_printk(core, "warning: unknown hauppauge model #%d\n",
2903 tv.model);
2904 break;
2905 }
2906
2907 info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
2908}
2909
2910/* ----------------------------------------------------------------------- */
2911/* some GDI (was: Modular Technology) specific stuff */
2912
2913static const struct {
2914 int id;
2915 int fm;
2916 const char *name;
2917} gdi_tuner[] = {
2918 [ 0x01 ] = { .id = TUNER_ABSENT,
2919 .name = "NTSC_M" },
2920 [ 0x02 ] = { .id = TUNER_ABSENT,
2921 .name = "PAL_B" },
2922 [ 0x03 ] = { .id = TUNER_ABSENT,
2923 .name = "PAL_I" },
2924 [ 0x04 ] = { .id = TUNER_ABSENT,
2925 .name = "PAL_D" },
2926 [ 0x05 ] = { .id = TUNER_ABSENT,
2927 .name = "SECAM" },
2928
2929 [ 0x10 ] = { .id = TUNER_ABSENT,
2930 .fm = 1,
2931 .name = "TEMIC_4049" },
2932 [ 0x11 ] = { .id = TUNER_TEMIC_4136FY5,
2933 .name = "TEMIC_4136" },
2934 [ 0x12 ] = { .id = TUNER_ABSENT,
2935 .name = "TEMIC_4146" },
2936
2937 [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME,
2938 .fm = 1,
2939 .name = "PHILIPS_FQ1216_MK3" },
2940 [ 0x21 ] = { .id = TUNER_ABSENT, .fm = 1,
2941 .name = "PHILIPS_FQ1236_MK3" },
2942 [ 0x22 ] = { .id = TUNER_ABSENT,
2943 .name = "PHILIPS_FI1236_MK3" },
2944 [ 0x23 ] = { .id = TUNER_ABSENT,
2945 .name = "PHILIPS_FI1216_MK3" },
2946};
2947
2948static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
2949{
2950 const char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
2951 ? gdi_tuner[eeprom_data[0x0d]].name : NULL;
2952
2953 info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
2954 if (NULL == name)
2955 return;
2956 core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
2957 core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ?
2958 CX88_RADIO : 0;
2959}
2960
2961/* ------------------------------------------------------------------- */
2962/* some Divco specific stuff */
2963static int cx88_dvico_xc2028_callback(struct cx88_core *core,
2964 int command, int arg)
2965{
2966 switch (command) {
2967 case XC2028_TUNER_RESET:
2968 switch (core->boardnr) {
2969 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
2970 /* GPIO-4 xc3028 tuner */
2971
2972 cx_set(MO_GP0_IO, 0x00001000);
2973 cx_clear(MO_GP0_IO, 0x00000010);
2974 msleep(100);
2975 cx_set(MO_GP0_IO, 0x00000010);
2976 msleep(100);
2977 break;
2978 default:
2979 cx_write(MO_GP0_IO, 0x101000);
2980 mdelay(5);
2981 cx_set(MO_GP0_IO, 0x101010);
2982 }
2983 break;
2984 default:
2985 return -EINVAL;
2986 }
2987
2988 return 0;
2989}
2990
2991
2992/* ----------------------------------------------------------------------- */
2993/* some Geniatech specific stuff */
2994
2995static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core,
2996 int command, int mode)
2997{
2998 switch (command) {
2999 case XC2028_TUNER_RESET:
3000 switch (INPUT(core->input).type) {
3001 case CX88_RADIO:
3002 break;
3003 case CX88_VMUX_DVB:
3004 cx_write(MO_GP1_IO, 0x030302);
3005 mdelay(50);
3006 break;
3007 default:
3008 cx_write(MO_GP1_IO, 0x030301);
3009 mdelay(50);
3010 }
3011 cx_write(MO_GP1_IO, 0x101010);
3012 mdelay(50);
3013 cx_write(MO_GP1_IO, 0x101000);
3014 mdelay(50);
3015 cx_write(MO_GP1_IO, 0x101010);
3016 mdelay(50);
3017 return 0;
3018 }
3019 return -EINVAL;
3020}
3021
3022static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
3023 int command, int arg)
3024{
3025 switch (command) {
3026 case XC2028_TUNER_RESET:
3027 /* GPIO 12 (xc3028 tuner reset) */
3028 cx_set(MO_GP1_IO, 0x1010);
3029 mdelay(50);
3030 cx_clear(MO_GP1_IO, 0x10);
3031 mdelay(75);
3032 cx_set(MO_GP1_IO, 0x10);
3033 mdelay(75);
3034 return 0;
3035 }
3036 return -EINVAL;
3037}
3038
3039static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core,
3040 int command, int arg)
3041{
3042 switch (command) {
3043 case XC4000_TUNER_RESET:
3044 /* GPIO 12 (xc4000 tuner reset) */
3045 cx_set(MO_GP1_IO, 0x1010);
3046 mdelay(50);
3047 cx_clear(MO_GP1_IO, 0x10);
3048 mdelay(75);
3049 cx_set(MO_GP1_IO, 0x10);
3050 mdelay(75);
3051 return 0;
3052 }
3053 return -EINVAL;
3054}
3055
3056/* ------------------------------------------------------------------- */
3057/* some Divco specific stuff */
3058static int cx88_pv_8000gt_callback(struct cx88_core *core,
3059 int command, int arg)
3060{
3061 switch (command) {
3062 case XC2028_TUNER_RESET:
3063 cx_write(MO_GP2_IO, 0xcf7);
3064 mdelay(50);
3065 cx_write(MO_GP2_IO, 0xef5);
3066 mdelay(50);
3067 cx_write(MO_GP2_IO, 0xcf7);
3068 break;
3069 default:
3070 return -EINVAL;
3071 }
3072
3073 return 0;
3074}
3075
3076/* ----------------------------------------------------------------------- */
3077/* some DViCO specific stuff */
3078
3079static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
3080{
3081 struct i2c_msg msg = { .addr = 0x45, .flags = 0 };
3082 int i, err;
3083 static u8 init_bufs[13][5] = {
3084 { 0x10, 0x00, 0x20, 0x01, 0x03 },
3085 { 0x10, 0x10, 0x01, 0x00, 0x21 },
3086 { 0x10, 0x10, 0x10, 0x00, 0xCA },
3087 { 0x10, 0x10, 0x12, 0x00, 0x08 },
3088 { 0x10, 0x10, 0x13, 0x00, 0x0A },
3089 { 0x10, 0x10, 0x16, 0x01, 0xC0 },
3090 { 0x10, 0x10, 0x22, 0x01, 0x3D },
3091 { 0x10, 0x10, 0x73, 0x01, 0x2E },
3092 { 0x10, 0x10, 0x72, 0x00, 0xC5 },
3093 { 0x10, 0x10, 0x71, 0x01, 0x97 },
3094 { 0x10, 0x10, 0x70, 0x00, 0x0F },
3095 { 0x10, 0x10, 0xB0, 0x00, 0x01 },
3096 { 0x03, 0x0C },
3097 };
3098
3099 for (i = 0; i < ARRAY_SIZE(init_bufs); i++) {
3100 msg.buf = init_bufs[i];
3101 msg.len = (i != 12 ? 5 : 2);
3102 err = i2c_transfer(&core->i2c_adap, &msg, 1);
3103 if (err != 1) {
3104 warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d "
3105 "failed (err = %d)!\n", i, err);
3106 return;
3107 }
3108 }
3109}
3110
3111static int cx88_xc2028_tuner_callback(struct cx88_core *core,
3112 int command, int arg)
3113{
3114 /* Board-specific callbacks */
3115 switch (core->boardnr) {
3116 case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
3117 case CX88_BOARD_GENIATECH_X8000_MT:
3118 case CX88_BOARD_KWORLD_ATSC_120:
3119 return cx88_xc3028_geniatech_tuner_callback(core,
3120 command, arg);
3121 case CX88_BOARD_PROLINK_PV_8000GT:
3122 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
3123 return cx88_pv_8000gt_callback(core, command, arg);
3124 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
3125 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
3126 return cx88_dvico_xc2028_callback(core, command, arg);
3127 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
3128 case CX88_BOARD_WINFAST_DTV1800H:
3129 return cx88_xc3028_winfast1800h_callback(core, command, arg);
3130 }
3131
3132 switch (command) {
3133 case XC2028_TUNER_RESET:
3134 switch (INPUT(core->input).type) {
3135 case CX88_RADIO:
3136 info_printk(core, "setting GPIO to radio!\n");
3137 cx_write(MO_GP0_IO, 0x4ff);
3138 mdelay(250);
3139 cx_write(MO_GP2_IO, 0xff);
3140 mdelay(250);
3141 break;
3142 case CX88_VMUX_DVB: /* Digital TV*/
3143 default: /* Analog TV */
3144 info_printk(core, "setting GPIO to TV!\n");
3145 break;
3146 }
3147 cx_write(MO_GP1_IO, 0x101010);
3148 mdelay(250);
3149 cx_write(MO_GP1_IO, 0x101000);
3150 mdelay(250);
3151 cx_write(MO_GP1_IO, 0x101010);
3152 mdelay(250);
3153 return 0;
3154 }
3155 return -EINVAL;
3156}
3157
3158static int cx88_xc4000_tuner_callback(struct cx88_core *core,
3159 int command, int arg)
3160{
3161 /* Board-specific callbacks */
3162 switch (core->boardnr) {
3163 case CX88_BOARD_WINFAST_DTV1800H_XC4000:
3164 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
3165 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
3166 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
3167 return cx88_xc4000_winfast2000h_plus_callback(core,
3168 command, arg);
3169 }
3170 return -EINVAL;
3171}
3172
3173/* ----------------------------------------------------------------------- */
3174/* Tuner callback function. Currently only needed for the Pinnacle *
3175 * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both *
3176 * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c) */
3177
3178static int cx88_xc5000_tuner_callback(struct cx88_core *core,
3179 int command, int arg)
3180{
3181 switch (core->boardnr) {
3182 case CX88_BOARD_PINNACLE_PCTV_HD_800i:
3183 if (command == 0) { /* This is the reset command from xc5000 */
3184
3185 /* djh - According to the engineer at PCTV Systems,
3186 the xc5000 reset pin is supposed to be on GPIO12.
3187 However, despite three nights of effort, pulling
3188 that GPIO low didn't reset the xc5000. While
3189 pulling MO_SRST_IO low does reset the xc5000, this
3190 also resets in the s5h1409 being reset as well.
3191 This causes tuning to always fail since the internal
3192 state of the s5h1409 does not match the driver's
3193 state. Given that the only two conditions in which
3194 the driver performs a reset is during firmware load
3195 and powering down the chip, I am taking out the
3196 reset. We know that the chip is being reset
3197 when the cx88 comes online, and not being able to
3198 do power management for this board is worse than
3199 not having any tuning at all. */
3200 return 0;
3201 } else {
3202 err_printk(core, "xc5000: unknown tuner "
3203 "callback command.\n");
3204 return -EINVAL;
3205 }
3206 break;
3207 case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
3208 if (command == 0) { /* This is the reset command from xc5000 */
3209 cx_clear(MO_GP0_IO, 0x00000010);
3210 msleep(10);
3211 cx_set(MO_GP0_IO, 0x00000010);
3212 return 0;
3213 } else {
3214 printk(KERN_ERR
3215 "xc5000: unknown tuner callback command.\n");
3216 return -EINVAL;
3217 }
3218 break;
3219 }
3220 return 0; /* Should never be here */
3221}
3222
3223int cx88_tuner_callback(void *priv, int component, int command, int arg)
3224{
3225 struct i2c_algo_bit_data *i2c_algo = priv;
3226 struct cx88_core *core;
3227
3228 if (!i2c_algo) {
3229 printk(KERN_ERR "cx88: Error - i2c private data undefined.\n");
3230 return -EINVAL;
3231 }
3232
3233 core = i2c_algo->data;
3234
3235 if (!core) {
3236 printk(KERN_ERR "cx88: Error - device struct undefined.\n");
3237 return -EINVAL;
3238 }
3239
3240 if (component != DVB_FRONTEND_COMPONENT_TUNER)
3241 return -EINVAL;
3242
3243 switch (core->board.tuner_type) {
3244 case TUNER_XC2028:
3245 info_printk(core, "Calling XC2028/3028 callback\n");
3246 return cx88_xc2028_tuner_callback(core, command, arg);
3247 case TUNER_XC4000:
3248 info_printk(core, "Calling XC4000 callback\n");
3249 return cx88_xc4000_tuner_callback(core, command, arg);
3250 case TUNER_XC5000:
3251 info_printk(core, "Calling XC5000 callback\n");
3252 return cx88_xc5000_tuner_callback(core, command, arg);
3253 }
3254 err_printk(core, "Error: Calling callback for tuner %d\n",
3255 core->board.tuner_type);
3256 return -EINVAL;
3257}
3258EXPORT_SYMBOL(cx88_tuner_callback);
3259
3260/* ----------------------------------------------------------------------- */
3261
3262static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
3263{
3264 int i;
3265
3266 if (0 == pci->subsystem_vendor &&
3267 0 == pci->subsystem_device) {
3268 printk(KERN_ERR
3269 "%s: Your board has no valid PCI Subsystem ID and thus can't\n"
3270 "%s: be autodetected. Please pass card=<n> insmod option to\n"
3271 "%s: workaround that. Redirect complaints to the vendor of\n"
3272 "%s: the TV card. Best regards,\n"
3273 "%s: -- tux\n",
3274 core->name,core->name,core->name,core->name,core->name);
3275 } else {
3276 printk(KERN_ERR
3277 "%s: Your board isn't known (yet) to the driver. You can\n"
3278 "%s: try to pick one of the existing card configs via\n"
3279 "%s: card=<n> insmod option. Updating to the latest\n"
3280 "%s: version might help as well.\n",
3281 core->name,core->name,core->name,core->name);
3282 }
3283 err_printk(core, "Here is a list of valid choices for the card=<n> "
3284 "insmod option:\n");
3285 for (i = 0; i < ARRAY_SIZE(cx88_boards); i++)
3286 printk(KERN_ERR "%s: card=%d -> %s\n",
3287 core->name, i, cx88_boards[i].name);
3288}
3289
3290static void cx88_card_setup_pre_i2c(struct cx88_core *core)
3291{
3292 switch (core->boardnr) {
3293 case CX88_BOARD_HAUPPAUGE_HVR1300:
3294 /*
3295 * Bring the 702 demod up before i2c scanning/attach or devices are hidden
3296 * We leave here with the 702 on the bus
3297 *
3298 * "reset the IR receiver on GPIO[3]"
3299 * Reported by Mike Crash <mike AT mikecrash.com>
3300 */
3301 cx_write(MO_GP0_IO, 0x0000ef88);
3302 udelay(1000);
3303 cx_clear(MO_GP0_IO, 0x00000088);
3304 udelay(50);
3305 cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */
3306 udelay(1000);
3307 break;
3308
3309 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
3310 case CX88_BOARD_PROLINK_PV_8000GT:
3311 cx_write(MO_GP2_IO, 0xcf7);
3312 mdelay(50);
3313 cx_write(MO_GP2_IO, 0xef5);
3314 mdelay(50);
3315 cx_write(MO_GP2_IO, 0xcf7);
3316 msleep(10);
3317 break;
3318
3319 case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
3320 /* Enable the xc5000 tuner */
3321 cx_set(MO_GP0_IO, 0x00001010);
3322 break;
3323
3324 case CX88_BOARD_WINFAST_DTV2000H_J:
3325 case CX88_BOARD_HAUPPAUGE_HVR3000:
3326 case CX88_BOARD_HAUPPAUGE_HVR4000:
3327 /* Init GPIO */
3328 cx_write(MO_GP0_IO, core->board.input[0].gpio0);
3329 udelay(1000);
3330 cx_clear(MO_GP0_IO, 0x00000080);
3331 udelay(50);
3332 cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
3333 udelay(1000);
3334 break;
3335
3336 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
3337 case CX88_BOARD_WINFAST_DTV1800H:
3338 cx88_xc3028_winfast1800h_callback(core, XC2028_TUNER_RESET, 0);
3339 break;
3340
3341 case CX88_BOARD_WINFAST_DTV1800H_XC4000:
3342 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
3343 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
3344 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
3345 cx88_xc4000_winfast2000h_plus_callback(core,
3346 XC4000_TUNER_RESET, 0);
3347 break;
3348
3349 case CX88_BOARD_TWINHAN_VP1027_DVBS:
3350 cx_write(MO_GP0_IO, 0x00003230);
3351 cx_write(MO_GP0_IO, 0x00003210);
3352 msleep(1);
3353 cx_write(MO_GP0_IO, 0x00001230);
3354 break;
3355 }
3356}
3357
3358/*
3359 * Sets board-dependent xc3028 configuration
3360 */
3361void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
3362{
3363 memset(ctl, 0, sizeof(*ctl));
3364
3365 ctl->fname = XC2028_DEFAULT_FIRMWARE;
3366 ctl->max_len = 64;
3367
3368 switch (core->boardnr) {
3369 case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
3370 /* Now works with firmware version 2.7 */
3371 if (core->i2c_algo.udelay < 16)
3372 core->i2c_algo.udelay = 16;
3373 break;
3374 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
3375 case CX88_BOARD_WINFAST_DTV1800H:
3376 ctl->demod = XC3028_FE_ZARLINK456;
3377 break;
3378 case CX88_BOARD_KWORLD_ATSC_120:
3379 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
3380 ctl->demod = XC3028_FE_OREN538;
3381 break;
3382 case CX88_BOARD_GENIATECH_X8000_MT:
3383 /* FIXME: For this board, the xc3028 never recovers after being
3384 powered down (the reset GPIO probably is not set properly).
3385 We don't have access to the hardware so we cannot determine
3386 which GPIO is used for xc3028, so just disable power xc3028
3387 power management for now */
3388 ctl->disable_power_mgmt = 1;
3389 break;
3390 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
3391 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
3392 case CX88_BOARD_PROLINK_PV_8000GT:
3393 /*
3394 * Those boards uses non-MTS firmware
3395 */
3396 break;
3397 case CX88_BOARD_PINNACLE_HYBRID_PCTV:
3398 case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
3399 ctl->demod = XC3028_FE_ZARLINK456;
3400 ctl->mts = 1;
3401 break;
3402 default:
3403 ctl->demod = XC3028_FE_OREN538;
3404 ctl->mts = 1;
3405 }
3406}
3407EXPORT_SYMBOL_GPL(cx88_setup_xc3028);
3408
3409static void cx88_card_setup(struct cx88_core *core)
3410{
3411 static u8 eeprom[256];
3412 struct tuner_setup tun_setup;
3413 unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
3414
3415 memset(&tun_setup, 0, sizeof(tun_setup));
3416
3417 if (0 == core->i2c_rc) {
3418 core->i2c_client.addr = 0xa0 >> 1;
3419 tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom));
3420 }
3421
3422 switch (core->boardnr) {
3423 case CX88_BOARD_HAUPPAUGE:
3424 case CX88_BOARD_HAUPPAUGE_ROSLYN:
3425 if (0 == core->i2c_rc)
3426 hauppauge_eeprom(core, eeprom+8);
3427 break;
3428 case CX88_BOARD_GDI:
3429 if (0 == core->i2c_rc)
3430 gdi_eeprom(core, eeprom);
3431 break;
3432 case CX88_BOARD_LEADTEK_PVR2000:
3433 case CX88_BOARD_WINFAST_DV2000:
3434 case CX88_BOARD_WINFAST2000XP_EXPERT:
3435 if (0 == core->i2c_rc)
3436 leadtek_eeprom(core, eeprom);
3437 break;
3438 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
3439 case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
3440 case CX88_BOARD_HAUPPAUGE_DVB_T1:
3441 case CX88_BOARD_HAUPPAUGE_HVR1100:
3442 case CX88_BOARD_HAUPPAUGE_HVR1100LP:
3443 case CX88_BOARD_HAUPPAUGE_HVR3000:
3444 case CX88_BOARD_HAUPPAUGE_HVR1300:
3445 case CX88_BOARD_HAUPPAUGE_HVR4000:
3446 case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
3447 case CX88_BOARD_HAUPPAUGE_IRONLY:
3448 if (0 == core->i2c_rc)
3449 hauppauge_eeprom(core, eeprom);
3450 break;
3451 case CX88_BOARD_KWORLD_DVBS_100:
3452 cx_write(MO_GP0_IO, 0x000007f8);
3453 cx_write(MO_GP1_IO, 0x00000001);
3454 break;
3455 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
3456 /* GPIO0:0 is hooked to demod reset */
3457 /* GPIO0:4 is hooked to xc3028 reset */
3458 cx_write(MO_GP0_IO, 0x00111100);
3459 msleep(1);
3460 cx_write(MO_GP0_IO, 0x00111111);
3461 break;
3462 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
3463 /* GPIO0:6 is hooked to FX2 reset pin */
3464 cx_set(MO_GP0_IO, 0x00004040);
3465 cx_clear(MO_GP0_IO, 0x00000040);
3466 msleep(1000);
3467 cx_set(MO_GP0_IO, 0x00004040);
3468 /* FALLTHROUGH */
3469 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
3470 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
3471 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
3472 /* GPIO0:0 is hooked to mt352 reset pin */
3473 cx_set(MO_GP0_IO, 0x00000101);
3474 cx_clear(MO_GP0_IO, 0x00000001);
3475 msleep(1);
3476 cx_set(MO_GP0_IO, 0x00000101);
3477 if (0 == core->i2c_rc &&
3478 core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
3479 dvico_fusionhdtv_hybrid_init(core);
3480 break;
3481 case CX88_BOARD_KWORLD_DVB_T:
3482 case CX88_BOARD_DNTV_LIVE_DVB_T:
3483 cx_set(MO_GP0_IO, 0x00000707);
3484 cx_set(MO_GP2_IO, 0x00000101);
3485 cx_clear(MO_GP2_IO, 0x00000001);
3486 msleep(1);
3487 cx_clear(MO_GP0_IO, 0x00000007);
3488 cx_set(MO_GP2_IO, 0x00000101);
3489 break;
3490 case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
3491 cx_write(MO_GP0_IO, 0x00080808);
3492 break;
3493 case CX88_BOARD_ATI_HDTVWONDER:
3494 if (0 == core->i2c_rc) {
3495 /* enable tuner */
3496 int i;
3497 static const u8 buffer [][2] = {
3498 {0x10,0x12},
3499 {0x13,0x04},
3500 {0x16,0x00},
3501 {0x14,0x04},
3502 {0x17,0x00}
3503 };
3504 core->i2c_client.addr = 0x0a;
3505
3506 for (i = 0; i < ARRAY_SIZE(buffer); i++)
3507 if (2 != i2c_master_send(&core->i2c_client,
3508 buffer[i],2))
3509 warn_printk(core, "Unable to enable "
3510 "tuner(%i).\n", i);
3511 }
3512 break;
3513 case CX88_BOARD_MSI_TVANYWHERE_MASTER:
3514 {
3515 struct v4l2_priv_tun_config tea5767_cfg;
3516 struct tea5767_ctrl ctl;
3517
3518 memset(&ctl, 0, sizeof(ctl));
3519
3520 ctl.high_cut = 1;
3521 ctl.st_noise = 1;
3522 ctl.deemph_75 = 1;
3523 ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
3524
3525 tea5767_cfg.tuner = TUNER_TEA5767;
3526 tea5767_cfg.priv = &ctl;
3527
3528 call_all(core, tuner, s_config, &tea5767_cfg);
3529 break;
3530 }
3531 case CX88_BOARD_TEVII_S420:
3532 case CX88_BOARD_TEVII_S460:
3533 case CX88_BOARD_TEVII_S464:
3534 case CX88_BOARD_OMICOM_SS4_PCI:
3535 case CX88_BOARD_TBS_8910:
3536 case CX88_BOARD_TBS_8920:
3537 case CX88_BOARD_PROF_6200:
3538 case CX88_BOARD_PROF_7300:
3539 case CX88_BOARD_PROF_7301:
3540 case CX88_BOARD_SATTRADE_ST4200:
3541 cx_write(MO_GP0_IO, 0x8000);
3542 msleep(100);
3543 cx_write(MO_SRST_IO, 0);
3544 msleep(10);
3545 cx_write(MO_GP0_IO, 0x8080);
3546 msleep(100);
3547 cx_write(MO_SRST_IO, 1);
3548 msleep(100);
3549 break;
3550 } /*end switch() */
3551
3552
3553 /* Setup tuners */
3554 if ((core->board.radio_type != UNSET)) {
3555 tun_setup.mode_mask = T_RADIO;
3556 tun_setup.type = core->board.radio_type;
3557 tun_setup.addr = core->board.radio_addr;
3558 tun_setup.tuner_callback = cx88_tuner_callback;
3559 call_all(core, tuner, s_type_addr, &tun_setup);
3560 mode_mask &= ~T_RADIO;
3561 }
3562
3563 if (core->board.tuner_type != TUNER_ABSENT) {
3564 tun_setup.mode_mask = mode_mask;
3565 tun_setup.type = core->board.tuner_type;
3566 tun_setup.addr = core->board.tuner_addr;
3567 tun_setup.tuner_callback = cx88_tuner_callback;
3568
3569 call_all(core, tuner, s_type_addr, &tun_setup);
3570 }
3571
3572 if (core->board.tda9887_conf) {
3573 struct v4l2_priv_tun_config tda9887_cfg;
3574
3575 tda9887_cfg.tuner = TUNER_TDA9887;
3576 tda9887_cfg.priv = &core->board.tda9887_conf;
3577
3578 call_all(core, tuner, s_config, &tda9887_cfg);
3579 }
3580
3581 if (core->board.tuner_type == TUNER_XC2028) {
3582 struct v4l2_priv_tun_config xc2028_cfg;
3583 struct xc2028_ctrl ctl;
3584
3585 /* Fills device-dependent initialization parameters */
3586 cx88_setup_xc3028(core, &ctl);
3587
3588 /* Sends parameters to xc2028/3028 tuner */
3589 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
3590 xc2028_cfg.tuner = TUNER_XC2028;
3591 xc2028_cfg.priv = &ctl;
3592 info_printk(core, "Asking xc2028/3028 to load firmware %s\n",
3593 ctl.fname);
3594 call_all(core, tuner, s_config, &xc2028_cfg);
3595 }
3596 call_all(core, core, s_power, 0);
3597}
3598
3599/* ------------------------------------------------------------------ */
3600
3601static int cx88_pci_quirks(const char *name, struct pci_dev *pci)
3602{
3603 unsigned int lat = UNSET;
3604 u8 ctrl = 0;
3605 u8 value;
3606
3607 /* check pci quirks */
3608 if (pci_pci_problems & PCIPCI_TRITON) {
3609 printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
3610 name);
3611 ctrl |= CX88X_EN_TBFX;
3612 }
3613 if (pci_pci_problems & PCIPCI_NATOMA) {
3614 printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
3615 name);
3616 ctrl |= CX88X_EN_TBFX;
3617 }
3618 if (pci_pci_problems & PCIPCI_VIAETBF) {
3619 printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
3620 name);
3621 ctrl |= CX88X_EN_TBFX;
3622 }
3623 if (pci_pci_problems & PCIPCI_VSFX) {
3624 printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
3625 name);
3626 ctrl |= CX88X_EN_VSFX;
3627 }
3628#ifdef PCIPCI_ALIMAGIK
3629 if (pci_pci_problems & PCIPCI_ALIMAGIK) {
3630 printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
3631 name);
3632 lat = 0x0A;
3633 }
3634#endif
3635
3636 /* check insmod options */
3637 if (UNSET != latency)
3638 lat = latency;
3639
3640 /* apply stuff */
3641 if (ctrl) {
3642 pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
3643 value |= ctrl;
3644 pci_write_config_byte(pci, CX88X_DEVCTRL, value);
3645 }
3646 if (UNSET != lat) {
3647 printk(KERN_INFO "%s: setting pci latency timer to %d\n",
3648 name, latency);
3649 pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
3650 }
3651 return 0;
3652}
3653
3654int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci)
3655{
3656 if (request_mem_region(pci_resource_start(pci,0),
3657 pci_resource_len(pci,0),
3658 core->name))
3659 return 0;
3660 printk(KERN_ERR
3661 "%s/%d: Can't get MMIO memory @ 0x%llx, subsystem: %04x:%04x\n",
3662 core->name, PCI_FUNC(pci->devfn),
3663 (unsigned long long)pci_resource_start(pci, 0),
3664 pci->subsystem_vendor, pci->subsystem_device);
3665 return -EBUSY;
3666}
3667
3668/* Allocate and initialize the cx88 core struct. One should hold the
3669 * devlist mutex before calling this. */
3670struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
3671{
3672 struct cx88_core *core;
3673 int i;
3674
3675 core = kzalloc(sizeof(*core), GFP_KERNEL);
3676 if (core == NULL)
3677 return NULL;
3678
3679 atomic_inc(&core->refcount);
3680 core->pci_bus = pci->bus->number;
3681 core->pci_slot = PCI_SLOT(pci->devfn);
3682 core->pci_irqmask = PCI_INT_RISC_RD_BERRINT | PCI_INT_RISC_WR_BERRINT |
3683 PCI_INT_BRDG_BERRINT | PCI_INT_SRC_DMA_BERRINT |
3684 PCI_INT_DST_DMA_BERRINT | PCI_INT_IPB_DMA_BERRINT;
3685 mutex_init(&core->lock);
3686
3687 core->nr = nr;
3688 sprintf(core->name, "cx88[%d]", core->nr);
3689
3690 strcpy(core->v4l2_dev.name, core->name);
3691 if (v4l2_device_register(NULL, &core->v4l2_dev)) {
3692 kfree(core);
3693 return NULL;
3694 }
3695
3696 if (v4l2_ctrl_handler_init(&core->video_hdl, 13)) {
3697 v4l2_device_unregister(&core->v4l2_dev);
3698 kfree(core);
3699 return NULL;
3700 }
3701
3702 if (v4l2_ctrl_handler_init(&core->audio_hdl, 13)) {
3703 v4l2_ctrl_handler_free(&core->video_hdl);
3704 v4l2_device_unregister(&core->v4l2_dev);
3705 kfree(core);
3706 return NULL;
3707 }
3708
3709 if (0 != cx88_get_resources(core, pci)) {
3710 v4l2_ctrl_handler_free(&core->video_hdl);
3711 v4l2_ctrl_handler_free(&core->audio_hdl);
3712 v4l2_device_unregister(&core->v4l2_dev);
3713 kfree(core);
3714 return NULL;
3715 }
3716
3717 /* PCI stuff */
3718 cx88_pci_quirks(core->name, pci);
3719 core->lmmio = ioremap(pci_resource_start(pci, 0),
3720 pci_resource_len(pci, 0));
3721 core->bmmio = (u8 __iomem *)core->lmmio;
3722
3723 if (core->lmmio == NULL) {
3724 release_mem_region(pci_resource_start(pci, 0),
3725 pci_resource_len(pci, 0));
3726 v4l2_ctrl_handler_free(&core->video_hdl);
3727 v4l2_ctrl_handler_free(&core->audio_hdl);
3728 v4l2_device_unregister(&core->v4l2_dev);
3729 kfree(core);
3730 return NULL;
3731 }
3732
3733 /* board config */
3734 core->boardnr = UNSET;
3735 if (card[core->nr] < ARRAY_SIZE(cx88_boards))
3736 core->boardnr = card[core->nr];
3737 for (i = 0; UNSET == core->boardnr && i < ARRAY_SIZE(cx88_subids); i++)
3738 if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
3739 pci->subsystem_device == cx88_subids[i].subdevice)
3740 core->boardnr = cx88_subids[i].card;
3741 if (UNSET == core->boardnr) {
3742 core->boardnr = CX88_BOARD_UNKNOWN;
3743 cx88_card_list(core, pci);
3744 }
3745
3746 memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
3747
3748 if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB))
3749 core->board.num_frontends = 1;
3750
3751 info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
3752 pci->subsystem_vendor, pci->subsystem_device, core->board.name,
3753 core->boardnr, card[core->nr] == core->boardnr ?
3754 "insmod option" : "autodetected",
3755 core->board.num_frontends);
3756
3757 if (tuner[core->nr] != UNSET)
3758 core->board.tuner_type = tuner[core->nr];
3759 if (radio[core->nr] != UNSET)
3760 core->board.radio_type = radio[core->nr];
3761
3762 info_printk(core, "TV tuner type %d, Radio tuner type %d\n",
3763 core->board.tuner_type, core->board.radio_type);
3764
3765 /* init hardware */
3766 cx88_reset(core);
3767 cx88_card_setup_pre_i2c(core);
3768 cx88_i2c_init(core, pci);
3769
3770 /* load tuner module, if needed */
3771 if (TUNER_ABSENT != core->board.tuner_type) {
3772 /* Ignore 0x6b and 0x6f on cx88 boards.
3773 * FusionHDTV5 RT Gold has an ir receiver at 0x6b
3774 * and an RTC at 0x6f which can get corrupted if probed. */
3775 static const unsigned short tv_addrs[] = {
3776 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
3777 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
3778 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e,
3779 I2C_CLIENT_END
3780 };
3781 int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT);
3782
3783 /* I don't trust the radio_type as is stored in the card
3784 definitions, so we just probe for it.
3785 The radio_type is sometimes missing, or set to UNSET but
3786 later code configures a tea5767.
3787 */
3788 v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
3789 "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
3790 if (has_demod)
3791 v4l2_i2c_new_subdev(&core->v4l2_dev,
3792 &core->i2c_adap, "tuner",
3793 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
3794 if (core->board.tuner_addr == ADDR_UNSET) {
3795 v4l2_i2c_new_subdev(&core->v4l2_dev,
3796 &core->i2c_adap, "tuner",
3797 0, has_demod ? tv_addrs + 4 : tv_addrs);
3798 } else {
3799 v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
3800 "tuner", core->board.tuner_addr, NULL);
3801 }
3802 }
3803
3804 cx88_card_setup(core);
3805 if (!disable_ir) {
3806 cx88_i2c_init_ir(core);
3807 cx88_ir_init(core, pci);
3808 }
3809
3810 return core;
3811}
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
new file mode 100644
index 000000000000..c97b174be3ab
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -0,0 +1,1131 @@
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 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 /* Reset on-board parts */
640 cx_write(MO_SRST_IO, 0);
641 msleep(10);
642 cx_write(MO_SRST_IO, 1);
643
644 return 0;
645}
646
647/* ------------------------------------------------------------------ */
648
649static unsigned int inline norm_swidth(v4l2_std_id norm)
650{
651 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
652}
653
654static unsigned int inline norm_hdelay(v4l2_std_id norm)
655{
656 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
657}
658
659static unsigned int inline norm_vdelay(v4l2_std_id norm)
660{
661 return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
662}
663
664static unsigned int inline norm_fsc8(v4l2_std_id norm)
665{
666 if (norm & V4L2_STD_PAL_M)
667 return 28604892; // 3.575611 MHz
668
669 if (norm & (V4L2_STD_PAL_Nc))
670 return 28656448; // 3.582056 MHz
671
672 if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
673 return 28636360; // 3.57954545 MHz +/- 10 Hz
674
675 /* SECAM have also different sub carrier for chroma,
676 but step_db and step_dr, at cx88_set_tvnorm already handles that.
677
678 The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
679 */
680
681 return 35468950; // 4.43361875 MHz +/- 5 Hz
682}
683
684static unsigned int inline norm_htotal(v4l2_std_id norm)
685{
686
687 unsigned int fsc4=norm_fsc8(norm)/2;
688
689 /* returns 4*FSC / vtotal / frames per seconds */
690 return (norm & V4L2_STD_625_50) ?
691 ((fsc4+312)/625+12)/25 :
692 ((fsc4+262)/525*1001+15000)/30000;
693}
694
695static unsigned int inline norm_vbipack(v4l2_std_id norm)
696{
697 return (norm & V4L2_STD_625_50) ? 511 : 400;
698}
699
700int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
701 enum v4l2_field field)
702{
703 unsigned int swidth = norm_swidth(core->tvnorm);
704 unsigned int sheight = norm_maxh(core->tvnorm);
705 u32 value;
706
707 dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
708 V4L2_FIELD_HAS_TOP(field) ? "T" : "",
709 V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
710 v4l2_norm_to_name(core->tvnorm));
711 if (!V4L2_FIELD_HAS_BOTH(field))
712 height *= 2;
713
714 // recalc H delay and scale registers
715 value = (width * norm_hdelay(core->tvnorm)) / swidth;
716 value &= 0x3fe;
717 cx_write(MO_HDELAY_EVEN, value);
718 cx_write(MO_HDELAY_ODD, value);
719 dprintk(1,"set_scale: hdelay 0x%04x (width %d)\n", value,swidth);
720
721 value = (swidth * 4096 / width) - 4096;
722 cx_write(MO_HSCALE_EVEN, value);
723 cx_write(MO_HSCALE_ODD, value);
724 dprintk(1,"set_scale: hscale 0x%04x\n", value);
725
726 cx_write(MO_HACTIVE_EVEN, width);
727 cx_write(MO_HACTIVE_ODD, width);
728 dprintk(1,"set_scale: hactive 0x%04x\n", width);
729
730 // recalc V scale Register (delay is constant)
731 cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
732 cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
733 dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
734
735 value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
736 cx_write(MO_VSCALE_EVEN, value);
737 cx_write(MO_VSCALE_ODD, value);
738 dprintk(1,"set_scale: vscale 0x%04x\n", value);
739
740 cx_write(MO_VACTIVE_EVEN, sheight);
741 cx_write(MO_VACTIVE_ODD, sheight);
742 dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
743
744 // setup filters
745 value = 0;
746 value |= (1 << 19); // CFILT (default)
747 if (core->tvnorm & V4L2_STD_SECAM) {
748 value |= (1 << 15);
749 value |= (1 << 16);
750 }
751 if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
752 value |= (1 << 13) | (1 << 5);
753 if (V4L2_FIELD_INTERLACED == field)
754 value |= (1 << 3); // VINT (interlaced vertical scaling)
755 if (width < 385)
756 value |= (1 << 0); // 3-tap interpolation
757 if (width < 193)
758 value |= (1 << 1); // 5-tap interpolation
759 if (nocomb)
760 value |= (3 << 5); // disable comb filter
761
762 cx_andor(MO_FILTER_EVEN, 0x7ffc7f, value); /* preserve PEAKEN, PSEL */
763 cx_andor(MO_FILTER_ODD, 0x7ffc7f, value);
764 dprintk(1,"set_scale: filter 0x%04x\n", value);
765
766 return 0;
767}
768
769static const u32 xtal = 28636363;
770
771static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
772{
773 static const u32 pre[] = { 0, 0, 0, 3, 2, 1 };
774 u64 pll;
775 u32 reg;
776 int i;
777
778 if (prescale < 2)
779 prescale = 2;
780 if (prescale > 5)
781 prescale = 5;
782
783 pll = ofreq * 8 * prescale * (u64)(1 << 20);
784 do_div(pll,xtal);
785 reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
786 if (((reg >> 20) & 0x3f) < 14) {
787 printk("%s/0: pll out of range\n",core->name);
788 return -1;
789 }
790
791 dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
792 reg, cx_read(MO_PLL_REG), ofreq);
793 cx_write(MO_PLL_REG, reg);
794 for (i = 0; i < 100; i++) {
795 reg = cx_read(MO_DEVICE_STATUS);
796 if (reg & (1<<2)) {
797 dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
798 prescale,ofreq);
799 return 0;
800 }
801 dprintk(1,"pll not locked yet, waiting ...\n");
802 msleep(10);
803 }
804 dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
805 return -1;
806}
807
808int cx88_start_audio_dma(struct cx88_core *core)
809{
810 /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
811 int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
812
813 int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
814
815 /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
816 if (cx_read(MO_AUD_DMACNTRL) & 0x10)
817 return 0;
818
819 /* setup fifo + format */
820 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
821 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
822 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
823 rds_bpl, 0);
824
825 cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
826 cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
827
828 /* enable Up, Down and Audio RDS fifo */
829 cx_write(MO_AUD_DMACNTRL, 0x0007);
830
831 return 0;
832}
833
834int cx88_stop_audio_dma(struct cx88_core *core)
835{
836 /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
837 if (cx_read(MO_AUD_DMACNTRL) & 0x10)
838 return 0;
839
840 /* stop dma */
841 cx_write(MO_AUD_DMACNTRL, 0x0000);
842
843 return 0;
844}
845
846static int set_tvaudio(struct cx88_core *core)
847{
848 v4l2_std_id norm = core->tvnorm;
849
850 if (CX88_VMUX_TELEVISION != INPUT(core->input).type &&
851 CX88_VMUX_CABLE != INPUT(core->input).type)
852 return 0;
853
854 if (V4L2_STD_PAL_BG & norm) {
855 core->tvaudio = WW_BG;
856
857 } else if (V4L2_STD_PAL_DK & norm) {
858 core->tvaudio = WW_DK;
859
860 } else if (V4L2_STD_PAL_I & norm) {
861 core->tvaudio = WW_I;
862
863 } else if (V4L2_STD_SECAM_L & norm) {
864 core->tvaudio = WW_L;
865
866 } else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
867 core->tvaudio = WW_BG;
868
869 } else if (V4L2_STD_SECAM_DK & norm) {
870 core->tvaudio = WW_DK;
871
872 } else if ((V4L2_STD_NTSC_M & norm) ||
873 (V4L2_STD_PAL_M & norm)) {
874 core->tvaudio = WW_BTSC;
875
876 } else if (V4L2_STD_NTSC_M_JP & norm) {
877 core->tvaudio = WW_EIAJ;
878
879 } else {
880 printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
881 core->name, v4l2_norm_to_name(core->tvnorm));
882 core->tvaudio = WW_NONE;
883 return 0;
884 }
885
886 cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
887 cx88_set_tvaudio(core);
888 /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
889
890/*
891 This should be needed only on cx88-alsa. It seems that some cx88 chips have
892 bugs and does require DMA enabled for it to work.
893 */
894 cx88_start_audio_dma(core);
895 return 0;
896}
897
898
899
900int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
901{
902 u32 fsc8;
903 u32 adc_clock;
904 u32 vdec_clock;
905 u32 step_db,step_dr;
906 u64 tmp64;
907 u32 bdelay,agcdelay,htotal;
908 u32 cxiformat, cxoformat;
909
910 core->tvnorm = norm;
911 fsc8 = norm_fsc8(norm);
912 adc_clock = xtal;
913 vdec_clock = fsc8;
914 step_db = fsc8;
915 step_dr = fsc8;
916
917 if (norm & V4L2_STD_NTSC_M_JP) {
918 cxiformat = VideoFormatNTSCJapan;
919 cxoformat = 0x181f0008;
920 } else if (norm & V4L2_STD_NTSC_443) {
921 cxiformat = VideoFormatNTSC443;
922 cxoformat = 0x181f0008;
923 } else if (norm & V4L2_STD_PAL_M) {
924 cxiformat = VideoFormatPALM;
925 cxoformat = 0x1c1f0008;
926 } else if (norm & V4L2_STD_PAL_N) {
927 cxiformat = VideoFormatPALN;
928 cxoformat = 0x1c1f0008;
929 } else if (norm & V4L2_STD_PAL_Nc) {
930 cxiformat = VideoFormatPALNC;
931 cxoformat = 0x1c1f0008;
932 } else if (norm & V4L2_STD_PAL_60) {
933 cxiformat = VideoFormatPAL60;
934 cxoformat = 0x181f0008;
935 } else if (norm & V4L2_STD_NTSC) {
936 cxiformat = VideoFormatNTSC;
937 cxoformat = 0x181f0008;
938 } else if (norm & V4L2_STD_SECAM) {
939 step_db = 4250000 * 8;
940 step_dr = 4406250 * 8;
941
942 cxiformat = VideoFormatSECAM;
943 cxoformat = 0x181f0008;
944 } else { /* PAL */
945 cxiformat = VideoFormatPAL;
946 cxoformat = 0x181f0008;
947 }
948
949 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
950 v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
951 step_db, step_dr);
952 set_pll(core,2,vdec_clock);
953
954 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
955 cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
956 /* Chroma AGC must be disabled if SECAM is used, we enable it
957 by default on PAL and NTSC */
958 cx_andor(MO_INPUT_FORMAT, 0x40f,
959 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
960
961 // FIXME: as-is from DScaler
962 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
963 cxoformat, cx_read(MO_OUTPUT_FORMAT));
964 cx_write(MO_OUTPUT_FORMAT, cxoformat);
965
966 // MO_SCONV_REG = adc clock / video dec clock * 2^17
967 tmp64 = adc_clock * (u64)(1 << 17);
968 do_div(tmp64, vdec_clock);
969 dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
970 (u32)tmp64, cx_read(MO_SCONV_REG));
971 cx_write(MO_SCONV_REG, (u32)tmp64);
972
973 // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
974 tmp64 = step_db * (u64)(1 << 22);
975 do_div(tmp64, vdec_clock);
976 dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
977 (u32)tmp64, cx_read(MO_SUB_STEP));
978 cx_write(MO_SUB_STEP, (u32)tmp64);
979
980 // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
981 tmp64 = step_dr * (u64)(1 << 22);
982 do_div(tmp64, vdec_clock);
983 dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
984 (u32)tmp64, cx_read(MO_SUB_STEP_DR));
985 cx_write(MO_SUB_STEP_DR, (u32)tmp64);
986
987 // bdelay + agcdelay
988 bdelay = vdec_clock * 65 / 20000000 + 21;
989 agcdelay = vdec_clock * 68 / 20000000 + 15;
990 dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
991 (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
992 cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
993
994 // htotal
995 tmp64 = norm_htotal(norm) * (u64)vdec_clock;
996 do_div(tmp64, fsc8);
997 htotal = (u32)tmp64;
998 dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
999 htotal, cx_read(MO_HTOTAL), (u32)tmp64);
1000 cx_andor(MO_HTOTAL, 0x07ff, htotal);
1001
1002 // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
1003 // the effective vbi offset ~244 samples, the same as the Bt8x8
1004 cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
1005
1006 // this is needed as well to set all tvnorm parameter
1007 cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
1008
1009 // audio
1010 set_tvaudio(core);
1011
1012 // tell i2c chips
1013 call_all(core, core, s_std, norm);
1014
1015 /* The chroma_agc control should be inaccessible if the video format is SECAM */
1016 v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
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->release = video_device_release;
1037 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1038 core->name, type, core->board.name);
1039 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
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_ctrl_handler_free(&core->video_hdl);
1093 v4l2_ctrl_handler_free(&core->audio_hdl);
1094 v4l2_device_unregister(&core->v4l2_dev);
1095 kfree(core);
1096}
1097
1098/* ------------------------------------------------------------------ */
1099
1100EXPORT_SYMBOL(cx88_print_irqbits);
1101
1102EXPORT_SYMBOL(cx88_core_irq);
1103EXPORT_SYMBOL(cx88_wakeup);
1104EXPORT_SYMBOL(cx88_reset);
1105EXPORT_SYMBOL(cx88_shutdown);
1106
1107EXPORT_SYMBOL(cx88_risc_buffer);
1108EXPORT_SYMBOL(cx88_risc_databuffer);
1109EXPORT_SYMBOL(cx88_risc_stopper);
1110EXPORT_SYMBOL(cx88_free_buffer);
1111
1112EXPORT_SYMBOL(cx88_sram_channels);
1113EXPORT_SYMBOL(cx88_sram_channel_setup);
1114EXPORT_SYMBOL(cx88_sram_channel_dump);
1115
1116EXPORT_SYMBOL(cx88_set_tvnorm);
1117EXPORT_SYMBOL(cx88_set_scale);
1118
1119EXPORT_SYMBOL(cx88_vdev_init);
1120EXPORT_SYMBOL(cx88_core_get);
1121EXPORT_SYMBOL(cx88_core_put);
1122
1123EXPORT_SYMBOL(cx88_ir_start);
1124EXPORT_SYMBOL(cx88_ir_stop);
1125
1126/*
1127 * Local variables:
1128 * c-basic-offset: 8
1129 * End:
1130 * 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
1131 */
diff --git a/drivers/media/pci/cx88/cx88-dsp.c b/drivers/media/pci/cx88/cx88-dsp.c
new file mode 100644
index 000000000000..a9907265ff66
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
new file mode 100644
index 000000000000..d803bba09525
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -0,0 +1,1778 @@
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{
820 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
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 = c->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 (c->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 int res = -EINVAL;
958
959 if (0 != core->i2c_rc) {
960 printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
961 goto frontend_detach;
962 }
963
964 /* Get the first frontend */
965 fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
966 if (!fe0)
967 goto frontend_detach;
968
969 /* multi-frontend gate control is undefined or defaults to fe0 */
970 dev->frontends.gate = 0;
971
972 /* Sets the gate control callback to be used by i2c command calls */
973 core->gate_ctrl = cx88_dvb_gate_ctrl;
974
975 /* init frontend(s) */
976 switch (core->boardnr) {
977 case CX88_BOARD_HAUPPAUGE_DVB_T1:
978 fe0->dvb.frontend = dvb_attach(cx22702_attach,
979 &connexant_refboard_config,
980 &core->i2c_adap);
981 if (fe0->dvb.frontend != NULL) {
982 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
983 0x61, &core->i2c_adap,
984 DVB_PLL_THOMSON_DTT759X))
985 goto frontend_detach;
986 }
987 break;
988 case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
989 case CX88_BOARD_CONEXANT_DVB_T1:
990 case CX88_BOARD_KWORLD_DVB_T_CX22702:
991 case CX88_BOARD_WINFAST_DTV1000:
992 fe0->dvb.frontend = dvb_attach(cx22702_attach,
993 &connexant_refboard_config,
994 &core->i2c_adap);
995 if (fe0->dvb.frontend != NULL) {
996 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
997 0x60, &core->i2c_adap,
998 DVB_PLL_THOMSON_DTT7579))
999 goto frontend_detach;
1000 }
1001 break;
1002 case CX88_BOARD_WINFAST_DTV2000H:
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_WINFAST_DTV2000H_J:
1017 fe0->dvb.frontend = dvb_attach(cx22702_attach,
1018 &hauppauge_hvr_config,
1019 &core->i2c_adap);
1020 if (fe0->dvb.frontend != NULL) {
1021 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1022 &core->i2c_adap, 0x61,
1023 TUNER_PHILIPS_FMD1216MEX_MK3))
1024 goto frontend_detach;
1025 }
1026 break;
1027 case CX88_BOARD_HAUPPAUGE_HVR3000:
1028 /* MFE frontend 1 */
1029 mfe_shared = 1;
1030 dev->frontends.gate = 2;
1031 /* DVB-S init */
1032 fe0->dvb.frontend = dvb_attach(cx24123_attach,
1033 &hauppauge_novas_config,
1034 &dev->core->i2c_adap);
1035 if (fe0->dvb.frontend) {
1036 if (!dvb_attach(isl6421_attach,
1037 fe0->dvb.frontend,
1038 &dev->core->i2c_adap,
1039 0x08, ISL6421_DCL, 0x00))
1040 goto frontend_detach;
1041 }
1042 /* MFE frontend 2 */
1043 fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
1044 if (!fe1)
1045 goto frontend_detach;
1046 /* DVB-T init */
1047 fe1->dvb.frontend = dvb_attach(cx22702_attach,
1048 &hauppauge_hvr_config,
1049 &dev->core->i2c_adap);
1050 if (fe1->dvb.frontend) {
1051 fe1->dvb.frontend->id = 1;
1052 if (!dvb_attach(simple_tuner_attach,
1053 fe1->dvb.frontend,
1054 &dev->core->i2c_adap,
1055 0x61, TUNER_PHILIPS_FMD1216ME_MK3))
1056 goto frontend_detach;
1057 }
1058 break;
1059 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
1060 fe0->dvb.frontend = dvb_attach(mt352_attach,
1061 &dvico_fusionhdtv,
1062 &core->i2c_adap);
1063 if (fe0->dvb.frontend != NULL) {
1064 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1065 0x60, NULL, DVB_PLL_THOMSON_DTT7579))
1066 goto frontend_detach;
1067 break;
1068 }
1069 /* ZL10353 replaces MT352 on later cards */
1070 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1071 &dvico_fusionhdtv_plus_v1_1,
1072 &core->i2c_adap);
1073 if (fe0->dvb.frontend != NULL) {
1074 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1075 0x60, NULL, DVB_PLL_THOMSON_DTT7579))
1076 goto frontend_detach;
1077 }
1078 break;
1079 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
1080 /* The tin box says DEE1601, but it seems to be DTT7579
1081 * compatible, with a slightly different MT352 AGC gain. */
1082 fe0->dvb.frontend = dvb_attach(mt352_attach,
1083 &dvico_fusionhdtv_dual,
1084 &core->i2c_adap);
1085 if (fe0->dvb.frontend != NULL) {
1086 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1087 0x61, NULL, DVB_PLL_THOMSON_DTT7579))
1088 goto frontend_detach;
1089 break;
1090 }
1091 /* ZL10353 replaces MT352 on later cards */
1092 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1093 &dvico_fusionhdtv_plus_v1_1,
1094 &core->i2c_adap);
1095 if (fe0->dvb.frontend != NULL) {
1096 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1097 0x61, NULL, DVB_PLL_THOMSON_DTT7579))
1098 goto frontend_detach;
1099 }
1100 break;
1101 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
1102 fe0->dvb.frontend = dvb_attach(mt352_attach,
1103 &dvico_fusionhdtv,
1104 &core->i2c_adap);
1105 if (fe0->dvb.frontend != NULL) {
1106 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1107 0x61, NULL, DVB_PLL_LG_Z201))
1108 goto frontend_detach;
1109 }
1110 break;
1111 case CX88_BOARD_KWORLD_DVB_T:
1112 case CX88_BOARD_DNTV_LIVE_DVB_T:
1113 case CX88_BOARD_ADSTECH_DVB_T_PCI:
1114 fe0->dvb.frontend = dvb_attach(mt352_attach,
1115 &dntv_live_dvbt_config,
1116 &core->i2c_adap);
1117 if (fe0->dvb.frontend != NULL) {
1118 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
1119 0x61, NULL, DVB_PLL_UNKNOWN_1))
1120 goto frontend_detach;
1121 }
1122 break;
1123 case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
1124#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
1125 /* MT352 is on a secondary I2C bus made from some GPIO lines */
1126 fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
1127 &dev->vp3054->adap);
1128 if (fe0->dvb.frontend != NULL) {
1129 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1130 &core->i2c_adap, 0x61,
1131 TUNER_PHILIPS_FMD1216ME_MK3))
1132 goto frontend_detach;
1133 }
1134#else
1135 printk(KERN_ERR "%s/2: built without vp3054 support\n",
1136 core->name);
1137#endif
1138 break;
1139 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
1140 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1141 &dvico_fusionhdtv_hybrid,
1142 &core->i2c_adap);
1143 if (fe0->dvb.frontend != NULL) {
1144 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1145 &core->i2c_adap, 0x61,
1146 TUNER_THOMSON_FE6600))
1147 goto frontend_detach;
1148 }
1149 break;
1150 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
1151 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1152 &dvico_fusionhdtv_xc3028,
1153 &core->i2c_adap);
1154 if (fe0->dvb.frontend == NULL)
1155 fe0->dvb.frontend = dvb_attach(mt352_attach,
1156 &dvico_fusionhdtv_mt352_xc3028,
1157 &core->i2c_adap);
1158 /*
1159 * On this board, the demod provides the I2C bus pullup.
1160 * We must not permit gate_ctrl to be performed, or
1161 * the xc3028 cannot communicate on the bus.
1162 */
1163 if (fe0->dvb.frontend)
1164 fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1165 if (attach_xc3028(0x61, dev) < 0)
1166 goto frontend_detach;
1167 break;
1168 case CX88_BOARD_PCHDTV_HD3000:
1169 fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
1170 &core->i2c_adap);
1171 if (fe0->dvb.frontend != NULL) {
1172 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1173 &core->i2c_adap, 0x61,
1174 TUNER_THOMSON_DTT761X))
1175 goto frontend_detach;
1176 }
1177 break;
1178 case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
1179 dev->ts_gen_cntrl = 0x08;
1180
1181 /* Do a hardware reset of chip before using it. */
1182 cx_clear(MO_GP0_IO, 1);
1183 mdelay(100);
1184 cx_set(MO_GP0_IO, 1);
1185 mdelay(200);
1186
1187 /* Select RF connector callback */
1188 fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
1189 fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1190 &fusionhdtv_3_gold,
1191 &core->i2c_adap);
1192 if (fe0->dvb.frontend != NULL) {
1193 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1194 &core->i2c_adap, 0x61,
1195 TUNER_MICROTUNE_4042FI5))
1196 goto frontend_detach;
1197 }
1198 break;
1199 case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
1200 dev->ts_gen_cntrl = 0x08;
1201
1202 /* Do a hardware reset of chip before using it. */
1203 cx_clear(MO_GP0_IO, 1);
1204 mdelay(100);
1205 cx_set(MO_GP0_IO, 9);
1206 mdelay(200);
1207 fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1208 &fusionhdtv_3_gold,
1209 &core->i2c_adap);
1210 if (fe0->dvb.frontend != NULL) {
1211 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1212 &core->i2c_adap, 0x61,
1213 TUNER_THOMSON_DTT761X))
1214 goto frontend_detach;
1215 }
1216 break;
1217 case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
1218 dev->ts_gen_cntrl = 0x08;
1219
1220 /* Do a hardware reset of chip before using it. */
1221 cx_clear(MO_GP0_IO, 1);
1222 mdelay(100);
1223 cx_set(MO_GP0_IO, 1);
1224 mdelay(200);
1225 fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1226 &fusionhdtv_5_gold,
1227 &core->i2c_adap);
1228 if (fe0->dvb.frontend != NULL) {
1229 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1230 &core->i2c_adap, 0x61,
1231 TUNER_LG_TDVS_H06XF))
1232 goto frontend_detach;
1233 if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
1234 &core->i2c_adap, 0x43))
1235 goto frontend_detach;
1236 }
1237 break;
1238 case CX88_BOARD_PCHDTV_HD5500:
1239 dev->ts_gen_cntrl = 0x08;
1240
1241 /* Do a hardware reset of chip before using it. */
1242 cx_clear(MO_GP0_IO, 1);
1243 mdelay(100);
1244 cx_set(MO_GP0_IO, 1);
1245 mdelay(200);
1246 fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
1247 &pchdtv_hd5500,
1248 &core->i2c_adap);
1249 if (fe0->dvb.frontend != NULL) {
1250 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1251 &core->i2c_adap, 0x61,
1252 TUNER_LG_TDVS_H06XF))
1253 goto frontend_detach;
1254 if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
1255 &core->i2c_adap, 0x43))
1256 goto frontend_detach;
1257 }
1258 break;
1259 case CX88_BOARD_ATI_HDTVWONDER:
1260 fe0->dvb.frontend = dvb_attach(nxt200x_attach,
1261 &ati_hdtvwonder,
1262 &core->i2c_adap);
1263 if (fe0->dvb.frontend != NULL) {
1264 if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
1265 &core->i2c_adap, 0x61,
1266 TUNER_PHILIPS_TUV1236D))
1267 goto frontend_detach;
1268 }
1269 break;
1270 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
1271 case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
1272 fe0->dvb.frontend = dvb_attach(cx24123_attach,
1273 &hauppauge_novas_config,
1274 &core->i2c_adap);
1275 if (fe0->dvb.frontend) {
1276 if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
1277 &core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
1278 goto frontend_detach;
1279 }
1280 break;
1281 case CX88_BOARD_KWORLD_DVBS_100:
1282 fe0->dvb.frontend = dvb_attach(cx24123_attach,
1283 &kworld_dvbs_100_config,
1284 &core->i2c_adap);
1285 if (fe0->dvb.frontend) {
1286 core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1287 fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
1288 }
1289 break;
1290 case CX88_BOARD_GENIATECH_DVBS:
1291 fe0->dvb.frontend = dvb_attach(cx24123_attach,
1292 &geniatech_dvbs_config,
1293 &core->i2c_adap);
1294 if (fe0->dvb.frontend) {
1295 core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1296 fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
1297 }
1298 break;
1299 case CX88_BOARD_PINNACLE_PCTV_HD_800i:
1300 fe0->dvb.frontend = dvb_attach(s5h1409_attach,
1301 &pinnacle_pctv_hd_800i_config,
1302 &core->i2c_adap);
1303 if (fe0->dvb.frontend != NULL) {
1304 if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
1305 &core->i2c_adap,
1306 &pinnacle_pctv_hd_800i_tuner_config))
1307 goto frontend_detach;
1308 }
1309 break;
1310 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
1311 fe0->dvb.frontend = dvb_attach(s5h1409_attach,
1312 &dvico_hdtv5_pci_nano_config,
1313 &core->i2c_adap);
1314 if (fe0->dvb.frontend != NULL) {
1315 struct dvb_frontend *fe;
1316 struct xc2028_config cfg = {
1317 .i2c_adap = &core->i2c_adap,
1318 .i2c_addr = 0x61,
1319 };
1320 static struct xc2028_ctrl ctl = {
1321 .fname = XC2028_DEFAULT_FIRMWARE,
1322 .max_len = 64,
1323 .scode_table = XC3028_FE_OREN538,
1324 };
1325
1326 fe = dvb_attach(xc2028_attach,
1327 fe0->dvb.frontend, &cfg);
1328 if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
1329 fe->ops.tuner_ops.set_config(fe, &ctl);
1330 }
1331 break;
1332 case CX88_BOARD_PINNACLE_HYBRID_PCTV:
1333 case CX88_BOARD_WINFAST_DTV1800H:
1334 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1335 &cx88_pinnacle_hybrid_pctv,
1336 &core->i2c_adap);
1337 if (fe0->dvb.frontend) {
1338 fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1339 if (attach_xc3028(0x61, dev) < 0)
1340 goto frontend_detach;
1341 }
1342 break;
1343 case CX88_BOARD_WINFAST_DTV1800H_XC4000:
1344 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
1345 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1346 &cx88_pinnacle_hybrid_pctv,
1347 &core->i2c_adap);
1348 if (fe0->dvb.frontend) {
1349 struct xc4000_config cfg = {
1350 .i2c_address = 0x61,
1351 .default_pm = 0,
1352 .dvb_amplitude = 134,
1353 .set_smoothedcvbs = 1,
1354 .if_khz = 4560
1355 };
1356 fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1357 if (attach_xc4000(dev, &cfg) < 0)
1358 goto frontend_detach;
1359 }
1360 break;
1361 case CX88_BOARD_GENIATECH_X8000_MT:
1362 dev->ts_gen_cntrl = 0x00;
1363
1364 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1365 &cx88_geniatech_x8000_mt,
1366 &core->i2c_adap);
1367 if (attach_xc3028(0x61, dev) < 0)
1368 goto frontend_detach;
1369 break;
1370 case CX88_BOARD_KWORLD_ATSC_120:
1371 fe0->dvb.frontend = dvb_attach(s5h1409_attach,
1372 &kworld_atsc_120_config,
1373 &core->i2c_adap);
1374 if (attach_xc3028(0x61, dev) < 0)
1375 goto frontend_detach;
1376 break;
1377 case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
1378 fe0->dvb.frontend = dvb_attach(s5h1411_attach,
1379 &dvico_fusionhdtv7_config,
1380 &core->i2c_adap);
1381 if (fe0->dvb.frontend != NULL) {
1382 if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
1383 &core->i2c_adap,
1384 &dvico_fusionhdtv7_tuner_config))
1385 goto frontend_detach;
1386 }
1387 break;
1388 case CX88_BOARD_HAUPPAUGE_HVR4000:
1389 /* MFE frontend 1 */
1390 mfe_shared = 1;
1391 dev->frontends.gate = 2;
1392 /* DVB-S/S2 Init */
1393 fe0->dvb.frontend = dvb_attach(cx24116_attach,
1394 &hauppauge_hvr4000_config,
1395 &dev->core->i2c_adap);
1396 if (fe0->dvb.frontend) {
1397 if (!dvb_attach(isl6421_attach,
1398 fe0->dvb.frontend,
1399 &dev->core->i2c_adap,
1400 0x08, ISL6421_DCL, 0x00))
1401 goto frontend_detach;
1402 }
1403 /* MFE frontend 2 */
1404 fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
1405 if (!fe1)
1406 goto frontend_detach;
1407 /* DVB-T Init */
1408 fe1->dvb.frontend = dvb_attach(cx22702_attach,
1409 &hauppauge_hvr_config,
1410 &dev->core->i2c_adap);
1411 if (fe1->dvb.frontend) {
1412 fe1->dvb.frontend->id = 1;
1413 if (!dvb_attach(simple_tuner_attach,
1414 fe1->dvb.frontend,
1415 &dev->core->i2c_adap,
1416 0x61, TUNER_PHILIPS_FMD1216ME_MK3))
1417 goto frontend_detach;
1418 }
1419 break;
1420 case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
1421 fe0->dvb.frontend = dvb_attach(cx24116_attach,
1422 &hauppauge_hvr4000_config,
1423 &dev->core->i2c_adap);
1424 if (fe0->dvb.frontend) {
1425 if (!dvb_attach(isl6421_attach,
1426 fe0->dvb.frontend,
1427 &dev->core->i2c_adap,
1428 0x08, ISL6421_DCL, 0x00))
1429 goto frontend_detach;
1430 }
1431 break;
1432 case CX88_BOARD_PROF_6200:
1433 case CX88_BOARD_TBS_8910:
1434 case CX88_BOARD_TEVII_S420:
1435 fe0->dvb.frontend = dvb_attach(stv0299_attach,
1436 &tevii_tuner_sharp_config,
1437 &core->i2c_adap);
1438 if (fe0->dvb.frontend != NULL) {
1439 if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
1440 &core->i2c_adap, DVB_PLL_OPERA1))
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 } else {
1446 fe0->dvb.frontend = dvb_attach(stv0288_attach,
1447 &tevii_tuner_earda_config,
1448 &core->i2c_adap);
1449 if (fe0->dvb.frontend != NULL) {
1450 if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
1451 &core->i2c_adap))
1452 goto frontend_detach;
1453 core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
1454 fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1455 }
1456 }
1457 break;
1458 case CX88_BOARD_TEVII_S460:
1459 fe0->dvb.frontend = dvb_attach(cx24116_attach,
1460 &tevii_s460_config,
1461 &core->i2c_adap);
1462 if (fe0->dvb.frontend != NULL)
1463 fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1464 break;
1465 case CX88_BOARD_TEVII_S464:
1466 fe0->dvb.frontend = dvb_attach(ds3000_attach,
1467 &tevii_ds3000_config,
1468 &core->i2c_adap);
1469 if (fe0->dvb.frontend != NULL)
1470 fe0->dvb.frontend->ops.set_voltage =
1471 tevii_dvbs_set_voltage;
1472 break;
1473 case CX88_BOARD_OMICOM_SS4_PCI:
1474 case CX88_BOARD_TBS_8920:
1475 case CX88_BOARD_PROF_7300:
1476 case CX88_BOARD_SATTRADE_ST4200:
1477 fe0->dvb.frontend = dvb_attach(cx24116_attach,
1478 &hauppauge_hvr4000_config,
1479 &core->i2c_adap);
1480 if (fe0->dvb.frontend != NULL)
1481 fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
1482 break;
1483 case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
1484 fe0->dvb.frontend = dvb_attach(zl10353_attach,
1485 &cx88_terratec_cinergy_ht_pci_mkii_config,
1486 &core->i2c_adap);
1487 if (fe0->dvb.frontend) {
1488 fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
1489 if (attach_xc3028(0x61, dev) < 0)
1490 goto frontend_detach;
1491 }
1492 break;
1493 case CX88_BOARD_PROF_7301:{
1494 struct dvb_tuner_ops *tuner_ops = NULL;
1495
1496 fe0->dvb.frontend = dvb_attach(stv0900_attach,
1497 &prof_7301_stv0900_config,
1498 &core->i2c_adap, 0);
1499 if (fe0->dvb.frontend != NULL) {
1500 if (!dvb_attach(stb6100_attach, fe0->dvb.frontend,
1501 &prof_7301_stb6100_config,
1502 &core->i2c_adap))
1503 goto frontend_detach;
1504
1505 tuner_ops = &fe0->dvb.frontend->ops.tuner_ops;
1506 tuner_ops->set_frequency = stb6100_set_freq;
1507 tuner_ops->get_frequency = stb6100_get_freq;
1508 tuner_ops->set_bandwidth = stb6100_set_bandw;
1509 tuner_ops->get_bandwidth = stb6100_get_bandw;
1510
1511 core->prev_set_voltage =
1512 fe0->dvb.frontend->ops.set_voltage;
1513 fe0->dvb.frontend->ops.set_voltage =
1514 tevii_dvbs_set_voltage;
1515 }
1516 break;
1517 }
1518 case CX88_BOARD_SAMSUNG_SMT_7020:
1519 dev->ts_gen_cntrl = 0x08;
1520
1521 cx_set(MO_GP0_IO, 0x0101);
1522
1523 cx_clear(MO_GP0_IO, 0x01);
1524 mdelay(100);
1525 cx_set(MO_GP0_IO, 0x01);
1526 mdelay(200);
1527
1528 fe0->dvb.frontend = dvb_attach(stv0299_attach,
1529 &samsung_stv0299_config,
1530 &dev->core->i2c_adap);
1531 if (fe0->dvb.frontend) {
1532 fe0->dvb.frontend->ops.tuner_ops.set_params =
1533 samsung_smt_7020_tuner_set_params;
1534 fe0->dvb.frontend->tuner_priv =
1535 &dev->core->i2c_adap;
1536 fe0->dvb.frontend->ops.set_voltage =
1537 samsung_smt_7020_set_voltage;
1538 fe0->dvb.frontend->ops.set_tone =
1539 samsung_smt_7020_set_tone;
1540 }
1541
1542 break;
1543 case CX88_BOARD_TWINHAN_VP1027_DVBS:
1544 dev->ts_gen_cntrl = 0x00;
1545 fe0->dvb.frontend = dvb_attach(mb86a16_attach,
1546 &twinhan_vp1027,
1547 &core->i2c_adap);
1548 if (fe0->dvb.frontend) {
1549 core->prev_set_voltage =
1550 fe0->dvb.frontend->ops.set_voltage;
1551 fe0->dvb.frontend->ops.set_voltage =
1552 vp1027_set_voltage;
1553 }
1554 break;
1555
1556 default:
1557 printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
1558 core->name);
1559 break;
1560 }
1561
1562 if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) {
1563 printk(KERN_ERR
1564 "%s/2: frontend initialization failed\n",
1565 core->name);
1566 goto frontend_detach;
1567 }
1568 /* define general-purpose callback pointer */
1569 fe0->dvb.frontend->callback = cx88_tuner_callback;
1570
1571 /* Ensure all frontends negotiate bus access */
1572 fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
1573 if (fe1)
1574 fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
1575
1576 /* Put the analog decoder in standby to keep it quiet */
1577 call_all(core, core, s_power, 0);
1578
1579 /* register everything */
1580 res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
1581 &dev->pci->dev, adapter_nr, mfe_shared);
1582 if (res)
1583 goto frontend_detach;
1584 return res;
1585
1586frontend_detach:
1587 core->gate_ctrl = NULL;
1588 videobuf_dvb_dealloc_frontends(&dev->frontends);
1589 return res;
1590}
1591
1592/* ----------------------------------------------------------- */
1593
1594/* CX8802 MPEG -> mini driver - We have been given the hardware */
1595static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
1596{
1597 struct cx88_core *core = drv->core;
1598 int err = 0;
1599 dprintk( 1, "%s\n", __func__);
1600
1601 switch (core->boardnr) {
1602 case CX88_BOARD_HAUPPAUGE_HVR1300:
1603 /* We arrive here with either the cx23416 or the cx22702
1604 * on the bus. Take the bus from the cx23416 and enable the
1605 * cx22702 demod
1606 */
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 /* enable the cx22702 pins */
1615 cx_clear(MO_GP0_IO, 0x00000004);
1616 udelay(1000);
1617 break;
1618
1619 case CX88_BOARD_HAUPPAUGE_HVR3000:
1620 case CX88_BOARD_HAUPPAUGE_HVR4000:
1621 /* Toggle reset on cx22702 leaving i2c active */
1622 cx_set(MO_GP0_IO, 0x00000080);
1623 udelay(1000);
1624 cx_clear(MO_GP0_IO, 0x00000080);
1625 udelay(50);
1626 cx_set(MO_GP0_IO, 0x00000080);
1627 udelay(1000);
1628 switch (core->dvbdev->frontends.active_fe_id) {
1629 case 1: /* DVB-S/S2 Enabled */
1630 /* tri-state the cx22702 pins */
1631 cx_set(MO_GP0_IO, 0x00000004);
1632 /* Take the cx24116/cx24123 out of reset */
1633 cx_write(MO_SRST_IO, 1);
1634 core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
1635 break;
1636 case 2: /* DVB-T Enabled */
1637 /* Put the cx24116/cx24123 into reset */
1638 cx_write(MO_SRST_IO, 0);
1639 /* enable the cx22702 pins */
1640 cx_clear(MO_GP0_IO, 0x00000004);
1641 core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
1642 break;
1643 }
1644 udelay(1000);
1645 break;
1646
1647 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
1648 /* set RF input to AIR for DVB-T (GPIO 16) */
1649 cx_write(MO_GP2_IO, 0x0101);
1650 break;
1651
1652 default:
1653 err = -ENODEV;
1654 }
1655 return err;
1656}
1657
1658/* CX8802 MPEG -> mini driver - We no longer have the hardware */
1659static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
1660{
1661 struct cx88_core *core = drv->core;
1662 int err = 0;
1663 dprintk( 1, "%s\n", __func__);
1664
1665 switch (core->boardnr) {
1666 case CX88_BOARD_HAUPPAUGE_HVR1300:
1667 /* Do Nothing, leave the cx22702 on the bus. */
1668 break;
1669 case CX88_BOARD_HAUPPAUGE_HVR3000:
1670 case CX88_BOARD_HAUPPAUGE_HVR4000:
1671 break;
1672 default:
1673 err = -ENODEV;
1674 }
1675 return err;
1676}
1677
1678static int cx8802_dvb_probe(struct cx8802_driver *drv)
1679{
1680 struct cx88_core *core = drv->core;
1681 struct cx8802_dev *dev = drv->core->dvbdev;
1682 int err;
1683 struct videobuf_dvb_frontend *fe;
1684 int i;
1685
1686 dprintk( 1, "%s\n", __func__);
1687 dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
1688 core->boardnr,
1689 core->name,
1690 core->pci_bus,
1691 core->pci_slot);
1692
1693 err = -ENODEV;
1694 if (!(core->board.mpeg & CX88_MPEG_DVB))
1695 goto fail_core;
1696
1697 /* If vp3054 isn't enabled, a stub will just return 0 */
1698 err = vp3054_i2c_probe(dev);
1699 if (0 != err)
1700 goto fail_core;
1701
1702 /* dvb stuff */
1703 printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
1704 dev->ts_gen_cntrl = 0x0c;
1705
1706 err = cx8802_alloc_frontends(dev);
1707 if (err)
1708 goto fail_core;
1709
1710 err = -ENODEV;
1711 for (i = 1; i <= core->board.num_frontends; i++) {
1712 fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
1713 if (fe == NULL) {
1714 printk(KERN_ERR "%s() failed to get frontend(%d)\n",
1715 __func__, i);
1716 goto fail_probe;
1717 }
1718 videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
1719 &dev->pci->dev, &dev->slock,
1720 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1721 V4L2_FIELD_TOP,
1722 sizeof(struct cx88_buffer),
1723 dev, NULL);
1724 /* init struct videobuf_dvb */
1725 fe->dvb.name = dev->core->name;
1726 }
1727
1728 err = dvb_register(dev);
1729 if (err)
1730 /* frontends/adapter de-allocated in dvb_register */
1731 printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
1732 core->name, err);
1733 return err;
1734fail_probe:
1735 videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends);
1736fail_core:
1737 return err;
1738}
1739
1740static int cx8802_dvb_remove(struct cx8802_driver *drv)
1741{
1742 struct cx88_core *core = drv->core;
1743 struct cx8802_dev *dev = drv->core->dvbdev;
1744
1745 dprintk( 1, "%s\n", __func__);
1746
1747 videobuf_dvb_unregister_bus(&dev->frontends);
1748
1749 vp3054_i2c_remove(dev);
1750
1751 core->gate_ctrl = NULL;
1752
1753 return 0;
1754}
1755
1756static struct cx8802_driver cx8802_dvb_driver = {
1757 .type_id = CX88_MPEG_DVB,
1758 .hw_access = CX8802_DRVCTL_SHARED,
1759 .probe = cx8802_dvb_probe,
1760 .remove = cx8802_dvb_remove,
1761 .advise_acquire = cx8802_dvb_advise_acquire,
1762 .advise_release = cx8802_dvb_advise_release,
1763};
1764
1765static int __init dvb_init(void)
1766{
1767 printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n",
1768 CX88_VERSION);
1769 return cx8802_register_driver(&cx8802_dvb_driver);
1770}
1771
1772static void __exit dvb_fini(void)
1773{
1774 cx8802_unregister_driver(&cx8802_dvb_driver);
1775}
1776
1777module_init(dvb_init);
1778module_exit(dvb_fini);
diff --git a/drivers/media/pci/cx88/cx88-i2c.c b/drivers/media/pci/cx88/cx88-i2c.c
new file mode 100644
index 000000000000..de0f1af74e41
--- /dev/null
+++ b/drivers/media/pci/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 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/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
new file mode 100644
index 000000000000..ebf448c48ca3
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -0,0 +1,635 @@
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 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
107 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
108 gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
109 auxgpio = gpio;
110 break;
111 default:
112 auxgpio = gpio;
113 }
114 if (ir->polling) {
115 if (ir->last_gpio == auxgpio)
116 return;
117 ir->last_gpio = auxgpio;
118 }
119
120 /* extract data */
121 data = ir_extract_bits(gpio, ir->mask_keycode);
122 ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
123 gpio, data,
124 ir->polling ? "poll" : "irq",
125 (gpio & ir->mask_keydown) ? " down" : "",
126 (gpio & ir->mask_keyup) ? " up" : "");
127
128 if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) {
129 u32 gpio_key = cx_read(MO_GP0_IO);
130
131 data = (data << 4) | ((gpio_key & 0xf0) >> 4);
132
133 rc_keydown(ir->dev, data, 0);
134
135 } else if (ir->mask_keydown) {
136 /* bit set on keydown */
137 if (gpio & ir->mask_keydown)
138 rc_keydown_notimeout(ir->dev, data, 0);
139 else
140 rc_keyup(ir->dev);
141
142 } else if (ir->mask_keyup) {
143 /* bit cleared on keydown */
144 if (0 == (gpio & ir->mask_keyup))
145 rc_keydown_notimeout(ir->dev, data, 0);
146 else
147 rc_keyup(ir->dev);
148
149 } else {
150 /* can't distinguish keydown/up :-/ */
151 rc_keydown_notimeout(ir->dev, data, 0);
152 rc_keyup(ir->dev);
153 }
154}
155
156static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer)
157{
158 unsigned long missed;
159 struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);
160
161 cx88_ir_handle_key(ir);
162 missed = hrtimer_forward_now(&ir->timer,
163 ktime_set(0, ir->polling * 1000000));
164 if (missed > 1)
165 ir_dprintk("Missed ticks %ld\n", missed - 1);
166
167 return HRTIMER_RESTART;
168}
169
170static int __cx88_ir_start(void *priv)
171{
172 struct cx88_core *core = priv;
173 struct cx88_IR *ir;
174
175 if (!core || !core->ir)
176 return -EINVAL;
177
178 ir = core->ir;
179
180 if (ir->polling) {
181 hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
182 ir->timer.function = cx88_ir_work;
183 hrtimer_start(&ir->timer,
184 ktime_set(0, ir->polling * 1000000),
185 HRTIMER_MODE_REL);
186 }
187 if (ir->sampling) {
188 core->pci_irqmask |= PCI_INT_IR_SMPINT;
189 cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */
190 cx_write(MO_DDSCFG_IO, 0x5); /* enable */
191 }
192 return 0;
193}
194
195static void __cx88_ir_stop(void *priv)
196{
197 struct cx88_core *core = priv;
198 struct cx88_IR *ir;
199
200 if (!core || !core->ir)
201 return;
202
203 ir = core->ir;
204 if (ir->sampling) {
205 cx_write(MO_DDSCFG_IO, 0x0);
206 core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
207 }
208
209 if (ir->polling)
210 hrtimer_cancel(&ir->timer);
211}
212
213int cx88_ir_start(struct cx88_core *core)
214{
215 if (core->ir->users)
216 return __cx88_ir_start(core);
217
218 return 0;
219}
220
221void cx88_ir_stop(struct cx88_core *core)
222{
223 if (core->ir->users)
224 __cx88_ir_stop(core);
225}
226
227static int cx88_ir_open(struct rc_dev *rc)
228{
229 struct cx88_core *core = rc->priv;
230
231 core->ir->users++;
232 return __cx88_ir_start(core);
233}
234
235static void cx88_ir_close(struct rc_dev *rc)
236{
237 struct cx88_core *core = rc->priv;
238
239 core->ir->users--;
240 if (!core->ir->users)
241 __cx88_ir_stop(core);
242}
243
244/* ---------------------------------------------------------------------- */
245
246int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
247{
248 struct cx88_IR *ir;
249 struct rc_dev *dev;
250 char *ir_codes = NULL;
251 u64 rc_type = RC_TYPE_OTHER;
252 int err = -ENOMEM;
253 u32 hardware_mask = 0; /* For devices with a hardware mask, when
254 * used with a full-code IR table
255 */
256
257 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
258 dev = rc_allocate_device();
259 if (!ir || !dev)
260 goto err_out_free;
261
262 ir->dev = dev;
263
264 /* detect & configure */
265 switch (core->boardnr) {
266 case CX88_BOARD_DNTV_LIVE_DVB_T:
267 case CX88_BOARD_KWORLD_DVB_T:
268 case CX88_BOARD_KWORLD_DVB_T_CX22702:
269 ir_codes = RC_MAP_DNTV_LIVE_DVB_T;
270 ir->gpio_addr = MO_GP1_IO;
271 ir->mask_keycode = 0x1f;
272 ir->mask_keyup = 0x60;
273 ir->polling = 50; /* ms */
274 break;
275 case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
276 ir_codes = RC_MAP_CINERGY_1400;
277 ir->sampling = 0xeb04; /* address */
278 break;
279 case CX88_BOARD_HAUPPAUGE:
280 case CX88_BOARD_HAUPPAUGE_DVB_T1:
281 case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
282 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
283 case CX88_BOARD_HAUPPAUGE_HVR1100:
284 case CX88_BOARD_HAUPPAUGE_HVR3000:
285 case CX88_BOARD_HAUPPAUGE_HVR4000:
286 case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
287 case CX88_BOARD_PCHDTV_HD3000:
288 case CX88_BOARD_PCHDTV_HD5500:
289 case CX88_BOARD_HAUPPAUGE_IRONLY:
290 ir_codes = RC_MAP_HAUPPAUGE;
291 ir->sampling = 1;
292 break;
293 case CX88_BOARD_WINFAST_DTV2000H:
294 case CX88_BOARD_WINFAST_DTV2000H_J:
295 case CX88_BOARD_WINFAST_DTV1800H:
296 case CX88_BOARD_WINFAST_DTV1800H_XC4000:
297 case CX88_BOARD_WINFAST_DTV2000H_PLUS:
298 ir_codes = RC_MAP_WINFAST;
299 ir->gpio_addr = MO_GP0_IO;
300 ir->mask_keycode = 0x8f8;
301 ir->mask_keyup = 0x100;
302 ir->polling = 50; /* ms */
303 break;
304 case CX88_BOARD_WINFAST2000XP_EXPERT:
305 case CX88_BOARD_WINFAST_DTV1000:
306 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
307 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
308 case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
309 ir_codes = RC_MAP_WINFAST;
310 ir->gpio_addr = MO_GP0_IO;
311 ir->mask_keycode = 0x8f8;
312 ir->mask_keyup = 0x100;
313 ir->polling = 1; /* ms */
314 break;
315 case CX88_BOARD_IODATA_GVBCTV7E:
316 ir_codes = RC_MAP_IODATA_BCTV7E;
317 ir->gpio_addr = MO_GP0_IO;
318 ir->mask_keycode = 0xfd;
319 ir->mask_keydown = 0x02;
320 ir->polling = 5; /* ms */
321 break;
322 case CX88_BOARD_PROLINK_PLAYTVPVR:
323 case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
324 /*
325 * It seems that this hardware is paired with NEC extended
326 * address 0x866b. So, unfortunately, its usage with other
327 * IR's with different address won't work. Still, there are
328 * other IR's from the same manufacturer that works, like the
329 * 002-T mini RC, provided with newer PV hardware
330 */
331 ir_codes = RC_MAP_PIXELVIEW_MK12;
332 ir->gpio_addr = MO_GP1_IO;
333 ir->mask_keyup = 0x80;
334 ir->polling = 10; /* ms */
335 hardware_mask = 0x3f; /* Hardware returns only 6 bits from command part */
336 break;
337 case CX88_BOARD_PROLINK_PV_8000GT:
338 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
339 ir_codes = RC_MAP_PIXELVIEW_NEW;
340 ir->gpio_addr = MO_GP1_IO;
341 ir->mask_keycode = 0x3f;
342 ir->mask_keyup = 0x80;
343 ir->polling = 1; /* ms */
344 break;
345 case CX88_BOARD_KWORLD_LTV883:
346 ir_codes = RC_MAP_PIXELVIEW;
347 ir->gpio_addr = MO_GP1_IO;
348 ir->mask_keycode = 0x1f;
349 ir->mask_keyup = 0x60;
350 ir->polling = 1; /* ms */
351 break;
352 case CX88_BOARD_ADSTECH_DVB_T_PCI:
353 ir_codes = RC_MAP_ADSTECH_DVB_T_PCI;
354 ir->gpio_addr = MO_GP1_IO;
355 ir->mask_keycode = 0xbf;
356 ir->mask_keyup = 0x40;
357 ir->polling = 50; /* ms */
358 break;
359 case CX88_BOARD_MSI_TVANYWHERE_MASTER:
360 ir_codes = RC_MAP_MSI_TVANYWHERE;
361 ir->gpio_addr = MO_GP1_IO;
362 ir->mask_keycode = 0x1f;
363 ir->mask_keyup = 0x40;
364 ir->polling = 1; /* ms */
365 break;
366 case CX88_BOARD_AVERTV_303:
367 case CX88_BOARD_AVERTV_STUDIO_303:
368 ir_codes = RC_MAP_AVERTV_303;
369 ir->gpio_addr = MO_GP2_IO;
370 ir->mask_keycode = 0xfb;
371 ir->mask_keydown = 0x02;
372 ir->polling = 50; /* ms */
373 break;
374 case CX88_BOARD_OMICOM_SS4_PCI:
375 case CX88_BOARD_SATTRADE_ST4200:
376 case CX88_BOARD_TBS_8920:
377 case CX88_BOARD_TBS_8910:
378 case CX88_BOARD_PROF_7300:
379 case CX88_BOARD_PROF_7301:
380 case CX88_BOARD_PROF_6200:
381 ir_codes = RC_MAP_TBS_NEC;
382 ir->sampling = 0xff00; /* address */
383 break;
384 case CX88_BOARD_TEVII_S464:
385 case CX88_BOARD_TEVII_S460:
386 case CX88_BOARD_TEVII_S420:
387 ir_codes = RC_MAP_TEVII_NEC;
388 ir->sampling = 0xff00; /* address */
389 break;
390 case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
391 ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO;
392 ir->sampling = 0xff00; /* address */
393 break;
394 case CX88_BOARD_NORWOOD_MICRO:
395 ir_codes = RC_MAP_NORWOOD;
396 ir->gpio_addr = MO_GP1_IO;
397 ir->mask_keycode = 0x0e;
398 ir->mask_keyup = 0x80;
399 ir->polling = 50; /* ms */
400 break;
401 case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
402 ir_codes = RC_MAP_NPGTECH;
403 ir->gpio_addr = MO_GP0_IO;
404 ir->mask_keycode = 0xfa;
405 ir->polling = 50; /* ms */
406 break;
407 case CX88_BOARD_PINNACLE_PCTV_HD_800i:
408 ir_codes = RC_MAP_PINNACLE_PCTV_HD;
409 ir->sampling = 1;
410 break;
411 case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
412 ir_codes = RC_MAP_POWERCOLOR_REAL_ANGEL;
413 ir->gpio_addr = MO_GP2_IO;
414 ir->mask_keycode = 0x7e;
415 ir->polling = 100; /* ms */
416 break;
417 case CX88_BOARD_TWINHAN_VP1027_DVBS:
418 ir_codes = RC_MAP_TWINHAN_VP1027_DVBS;
419 rc_type = RC_TYPE_NEC;
420 ir->sampling = 0xff00; /* address */
421 break;
422 }
423
424 if (!ir_codes) {
425 err = -ENODEV;
426 goto err_out_free;
427 }
428
429 /*
430 * The usage of mask_keycode were very convenient, due to several
431 * reasons. Among others, the scancode tables were using the scancode
432 * as the index elements. So, the less bits it was used, the smaller
433 * the table were stored. After the input changes, the better is to use
434 * the full scancodes, since it allows replacing the IR remote by
435 * another one. Unfortunately, there are still some hardware, like
436 * Pixelview Ultra Pro, where only part of the scancode is sent via
437 * GPIO. So, there's no way to get the full scancode. Due to that,
438 * hardware_mask were introduced here: it represents those hardware
439 * that has such limits.
440 */
441 if (hardware_mask && !ir->mask_keycode)
442 ir->mask_keycode = hardware_mask;
443
444 /* init input device */
445 snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
446 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
447
448 dev->input_name = ir->name;
449 dev->input_phys = ir->phys;
450 dev->input_id.bustype = BUS_PCI;
451 dev->input_id.version = 1;
452 if (pci->subsystem_vendor) {
453 dev->input_id.vendor = pci->subsystem_vendor;
454 dev->input_id.product = pci->subsystem_device;
455 } else {
456 dev->input_id.vendor = pci->vendor;
457 dev->input_id.product = pci->device;
458 }
459 dev->dev.parent = &pci->dev;
460 dev->map_name = ir_codes;
461 dev->driver_name = MODULE_NAME;
462 dev->priv = core;
463 dev->open = cx88_ir_open;
464 dev->close = cx88_ir_close;
465 dev->scanmask = hardware_mask;
466
467 if (ir->sampling) {
468 dev->driver_type = RC_DRIVER_IR_RAW;
469 dev->timeout = 10 * 1000 * 1000; /* 10 ms */
470 } else {
471 dev->driver_type = RC_DRIVER_SCANCODE;
472 dev->allowed_protos = rc_type;
473 }
474
475 ir->core = core;
476 core->ir = ir;
477
478 /* all done */
479 err = rc_register_device(dev);
480 if (err)
481 goto err_out_free;
482
483 return 0;
484
485err_out_free:
486 rc_free_device(dev);
487 core->ir = NULL;
488 kfree(ir);
489 return err;
490}
491
492int cx88_ir_fini(struct cx88_core *core)
493{
494 struct cx88_IR *ir = core->ir;
495
496 /* skip detach on non attached boards */
497 if (NULL == ir)
498 return 0;
499
500 cx88_ir_stop(core);
501 rc_unregister_device(ir->dev);
502 kfree(ir);
503
504 /* done */
505 core->ir = NULL;
506 return 0;
507}
508
509/* ---------------------------------------------------------------------- */
510
511void cx88_ir_irq(struct cx88_core *core)
512{
513 struct cx88_IR *ir = core->ir;
514 u32 samples;
515 unsigned todo, bits;
516 struct ir_raw_event ev;
517
518 if (!ir || !ir->sampling)
519 return;
520
521 /*
522 * Samples are stored in a 32 bit register, oldest sample in
523 * the msb. A set bit represents space and an unset bit
524 * represents a pulse.
525 */
526 samples = cx_read(MO_SAMPLE_IO);
527
528 if (samples == 0xff && ir->dev->idle)
529 return;
530
531 init_ir_raw_event(&ev);
532 for (todo = 32; todo > 0; todo -= bits) {
533 ev.pulse = samples & 0x80000000 ? false : true;
534 bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
535 ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
536 ir_raw_event_store_with_filter(ir->dev, &ev);
537 samples <<= bits;
538 }
539 ir_raw_event_handle(ir->dev);
540}
541
542static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
543{
544 int flags, code;
545
546 /* poll IR chip */
547 flags = i2c_smbus_read_byte_data(ir->c, 0x10);
548 if (flags < 0) {
549 dprintk("read error\n");
550 return 0;
551 }
552 /* key pressed ? */
553 if (0 == (flags & 0x80))
554 return 0;
555
556 /* read actual key code */
557 code = i2c_smbus_read_byte_data(ir->c, 0x00);
558 if (code < 0) {
559 dprintk("read error\n");
560 return 0;
561 }
562
563 dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
564 code & 0xff, flags & 0xff);
565
566 *ir_key = code & 0xff;
567 *ir_raw = code;
568 return 1;
569}
570
571void cx88_i2c_init_ir(struct cx88_core *core)
572{
573 struct i2c_board_info info;
574 const unsigned short default_addr_list[] = {
575 0x18, 0x6b, 0x71,
576 I2C_CLIENT_END
577 };
578 const unsigned short pvr2000_addr_list[] = {
579 0x18, 0x1a,
580 I2C_CLIENT_END
581 };
582 const unsigned short *addr_list = default_addr_list;
583 const unsigned short *addrp;
584 /* Instantiate the IR receiver device, if present */
585 if (0 != core->i2c_rc)
586 return;
587
588 memset(&info, 0, sizeof(struct i2c_board_info));
589 strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
590
591 switch (core->boardnr) {
592 case CX88_BOARD_LEADTEK_PVR2000:
593 addr_list = pvr2000_addr_list;
594 core->init_data.name = "cx88 Leadtek PVR 2000 remote";
595 core->init_data.type = RC_TYPE_UNKNOWN;
596 core->init_data.get_key = get_key_pvr2000;
597 core->init_data.ir_codes = RC_MAP_EMPTY;
598 break;
599 }
600
601 /*
602 * We can't call i2c_new_probed_device() because it uses
603 * quick writes for probing and at least some RC receiver
604 * devices only reply to reads.
605 * Also, Hauppauge XVR needs to be specified, as address 0x71
606 * conflicts with another remote type used with saa7134
607 */
608 for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
609 info.platform_data = NULL;
610 memset(&core->init_data, 0, sizeof(core->init_data));
611
612 if (*addrp == 0x71) {
613 /* Hauppauge XVR */
614 core->init_data.name = "cx88 Hauppauge XVR remote";
615 core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
616 core->init_data.type = RC_TYPE_RC5;
617 core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
618
619 info.platform_data = &core->init_data;
620 }
621 if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
622 I2C_SMBUS_READ, 0,
623 I2C_SMBUS_QUICK, NULL) >= 0) {
624 info.addr = *addrp;
625 i2c_new_device(&core->i2c_adap, &info);
626 break;
627 }
628 }
629}
630
631/* ---------------------------------------------------------------------- */
632
633MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
634MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
635MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
new file mode 100644
index 000000000000..c04fb618e10b
--- /dev/null
+++ b/drivers/media/pci/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(&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/pci/cx88/cx88-reg.h b/drivers/media/pci/cx88/cx88-reg.h
new file mode 100644
index 000000000000..2ec52d1cdea0
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx88/cx88-tvaudio.c b/drivers/media/pci/cx88/cx88-tvaudio.c
new file mode 100644
index 000000000000..770ec05b5e9b
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
new file mode 100644
index 000000000000..f8f8389c0362
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
new file mode 100644
index 000000000000..a146d50d7795
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -0,0 +1,2075 @@
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/v4l2-event.h>
44#include <media/wm8775.h>
45
46MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
47MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
48MODULE_LICENSE("GPL");
49MODULE_VERSION(CX88_VERSION);
50
51/* ------------------------------------------------------------------ */
52
53static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
54static unsigned int vbi_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
55static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
56
57module_param_array(video_nr, int, NULL, 0444);
58module_param_array(vbi_nr, int, NULL, 0444);
59module_param_array(radio_nr, int, NULL, 0444);
60
61MODULE_PARM_DESC(video_nr,"video device numbers");
62MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
63MODULE_PARM_DESC(radio_nr,"radio device numbers");
64
65static unsigned int video_debug;
66module_param(video_debug,int,0644);
67MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
68
69static unsigned int irq_debug;
70module_param(irq_debug,int,0644);
71MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
72
73static unsigned int vid_limit = 16;
74module_param(vid_limit,int,0644);
75MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
76
77#define dprintk(level,fmt, arg...) if (video_debug >= level) \
78 printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
79
80/* ------------------------------------------------------------------- */
81/* static data */
82
83static const struct cx8800_fmt formats[] = {
84 {
85 .name = "8 bpp, gray",
86 .fourcc = V4L2_PIX_FMT_GREY,
87 .cxformat = ColorFormatY8,
88 .depth = 8,
89 .flags = FORMAT_FLAGS_PACKED,
90 },{
91 .name = "15 bpp RGB, le",
92 .fourcc = V4L2_PIX_FMT_RGB555,
93 .cxformat = ColorFormatRGB15,
94 .depth = 16,
95 .flags = FORMAT_FLAGS_PACKED,
96 },{
97 .name = "15 bpp RGB, be",
98 .fourcc = V4L2_PIX_FMT_RGB555X,
99 .cxformat = ColorFormatRGB15 | ColorFormatBSWAP,
100 .depth = 16,
101 .flags = FORMAT_FLAGS_PACKED,
102 },{
103 .name = "16 bpp RGB, le",
104 .fourcc = V4L2_PIX_FMT_RGB565,
105 .cxformat = ColorFormatRGB16,
106 .depth = 16,
107 .flags = FORMAT_FLAGS_PACKED,
108 },{
109 .name = "16 bpp RGB, be",
110 .fourcc = V4L2_PIX_FMT_RGB565X,
111 .cxformat = ColorFormatRGB16 | ColorFormatBSWAP,
112 .depth = 16,
113 .flags = FORMAT_FLAGS_PACKED,
114 },{
115 .name = "24 bpp RGB, le",
116 .fourcc = V4L2_PIX_FMT_BGR24,
117 .cxformat = ColorFormatRGB24,
118 .depth = 24,
119 .flags = FORMAT_FLAGS_PACKED,
120 },{
121 .name = "32 bpp RGB, le",
122 .fourcc = V4L2_PIX_FMT_BGR32,
123 .cxformat = ColorFormatRGB32,
124 .depth = 32,
125 .flags = FORMAT_FLAGS_PACKED,
126 },{
127 .name = "32 bpp RGB, be",
128 .fourcc = V4L2_PIX_FMT_RGB32,
129 .cxformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP,
130 .depth = 32,
131 .flags = FORMAT_FLAGS_PACKED,
132 },{
133 .name = "4:2:2, packed, YUYV",
134 .fourcc = V4L2_PIX_FMT_YUYV,
135 .cxformat = ColorFormatYUY2,
136 .depth = 16,
137 .flags = FORMAT_FLAGS_PACKED,
138 },{
139 .name = "4:2:2, packed, UYVY",
140 .fourcc = V4L2_PIX_FMT_UYVY,
141 .cxformat = ColorFormatYUY2 | ColorFormatBSWAP,
142 .depth = 16,
143 .flags = FORMAT_FLAGS_PACKED,
144 },
145};
146
147static const struct cx8800_fmt* format_by_fourcc(unsigned int fourcc)
148{
149 unsigned int i;
150
151 for (i = 0; i < ARRAY_SIZE(formats); i++)
152 if (formats[i].fourcc == fourcc)
153 return formats+i;
154 return NULL;
155}
156
157/* ------------------------------------------------------------------- */
158
159struct cx88_ctrl {
160 /* control information */
161 u32 id;
162 s32 minimum;
163 s32 maximum;
164 u32 step;
165 s32 default_value;
166
167 /* control register information */
168 u32 off;
169 u32 reg;
170 u32 sreg;
171 u32 mask;
172 u32 shift;
173};
174
175static const struct cx88_ctrl cx8800_vid_ctls[] = {
176 /* --- video --- */
177 {
178 .id = V4L2_CID_BRIGHTNESS,
179 .minimum = 0x00,
180 .maximum = 0xff,
181 .step = 1,
182 .default_value = 0x7f,
183 .off = 128,
184 .reg = MO_CONTR_BRIGHT,
185 .mask = 0x00ff,
186 .shift = 0,
187 },{
188 .id = V4L2_CID_CONTRAST,
189 .minimum = 0,
190 .maximum = 0xff,
191 .step = 1,
192 .default_value = 0x3f,
193 .off = 0,
194 .reg = MO_CONTR_BRIGHT,
195 .mask = 0xff00,
196 .shift = 8,
197 },{
198 .id = V4L2_CID_HUE,
199 .minimum = 0,
200 .maximum = 0xff,
201 .step = 1,
202 .default_value = 0x7f,
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 .id = V4L2_CID_SATURATION,
212 .minimum = 0,
213 .maximum = 0xff,
214 .step = 1,
215 .default_value = 0x7f,
216 .off = 0,
217 .reg = MO_UV_SATURATION,
218 .mask = 0x00ff,
219 .shift = 0,
220 }, {
221 .id = V4L2_CID_SHARPNESS,
222 .minimum = 0,
223 .maximum = 4,
224 .step = 1,
225 .default_value = 0x0,
226 .off = 0,
227 /* NOTE: the value is converted and written to both even
228 and odd registers in the code */
229 .reg = MO_FILTER_ODD,
230 .mask = 7 << 7,
231 .shift = 7,
232 }, {
233 .id = V4L2_CID_CHROMA_AGC,
234 .minimum = 0,
235 .maximum = 1,
236 .default_value = 0x1,
237 .reg = MO_INPUT_FORMAT,
238 .mask = 1 << 10,
239 .shift = 10,
240 }, {
241 .id = V4L2_CID_COLOR_KILLER,
242 .minimum = 0,
243 .maximum = 1,
244 .default_value = 0x1,
245 .reg = MO_INPUT_FORMAT,
246 .mask = 1 << 9,
247 .shift = 9,
248 }, {
249 .id = V4L2_CID_BAND_STOP_FILTER,
250 .minimum = 0,
251 .maximum = 1,
252 .step = 1,
253 .default_value = 0x0,
254 .off = 0,
255 .reg = MO_HTOTAL,
256 .mask = 3 << 11,
257 .shift = 11,
258 }
259};
260
261static const struct cx88_ctrl cx8800_aud_ctls[] = {
262 {
263 /* --- audio --- */
264 .id = V4L2_CID_AUDIO_MUTE,
265 .minimum = 0,
266 .maximum = 1,
267 .default_value = 1,
268 .reg = AUD_VOL_CTL,
269 .sreg = SHADOW_AUD_VOL_CTL,
270 .mask = (1 << 6),
271 .shift = 6,
272 },{
273 .id = V4L2_CID_AUDIO_VOLUME,
274 .minimum = 0,
275 .maximum = 0x3f,
276 .step = 1,
277 .default_value = 0x3f,
278 .reg = AUD_VOL_CTL,
279 .sreg = SHADOW_AUD_VOL_CTL,
280 .mask = 0x3f,
281 .shift = 0,
282 },{
283 .id = V4L2_CID_AUDIO_BALANCE,
284 .minimum = 0,
285 .maximum = 0x7f,
286 .step = 1,
287 .default_value = 0x40,
288 .reg = AUD_BAL_CTL,
289 .sreg = SHADOW_AUD_BAL_CTL,
290 .mask = 0x7f,
291 .shift = 0,
292 }
293};
294
295enum {
296 CX8800_VID_CTLS = ARRAY_SIZE(cx8800_vid_ctls),
297 CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls),
298};
299
300/* ------------------------------------------------------------------- */
301/* resource management */
302
303static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
304{
305 struct cx88_core *core = dev->core;
306 if (fh->resources & bit)
307 /* have it already allocated */
308 return 1;
309
310 /* is it free? */
311 mutex_lock(&core->lock);
312 if (dev->resources & bit) {
313 /* no, someone else uses it */
314 mutex_unlock(&core->lock);
315 return 0;
316 }
317 /* it's free, grab it */
318 fh->resources |= bit;
319 dev->resources |= bit;
320 dprintk(1,"res: get %d\n",bit);
321 mutex_unlock(&core->lock);
322 return 1;
323}
324
325static
326int res_check(struct cx8800_fh *fh, unsigned int bit)
327{
328 return (fh->resources & bit);
329}
330
331static
332int res_locked(struct cx8800_dev *dev, unsigned int bit)
333{
334 return (dev->resources & bit);
335}
336
337static
338void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
339{
340 struct cx88_core *core = dev->core;
341 BUG_ON((fh->resources & bits) != bits);
342
343 mutex_lock(&core->lock);
344 fh->resources &= ~bits;
345 dev->resources &= ~bits;
346 dprintk(1,"res: put %d\n",bits);
347 mutex_unlock(&core->lock);
348}
349
350/* ------------------------------------------------------------------ */
351
352int cx88_video_mux(struct cx88_core *core, unsigned int input)
353{
354 /* struct cx88_core *core = dev->core; */
355
356 dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
357 input, INPUT(input).vmux,
358 INPUT(input).gpio0,INPUT(input).gpio1,
359 INPUT(input).gpio2,INPUT(input).gpio3);
360 core->input = input;
361 cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14);
362 cx_write(MO_GP3_IO, INPUT(input).gpio3);
363 cx_write(MO_GP0_IO, INPUT(input).gpio0);
364 cx_write(MO_GP1_IO, INPUT(input).gpio1);
365 cx_write(MO_GP2_IO, INPUT(input).gpio2);
366
367 switch (INPUT(input).type) {
368 case CX88_VMUX_SVIDEO:
369 cx_set(MO_AFECFG_IO, 0x00000001);
370 cx_set(MO_INPUT_FORMAT, 0x00010010);
371 cx_set(MO_FILTER_EVEN, 0x00002020);
372 cx_set(MO_FILTER_ODD, 0x00002020);
373 break;
374 default:
375 cx_clear(MO_AFECFG_IO, 0x00000001);
376 cx_clear(MO_INPUT_FORMAT, 0x00010010);
377 cx_clear(MO_FILTER_EVEN, 0x00002020);
378 cx_clear(MO_FILTER_ODD, 0x00002020);
379 break;
380 }
381
382 /* if there are audioroutes defined, we have an external
383 ADC to deal with audio */
384 if (INPUT(input).audioroute) {
385 /* The wm8775 module has the "2" route hardwired into
386 the initialization. Some boards may use different
387 routes for different inputs. HVR-1300 surely does */
388 if (core->board.audio_chip &&
389 core->board.audio_chip == V4L2_IDENT_WM8775) {
390 call_all(core, audio, s_routing,
391 INPUT(input).audioroute, 0, 0);
392 }
393 /* cx2388's C-ADC is connected to the tuner only.
394 When used with S-Video, that ADC is busy dealing with
395 chroma, so an external must be used for baseband audio */
396 if (INPUT(input).type != CX88_VMUX_TELEVISION &&
397 INPUT(input).type != CX88_VMUX_CABLE) {
398 /* "I2S ADC mode" */
399 core->tvaudio = WW_I2SADC;
400 cx88_set_tvaudio(core);
401 } else {
402 /* Normal mode */
403 cx_write(AUD_I2SCNTL, 0x0);
404 cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
405 }
406 }
407
408 return 0;
409}
410EXPORT_SYMBOL(cx88_video_mux);
411
412/* ------------------------------------------------------------------ */
413
414static int start_video_dma(struct cx8800_dev *dev,
415 struct cx88_dmaqueue *q,
416 struct cx88_buffer *buf)
417{
418 struct cx88_core *core = dev->core;
419
420 /* setup fifo + format */
421 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
422 buf->bpl, buf->risc.dma);
423 cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
424 cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
425
426 /* reset counter */
427 cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
428 q->count = 1;
429
430 /* enable irqs */
431 cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
432
433 /* Enables corresponding bits at PCI_INT_STAT:
434 bits 0 to 4: video, audio, transport stream, VIP, Host
435 bit 7: timer
436 bits 8 and 9: DMA complete for: SRC, DST
437 bits 10 and 11: BERR signal asserted for RISC: RD, WR
438 bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
439 */
440 cx_set(MO_VID_INTMSK, 0x0f0011);
441
442 /* enable capture */
443 cx_set(VID_CAPTURE_CONTROL,0x06);
444
445 /* start dma */
446 cx_set(MO_DEV_CNTRL2, (1<<5));
447 cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */
448
449 return 0;
450}
451
452#ifdef CONFIG_PM
453static int stop_video_dma(struct cx8800_dev *dev)
454{
455 struct cx88_core *core = dev->core;
456
457 /* stop dma */
458 cx_clear(MO_VID_DMACNTRL, 0x11);
459
460 /* disable capture */
461 cx_clear(VID_CAPTURE_CONTROL,0x06);
462
463 /* disable irqs */
464 cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
465 cx_clear(MO_VID_INTMSK, 0x0f0011);
466 return 0;
467}
468#endif
469
470static int restart_video_queue(struct cx8800_dev *dev,
471 struct cx88_dmaqueue *q)
472{
473 struct cx88_core *core = dev->core;
474 struct cx88_buffer *buf, *prev;
475
476 if (!list_empty(&q->active)) {
477 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
478 dprintk(2,"restart_queue [%p/%d]: restart dma\n",
479 buf, buf->vb.i);
480 start_video_dma(dev, q, buf);
481 list_for_each_entry(buf, &q->active, vb.queue)
482 buf->count = q->count++;
483 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
484 return 0;
485 }
486
487 prev = NULL;
488 for (;;) {
489 if (list_empty(&q->queued))
490 return 0;
491 buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
492 if (NULL == prev) {
493 list_move_tail(&buf->vb.queue, &q->active);
494 start_video_dma(dev, q, buf);
495 buf->vb.state = VIDEOBUF_ACTIVE;
496 buf->count = q->count++;
497 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
498 dprintk(2,"[%p/%d] restart_queue - first active\n",
499 buf,buf->vb.i);
500
501 } else if (prev->vb.width == buf->vb.width &&
502 prev->vb.height == buf->vb.height &&
503 prev->fmt == buf->fmt) {
504 list_move_tail(&buf->vb.queue, &q->active);
505 buf->vb.state = VIDEOBUF_ACTIVE;
506 buf->count = q->count++;
507 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
508 dprintk(2,"[%p/%d] restart_queue - move to active\n",
509 buf,buf->vb.i);
510 } else {
511 return 0;
512 }
513 prev = buf;
514 }
515}
516
517/* ------------------------------------------------------------------ */
518
519static int
520buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
521{
522 struct cx8800_fh *fh = q->priv_data;
523 struct cx8800_dev *dev = fh->dev;
524
525 *size = dev->fmt->depth * dev->width * dev->height >> 3;
526 if (0 == *count)
527 *count = 32;
528 if (*size * *count > vid_limit * 1024 * 1024)
529 *count = (vid_limit * 1024 * 1024) / *size;
530 return 0;
531}
532
533static int
534buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
535 enum v4l2_field field)
536{
537 struct cx8800_fh *fh = q->priv_data;
538 struct cx8800_dev *dev = fh->dev;
539 struct cx88_core *core = dev->core;
540 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
541 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
542 int rc, init_buffer = 0;
543
544 BUG_ON(NULL == dev->fmt);
545 if (dev->width < 48 || dev->width > norm_maxw(core->tvnorm) ||
546 dev->height < 32 || dev->height > norm_maxh(core->tvnorm))
547 return -EINVAL;
548 buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3;
549 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
550 return -EINVAL;
551
552 if (buf->fmt != dev->fmt ||
553 buf->vb.width != dev->width ||
554 buf->vb.height != dev->height ||
555 buf->vb.field != field) {
556 buf->fmt = dev->fmt;
557 buf->vb.width = dev->width;
558 buf->vb.height = dev->height;
559 buf->vb.field = field;
560 init_buffer = 1;
561 }
562
563 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
564 init_buffer = 1;
565 if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
566 goto fail;
567 }
568
569 if (init_buffer) {
570 buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
571 switch (buf->vb.field) {
572 case V4L2_FIELD_TOP:
573 cx88_risc_buffer(dev->pci, &buf->risc,
574 dma->sglist, 0, UNSET,
575 buf->bpl, 0, buf->vb.height);
576 break;
577 case V4L2_FIELD_BOTTOM:
578 cx88_risc_buffer(dev->pci, &buf->risc,
579 dma->sglist, UNSET, 0,
580 buf->bpl, 0, buf->vb.height);
581 break;
582 case V4L2_FIELD_INTERLACED:
583 cx88_risc_buffer(dev->pci, &buf->risc,
584 dma->sglist, 0, buf->bpl,
585 buf->bpl, buf->bpl,
586 buf->vb.height >> 1);
587 break;
588 case V4L2_FIELD_SEQ_TB:
589 cx88_risc_buffer(dev->pci, &buf->risc,
590 dma->sglist,
591 0, buf->bpl * (buf->vb.height >> 1),
592 buf->bpl, 0,
593 buf->vb.height >> 1);
594 break;
595 case V4L2_FIELD_SEQ_BT:
596 cx88_risc_buffer(dev->pci, &buf->risc,
597 dma->sglist,
598 buf->bpl * (buf->vb.height >> 1), 0,
599 buf->bpl, 0,
600 buf->vb.height >> 1);
601 break;
602 default:
603 BUG();
604 }
605 }
606 dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
607 buf, buf->vb.i,
608 dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
609 (unsigned long)buf->risc.dma);
610
611 buf->vb.state = VIDEOBUF_PREPARED;
612 return 0;
613
614 fail:
615 cx88_free_buffer(q,buf);
616 return rc;
617}
618
619static void
620buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
621{
622 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
623 struct cx88_buffer *prev;
624 struct cx8800_fh *fh = vq->priv_data;
625 struct cx8800_dev *dev = fh->dev;
626 struct cx88_core *core = dev->core;
627 struct cx88_dmaqueue *q = &dev->vidq;
628
629 /* add jump to stopper */
630 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
631 buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
632
633 if (!list_empty(&q->queued)) {
634 list_add_tail(&buf->vb.queue,&q->queued);
635 buf->vb.state = VIDEOBUF_QUEUED;
636 dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
637 buf, buf->vb.i);
638
639 } else if (list_empty(&q->active)) {
640 list_add_tail(&buf->vb.queue,&q->active);
641 start_video_dma(dev, q, buf);
642 buf->vb.state = VIDEOBUF_ACTIVE;
643 buf->count = q->count++;
644 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
645 dprintk(2,"[%p/%d] buffer_queue - first active\n",
646 buf, buf->vb.i);
647
648 } else {
649 prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
650 if (prev->vb.width == buf->vb.width &&
651 prev->vb.height == buf->vb.height &&
652 prev->fmt == buf->fmt) {
653 list_add_tail(&buf->vb.queue,&q->active);
654 buf->vb.state = VIDEOBUF_ACTIVE;
655 buf->count = q->count++;
656 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
657 dprintk(2,"[%p/%d] buffer_queue - append to active\n",
658 buf, buf->vb.i);
659
660 } else {
661 list_add_tail(&buf->vb.queue,&q->queued);
662 buf->vb.state = VIDEOBUF_QUEUED;
663 dprintk(2,"[%p/%d] buffer_queue - first queued\n",
664 buf, buf->vb.i);
665 }
666 }
667}
668
669static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
670{
671 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
672
673 cx88_free_buffer(q,buf);
674}
675
676static const struct videobuf_queue_ops cx8800_video_qops = {
677 .buf_setup = buffer_setup,
678 .buf_prepare = buffer_prepare,
679 .buf_queue = buffer_queue,
680 .buf_release = buffer_release,
681};
682
683/* ------------------------------------------------------------------ */
684
685
686/* ------------------------------------------------------------------ */
687
688static struct videobuf_queue *get_queue(struct file *file)
689{
690 struct video_device *vdev = video_devdata(file);
691 struct cx8800_fh *fh = file->private_data;
692
693 switch (vdev->vfl_type) {
694 case VFL_TYPE_GRABBER:
695 return &fh->vidq;
696 case VFL_TYPE_VBI:
697 return &fh->vbiq;
698 default:
699 BUG();
700 return NULL;
701 }
702}
703
704static int get_resource(struct file *file)
705{
706 struct video_device *vdev = video_devdata(file);
707
708 switch (vdev->vfl_type) {
709 case VFL_TYPE_GRABBER:
710 return RESOURCE_VIDEO;
711 case VFL_TYPE_VBI:
712 return RESOURCE_VBI;
713 default:
714 BUG();
715 return 0;
716 }
717}
718
719static int video_open(struct file *file)
720{
721 struct video_device *vdev = video_devdata(file);
722 struct cx8800_dev *dev = video_drvdata(file);
723 struct cx88_core *core = dev->core;
724 struct cx8800_fh *fh;
725 enum v4l2_buf_type type = 0;
726 int radio = 0;
727
728 switch (vdev->vfl_type) {
729 case VFL_TYPE_GRABBER:
730 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
731 break;
732 case VFL_TYPE_VBI:
733 type = V4L2_BUF_TYPE_VBI_CAPTURE;
734 break;
735 case VFL_TYPE_RADIO:
736 radio = 1;
737 break;
738 }
739
740 dprintk(1, "open dev=%s radio=%d type=%s\n",
741 video_device_node_name(vdev), radio, v4l2_type_names[type]);
742
743 /* allocate + initialize per filehandle data */
744 fh = kzalloc(sizeof(*fh),GFP_KERNEL);
745 if (unlikely(!fh))
746 return -ENOMEM;
747
748 v4l2_fh_init(&fh->fh, vdev);
749 file->private_data = fh;
750 fh->dev = dev;
751
752 mutex_lock(&core->lock);
753
754 videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
755 &dev->pci->dev, &dev->slock,
756 V4L2_BUF_TYPE_VIDEO_CAPTURE,
757 V4L2_FIELD_INTERLACED,
758 sizeof(struct cx88_buffer),
759 fh, NULL);
760 videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
761 &dev->pci->dev, &dev->slock,
762 V4L2_BUF_TYPE_VBI_CAPTURE,
763 V4L2_FIELD_SEQ_TB,
764 sizeof(struct cx88_buffer),
765 fh, NULL);
766
767 if (vdev->vfl_type == VFL_TYPE_RADIO) {
768 dprintk(1,"video_open: setting radio device\n");
769 cx_write(MO_GP3_IO, core->board.radio.gpio3);
770 cx_write(MO_GP0_IO, core->board.radio.gpio0);
771 cx_write(MO_GP1_IO, core->board.radio.gpio1);
772 cx_write(MO_GP2_IO, core->board.radio.gpio2);
773 if (core->board.radio.audioroute) {
774 if(core->board.audio_chip &&
775 core->board.audio_chip == V4L2_IDENT_WM8775) {
776 call_all(core, audio, s_routing,
777 core->board.radio.audioroute, 0, 0);
778 }
779 /* "I2S ADC mode" */
780 core->tvaudio = WW_I2SADC;
781 cx88_set_tvaudio(core);
782 } else {
783 /* FM Mode */
784 core->tvaudio = WW_FM;
785 cx88_set_tvaudio(core);
786 cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
787 }
788 call_all(core, tuner, s_radio);
789 }
790
791 core->users++;
792 mutex_unlock(&core->lock);
793 v4l2_fh_add(&fh->fh);
794
795 return 0;
796}
797
798static ssize_t
799video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
800{
801 struct video_device *vdev = video_devdata(file);
802 struct cx8800_fh *fh = file->private_data;
803
804 switch (vdev->vfl_type) {
805 case VFL_TYPE_GRABBER:
806 if (res_locked(fh->dev,RESOURCE_VIDEO))
807 return -EBUSY;
808 return videobuf_read_one(&fh->vidq, data, count, ppos,
809 file->f_flags & O_NONBLOCK);
810 case VFL_TYPE_VBI:
811 if (!res_get(fh->dev,fh,RESOURCE_VBI))
812 return -EBUSY;
813 return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
814 file->f_flags & O_NONBLOCK);
815 default:
816 BUG();
817 return 0;
818 }
819}
820
821static unsigned int
822video_poll(struct file *file, struct poll_table_struct *wait)
823{
824 struct video_device *vdev = video_devdata(file);
825 struct cx8800_fh *fh = file->private_data;
826 struct cx88_buffer *buf;
827 unsigned int rc = v4l2_ctrl_poll(file, wait);
828
829 if (vdev->vfl_type == VFL_TYPE_VBI) {
830 if (!res_get(fh->dev,fh,RESOURCE_VBI))
831 return rc | POLLERR;
832 return rc | videobuf_poll_stream(file, &fh->vbiq, wait);
833 }
834 mutex_lock(&fh->vidq.vb_lock);
835 if (res_check(fh,RESOURCE_VIDEO)) {
836 /* streaming capture */
837 if (list_empty(&fh->vidq.stream))
838 goto done;
839 buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
840 } else {
841 /* read() capture */
842 buf = (struct cx88_buffer*)fh->vidq.read_buf;
843 if (NULL == buf)
844 goto done;
845 }
846 poll_wait(file, &buf->vb.done, wait);
847 if (buf->vb.state == VIDEOBUF_DONE ||
848 buf->vb.state == VIDEOBUF_ERROR)
849 rc |= POLLIN|POLLRDNORM;
850done:
851 mutex_unlock(&fh->vidq.vb_lock);
852 return rc;
853}
854
855static int video_release(struct file *file)
856{
857 struct cx8800_fh *fh = file->private_data;
858 struct cx8800_dev *dev = fh->dev;
859
860 /* turn off overlay */
861 if (res_check(fh, RESOURCE_OVERLAY)) {
862 /* FIXME */
863 res_free(dev,fh,RESOURCE_OVERLAY);
864 }
865
866 /* stop video capture */
867 if (res_check(fh, RESOURCE_VIDEO)) {
868 videobuf_queue_cancel(&fh->vidq);
869 res_free(dev,fh,RESOURCE_VIDEO);
870 }
871 if (fh->vidq.read_buf) {
872 buffer_release(&fh->vidq,fh->vidq.read_buf);
873 kfree(fh->vidq.read_buf);
874 }
875
876 /* stop vbi capture */
877 if (res_check(fh, RESOURCE_VBI)) {
878 videobuf_stop(&fh->vbiq);
879 res_free(dev,fh,RESOURCE_VBI);
880 }
881
882 videobuf_mmap_free(&fh->vidq);
883 videobuf_mmap_free(&fh->vbiq);
884
885 mutex_lock(&dev->core->lock);
886 v4l2_fh_del(&fh->fh);
887 v4l2_fh_exit(&fh->fh);
888 file->private_data = NULL;
889 kfree(fh);
890
891 dev->core->users--;
892 if (!dev->core->users)
893 call_all(dev->core, core, s_power, 0);
894 mutex_unlock(&dev->core->lock);
895
896 return 0;
897}
898
899static int
900video_mmap(struct file *file, struct vm_area_struct * vma)
901{
902 return videobuf_mmap_mapper(get_queue(file), vma);
903}
904
905/* ------------------------------------------------------------------ */
906/* VIDEO CTRL IOCTLS */
907
908static int cx8800_s_vid_ctrl(struct v4l2_ctrl *ctrl)
909{
910 struct cx88_core *core =
911 container_of(ctrl->handler, struct cx88_core, video_hdl);
912 const struct cx88_ctrl *cc = ctrl->priv;
913 u32 value, mask;
914
915 mask = cc->mask;
916 switch (ctrl->id) {
917 case V4L2_CID_SATURATION:
918 /* special v_sat handling */
919
920 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
921
922 if (core->tvnorm & V4L2_STD_SECAM) {
923 /* For SECAM, both U and V sat should be equal */
924 value = value << 8 | value;
925 } else {
926 /* Keeps U Saturation proportional to V Sat */
927 value = (value * 0x5a) / 0x7f << 8 | value;
928 }
929 mask = 0xffff;
930 break;
931 case V4L2_CID_SHARPNESS:
932 /* 0b000, 0b100, 0b101, 0b110, or 0b111 */
933 value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7));
934 /* needs to be set for both fields */
935 cx_andor(MO_FILTER_EVEN, mask, value);
936 break;
937 case V4L2_CID_CHROMA_AGC:
938 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
939 break;
940 default:
941 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
942 break;
943 }
944 dprintk(1, "set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
945 ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
946 mask, cc->sreg ? " [shadowed]" : "");
947 if (cc->sreg)
948 cx_sandor(cc->sreg, cc->reg, mask, value);
949 else
950 cx_andor(cc->reg, mask, value);
951 return 0;
952}
953
954static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl)
955{
956 struct cx88_core *core =
957 container_of(ctrl->handler, struct cx88_core, audio_hdl);
958 const struct cx88_ctrl *cc = ctrl->priv;
959 u32 value,mask;
960
961 /* Pass changes onto any WM8775 */
962 if (core->board.audio_chip == V4L2_IDENT_WM8775) {
963 switch (ctrl->id) {
964 case V4L2_CID_AUDIO_MUTE:
965 wm8775_s_ctrl(core, ctrl->id, ctrl->val);
966 break;
967 case V4L2_CID_AUDIO_VOLUME:
968 wm8775_s_ctrl(core, ctrl->id, (ctrl->val) ?
969 (0x90 + ctrl->val) << 8 : 0);
970 break;
971 case V4L2_CID_AUDIO_BALANCE:
972 wm8775_s_ctrl(core, ctrl->id, ctrl->val << 9);
973 break;
974 default:
975 break;
976 }
977 }
978
979 mask = cc->mask;
980 switch (ctrl->id) {
981 case V4L2_CID_AUDIO_BALANCE:
982 value = (ctrl->val < 0x40) ? (0x7f - ctrl->val) : (ctrl->val - 0x40);
983 break;
984 case V4L2_CID_AUDIO_VOLUME:
985 value = 0x3f - (ctrl->val & 0x3f);
986 break;
987 default:
988 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
989 break;
990 }
991 dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
992 ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
993 mask, cc->sreg ? " [shadowed]" : "");
994 if (cc->sreg)
995 cx_sandor(cc->sreg, cc->reg, mask, value);
996 else
997 cx_andor(cc->reg, mask, value);
998 return 0;
999}
1000
1001/* ------------------------------------------------------------------ */
1002/* VIDEO IOCTLS */
1003
1004static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1005 struct v4l2_format *f)
1006{
1007 struct cx8800_fh *fh = priv;
1008 struct cx8800_dev *dev = fh->dev;
1009
1010 f->fmt.pix.width = dev->width;
1011 f->fmt.pix.height = dev->height;
1012 f->fmt.pix.field = fh->vidq.field;
1013 f->fmt.pix.pixelformat = dev->fmt->fourcc;
1014 f->fmt.pix.bytesperline =
1015 (f->fmt.pix.width * dev->fmt->depth) >> 3;
1016 f->fmt.pix.sizeimage =
1017 f->fmt.pix.height * f->fmt.pix.bytesperline;
1018 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1019 return 0;
1020}
1021
1022static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1023 struct v4l2_format *f)
1024{
1025 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1026 const struct cx8800_fmt *fmt;
1027 enum v4l2_field field;
1028 unsigned int maxw, maxh;
1029
1030 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1031 if (NULL == fmt)
1032 return -EINVAL;
1033
1034 field = f->fmt.pix.field;
1035 maxw = norm_maxw(core->tvnorm);
1036 maxh = norm_maxh(core->tvnorm);
1037
1038 if (V4L2_FIELD_ANY == field) {
1039 field = (f->fmt.pix.height > maxh/2)
1040 ? V4L2_FIELD_INTERLACED
1041 : V4L2_FIELD_BOTTOM;
1042 }
1043
1044 switch (field) {
1045 case V4L2_FIELD_TOP:
1046 case V4L2_FIELD_BOTTOM:
1047 maxh = maxh / 2;
1048 break;
1049 case V4L2_FIELD_INTERLACED:
1050 break;
1051 default:
1052 return -EINVAL;
1053 }
1054
1055 f->fmt.pix.field = field;
1056 v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
1057 &f->fmt.pix.height, 32, maxh, 0, 0);
1058 f->fmt.pix.bytesperline =
1059 (f->fmt.pix.width * fmt->depth) >> 3;
1060 f->fmt.pix.sizeimage =
1061 f->fmt.pix.height * f->fmt.pix.bytesperline;
1062
1063 return 0;
1064}
1065
1066static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1067 struct v4l2_format *f)
1068{
1069 struct cx8800_fh *fh = priv;
1070 struct cx8800_dev *dev = fh->dev;
1071 int err = vidioc_try_fmt_vid_cap (file,priv,f);
1072
1073 if (0 != err)
1074 return err;
1075 dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1076 dev->width = f->fmt.pix.width;
1077 dev->height = f->fmt.pix.height;
1078 fh->vidq.field = f->fmt.pix.field;
1079 return 0;
1080}
1081
1082void cx88_querycap(struct file *file, struct cx88_core *core,
1083 struct v4l2_capability *cap)
1084{
1085 struct video_device *vdev = video_devdata(file);
1086
1087 strlcpy(cap->card, core->board.name, sizeof(cap->card));
1088 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
1089 if (UNSET != core->board.tuner_type)
1090 cap->device_caps |= V4L2_CAP_TUNER;
1091 switch (vdev->vfl_type) {
1092 case VFL_TYPE_RADIO:
1093 cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
1094 break;
1095 case VFL_TYPE_GRABBER:
1096 cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
1097 break;
1098 case VFL_TYPE_VBI:
1099 cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
1100 break;
1101 }
1102 cap->capabilities = cap->device_caps | V4L2_CAP_VIDEO_CAPTURE |
1103 V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS;
1104 if (core->board.radio.type == CX88_RADIO)
1105 cap->capabilities |= V4L2_CAP_RADIO;
1106}
1107EXPORT_SYMBOL(cx88_querycap);
1108
1109static int vidioc_querycap(struct file *file, void *priv,
1110 struct v4l2_capability *cap)
1111{
1112 struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev;
1113 struct cx88_core *core = dev->core;
1114
1115 strcpy(cap->driver, "cx8800");
1116 sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
1117 cx88_querycap(file, core, cap);
1118 return 0;
1119}
1120
1121static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
1122 struct v4l2_fmtdesc *f)
1123{
1124 if (unlikely(f->index >= ARRAY_SIZE(formats)))
1125 return -EINVAL;
1126
1127 strlcpy(f->description,formats[f->index].name,sizeof(f->description));
1128 f->pixelformat = formats[f->index].fourcc;
1129
1130 return 0;
1131}
1132
1133static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
1134{
1135 return videobuf_reqbufs(get_queue(file), p);
1136}
1137
1138static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
1139{
1140 return videobuf_querybuf(get_queue(file), p);
1141}
1142
1143static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
1144{
1145 return videobuf_qbuf(get_queue(file), p);
1146}
1147
1148static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
1149{
1150 return videobuf_dqbuf(get_queue(file), p,
1151 file->f_flags & O_NONBLOCK);
1152}
1153
1154static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
1155{
1156 struct video_device *vdev = video_devdata(file);
1157 struct cx8800_fh *fh = priv;
1158 struct cx8800_dev *dev = fh->dev;
1159
1160 if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
1161 (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
1162 return -EINVAL;
1163
1164 if (unlikely(!res_get(dev, fh, get_resource(file))))
1165 return -EBUSY;
1166 return videobuf_streamon(get_queue(file));
1167}
1168
1169static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
1170{
1171 struct video_device *vdev = video_devdata(file);
1172 struct cx8800_fh *fh = priv;
1173 struct cx8800_dev *dev = fh->dev;
1174 int err, res;
1175
1176 if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
1177 (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
1178 return -EINVAL;
1179
1180 res = get_resource(file);
1181 err = videobuf_streamoff(get_queue(file));
1182 if (err < 0)
1183 return err;
1184 res_free(dev,fh,res);
1185 return 0;
1186}
1187
1188static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
1189{
1190 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1191
1192 *tvnorm = core->tvnorm;
1193 return 0;
1194}
1195
1196static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms)
1197{
1198 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1199
1200 mutex_lock(&core->lock);
1201 cx88_set_tvnorm(core,*tvnorms);
1202 mutex_unlock(&core->lock);
1203
1204 return 0;
1205}
1206
1207/* only one input in this sample driver */
1208int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i)
1209{
1210 static const char * const iname[] = {
1211 [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
1212 [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
1213 [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
1214 [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
1215 [ CX88_VMUX_SVIDEO ] = "S-Video",
1216 [ CX88_VMUX_TELEVISION ] = "Television",
1217 [ CX88_VMUX_CABLE ] = "Cable TV",
1218 [ CX88_VMUX_DVB ] = "DVB",
1219 [ CX88_VMUX_DEBUG ] = "for debug only",
1220 };
1221 unsigned int n = i->index;
1222
1223 if (n >= 4)
1224 return -EINVAL;
1225 if (0 == INPUT(n).type)
1226 return -EINVAL;
1227 i->type = V4L2_INPUT_TYPE_CAMERA;
1228 strcpy(i->name,iname[INPUT(n).type]);
1229 if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||
1230 (CX88_VMUX_CABLE == INPUT(n).type)) {
1231 i->type = V4L2_INPUT_TYPE_TUNER;
1232 }
1233 i->std = CX88_NORMS;
1234 return 0;
1235}
1236EXPORT_SYMBOL(cx88_enum_input);
1237
1238static int vidioc_enum_input (struct file *file, void *priv,
1239 struct v4l2_input *i)
1240{
1241 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1242 return cx88_enum_input (core,i);
1243}
1244
1245static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
1246{
1247 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1248
1249 *i = core->input;
1250 return 0;
1251}
1252
1253static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
1254{
1255 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1256
1257 if (i >= 4)
1258 return -EINVAL;
1259 if (0 == INPUT(i).type)
1260 return -EINVAL;
1261
1262 mutex_lock(&core->lock);
1263 cx88_newstation(core);
1264 cx88_video_mux(core,i);
1265 mutex_unlock(&core->lock);
1266 return 0;
1267}
1268
1269static int vidioc_g_tuner (struct file *file, void *priv,
1270 struct v4l2_tuner *t)
1271{
1272 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1273 u32 reg;
1274
1275 if (unlikely(UNSET == core->board.tuner_type))
1276 return -EINVAL;
1277 if (0 != t->index)
1278 return -EINVAL;
1279
1280 strcpy(t->name, "Television");
1281 t->capability = V4L2_TUNER_CAP_NORM;
1282 t->rangehigh = 0xffffffffUL;
1283 call_all(core, tuner, g_tuner, t);
1284
1285 cx88_get_stereo(core ,t);
1286 reg = cx_read(MO_DEVICE_STATUS);
1287 t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
1288 return 0;
1289}
1290
1291static int vidioc_s_tuner (struct file *file, void *priv,
1292 struct v4l2_tuner *t)
1293{
1294 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1295
1296 if (UNSET == core->board.tuner_type)
1297 return -EINVAL;
1298 if (0 != t->index)
1299 return -EINVAL;
1300
1301 cx88_set_stereo(core, t->audmode, 1);
1302 return 0;
1303}
1304
1305static int vidioc_g_frequency (struct file *file, void *priv,
1306 struct v4l2_frequency *f)
1307{
1308 struct cx8800_fh *fh = priv;
1309 struct cx88_core *core = fh->dev->core;
1310
1311 if (unlikely(UNSET == core->board.tuner_type))
1312 return -EINVAL;
1313 if (f->tuner)
1314 return -EINVAL;
1315
1316 f->frequency = core->freq;
1317
1318 call_all(core, tuner, g_frequency, f);
1319
1320 return 0;
1321}
1322
1323int cx88_set_freq (struct cx88_core *core,
1324 struct v4l2_frequency *f)
1325{
1326 if (unlikely(UNSET == core->board.tuner_type))
1327 return -EINVAL;
1328 if (unlikely(f->tuner != 0))
1329 return -EINVAL;
1330
1331 mutex_lock(&core->lock);
1332 cx88_newstation(core);
1333 call_all(core, tuner, s_frequency, f);
1334 call_all(core, tuner, g_frequency, f);
1335 core->freq = f->frequency;
1336
1337 /* When changing channels it is required to reset TVAUDIO */
1338 msleep (10);
1339 cx88_set_tvaudio(core);
1340
1341 mutex_unlock(&core->lock);
1342
1343 return 0;
1344}
1345EXPORT_SYMBOL(cx88_set_freq);
1346
1347static int vidioc_s_frequency (struct file *file, void *priv,
1348 struct v4l2_frequency *f)
1349{
1350 struct cx8800_fh *fh = priv;
1351 struct cx88_core *core = fh->dev->core;
1352
1353 return cx88_set_freq(core, f);
1354}
1355
1356static int vidioc_g_chip_ident(struct file *file, void *priv,
1357 struct v4l2_dbg_chip_ident *chip)
1358{
1359 if (!v4l2_chip_match_host(&chip->match))
1360 return -EINVAL;
1361 chip->revision = 0;
1362 chip->ident = V4L2_IDENT_UNKNOWN;
1363 return 0;
1364}
1365
1366#ifdef CONFIG_VIDEO_ADV_DEBUG
1367static int vidioc_g_register (struct file *file, void *fh,
1368 struct v4l2_dbg_register *reg)
1369{
1370 struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
1371
1372 if (!v4l2_chip_match_host(&reg->match))
1373 return -EINVAL;
1374 /* cx2388x has a 24-bit register space */
1375 reg->val = cx_read(reg->reg & 0xffffff);
1376 reg->size = 4;
1377 return 0;
1378}
1379
1380static int vidioc_s_register (struct file *file, void *fh,
1381 struct v4l2_dbg_register *reg)
1382{
1383 struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
1384
1385 if (!v4l2_chip_match_host(&reg->match))
1386 return -EINVAL;
1387 cx_write(reg->reg & 0xffffff, reg->val);
1388 return 0;
1389}
1390#endif
1391
1392/* ----------------------------------------------------------- */
1393/* RADIO ESPECIFIC IOCTLS */
1394/* ----------------------------------------------------------- */
1395
1396static int radio_g_tuner (struct file *file, void *priv,
1397 struct v4l2_tuner *t)
1398{
1399 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1400
1401 if (unlikely(t->index > 0))
1402 return -EINVAL;
1403
1404 strcpy(t->name, "Radio");
1405
1406 call_all(core, tuner, g_tuner, t);
1407 return 0;
1408}
1409
1410/* FIXME: Should add a standard for radio */
1411
1412static int radio_s_tuner (struct file *file, void *priv,
1413 struct v4l2_tuner *t)
1414{
1415 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1416
1417 if (0 != t->index)
1418 return -EINVAL;
1419 if (t->audmode > V4L2_TUNER_MODE_STEREO)
1420 t->audmode = V4L2_TUNER_MODE_STEREO;
1421
1422 call_all(core, tuner, s_tuner, t);
1423
1424 return 0;
1425}
1426
1427/* ----------------------------------------------------------- */
1428
1429static void cx8800_vid_timeout(unsigned long data)
1430{
1431 struct cx8800_dev *dev = (struct cx8800_dev*)data;
1432 struct cx88_core *core = dev->core;
1433 struct cx88_dmaqueue *q = &dev->vidq;
1434 struct cx88_buffer *buf;
1435 unsigned long flags;
1436
1437 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
1438
1439 cx_clear(MO_VID_DMACNTRL, 0x11);
1440 cx_clear(VID_CAPTURE_CONTROL, 0x06);
1441
1442 spin_lock_irqsave(&dev->slock,flags);
1443 while (!list_empty(&q->active)) {
1444 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
1445 list_del(&buf->vb.queue);
1446 buf->vb.state = VIDEOBUF_ERROR;
1447 wake_up(&buf->vb.done);
1448 printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
1449 buf, buf->vb.i, (unsigned long)buf->risc.dma);
1450 }
1451 restart_video_queue(dev,q);
1452 spin_unlock_irqrestore(&dev->slock,flags);
1453}
1454
1455static const char *cx88_vid_irqs[32] = {
1456 "y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
1457 "y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
1458 "y_oflow", "u_oflow", "v_oflow", "vbi_oflow",
1459 "y_sync", "u_sync", "v_sync", "vbi_sync",
1460 "opc_err", "par_err", "rip_err", "pci_abort",
1461};
1462
1463static void cx8800_vid_irq(struct cx8800_dev *dev)
1464{
1465 struct cx88_core *core = dev->core;
1466 u32 status, mask, count;
1467
1468 status = cx_read(MO_VID_INTSTAT);
1469 mask = cx_read(MO_VID_INTMSK);
1470 if (0 == (status & mask))
1471 return;
1472 cx_write(MO_VID_INTSTAT, status);
1473 if (irq_debug || (status & mask & ~0xff))
1474 cx88_print_irqbits(core->name, "irq vid",
1475 cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs),
1476 status, mask);
1477
1478 /* risc op code error */
1479 if (status & (1 << 16)) {
1480 printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
1481 cx_clear(MO_VID_DMACNTRL, 0x11);
1482 cx_clear(VID_CAPTURE_CONTROL, 0x06);
1483 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
1484 }
1485
1486 /* risc1 y */
1487 if (status & 0x01) {
1488 spin_lock(&dev->slock);
1489 count = cx_read(MO_VIDY_GPCNT);
1490 cx88_wakeup(core, &dev->vidq, count);
1491 spin_unlock(&dev->slock);
1492 }
1493
1494 /* risc1 vbi */
1495 if (status & 0x08) {
1496 spin_lock(&dev->slock);
1497 count = cx_read(MO_VBI_GPCNT);
1498 cx88_wakeup(core, &dev->vbiq, count);
1499 spin_unlock(&dev->slock);
1500 }
1501
1502 /* risc2 y */
1503 if (status & 0x10) {
1504 dprintk(2,"stopper video\n");
1505 spin_lock(&dev->slock);
1506 restart_video_queue(dev,&dev->vidq);
1507 spin_unlock(&dev->slock);
1508 }
1509
1510 /* risc2 vbi */
1511 if (status & 0x80) {
1512 dprintk(2,"stopper vbi\n");
1513 spin_lock(&dev->slock);
1514 cx8800_restart_vbi_queue(dev,&dev->vbiq);
1515 spin_unlock(&dev->slock);
1516 }
1517}
1518
1519static irqreturn_t cx8800_irq(int irq, void *dev_id)
1520{
1521 struct cx8800_dev *dev = dev_id;
1522 struct cx88_core *core = dev->core;
1523 u32 status;
1524 int loop, handled = 0;
1525
1526 for (loop = 0; loop < 10; loop++) {
1527 status = cx_read(MO_PCI_INTSTAT) &
1528 (core->pci_irqmask | PCI_INT_VIDINT);
1529 if (0 == status)
1530 goto out;
1531 cx_write(MO_PCI_INTSTAT, status);
1532 handled = 1;
1533
1534 if (status & core->pci_irqmask)
1535 cx88_core_irq(core,status);
1536 if (status & PCI_INT_VIDINT)
1537 cx8800_vid_irq(dev);
1538 };
1539 if (10 == loop) {
1540 printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
1541 core->name);
1542 cx_write(MO_PCI_INTMSK,0);
1543 }
1544
1545 out:
1546 return IRQ_RETVAL(handled);
1547}
1548
1549/* ----------------------------------------------------------- */
1550/* exported stuff */
1551
1552static const struct v4l2_file_operations video_fops =
1553{
1554 .owner = THIS_MODULE,
1555 .open = video_open,
1556 .release = video_release,
1557 .read = video_read,
1558 .poll = video_poll,
1559 .mmap = video_mmap,
1560 .unlocked_ioctl = video_ioctl2,
1561};
1562
1563static const struct v4l2_ioctl_ops video_ioctl_ops = {
1564 .vidioc_querycap = vidioc_querycap,
1565 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1566 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1567 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1568 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1569 .vidioc_reqbufs = vidioc_reqbufs,
1570 .vidioc_querybuf = vidioc_querybuf,
1571 .vidioc_qbuf = vidioc_qbuf,
1572 .vidioc_dqbuf = vidioc_dqbuf,
1573 .vidioc_g_std = vidioc_g_std,
1574 .vidioc_s_std = vidioc_s_std,
1575 .vidioc_enum_input = vidioc_enum_input,
1576 .vidioc_g_input = vidioc_g_input,
1577 .vidioc_s_input = vidioc_s_input,
1578 .vidioc_streamon = vidioc_streamon,
1579 .vidioc_streamoff = vidioc_streamoff,
1580 .vidioc_g_tuner = vidioc_g_tuner,
1581 .vidioc_s_tuner = vidioc_s_tuner,
1582 .vidioc_g_frequency = vidioc_g_frequency,
1583 .vidioc_s_frequency = vidioc_s_frequency,
1584 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1585 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1586 .vidioc_g_chip_ident = vidioc_g_chip_ident,
1587#ifdef CONFIG_VIDEO_ADV_DEBUG
1588 .vidioc_g_register = vidioc_g_register,
1589 .vidioc_s_register = vidioc_s_register,
1590#endif
1591};
1592
1593static const struct video_device cx8800_video_template = {
1594 .name = "cx8800-video",
1595 .fops = &video_fops,
1596 .ioctl_ops = &video_ioctl_ops,
1597 .tvnorms = CX88_NORMS,
1598};
1599
1600static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
1601 .vidioc_querycap = vidioc_querycap,
1602 .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt,
1603 .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt,
1604 .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt,
1605 .vidioc_reqbufs = vidioc_reqbufs,
1606 .vidioc_querybuf = vidioc_querybuf,
1607 .vidioc_qbuf = vidioc_qbuf,
1608 .vidioc_dqbuf = vidioc_dqbuf,
1609 .vidioc_g_std = vidioc_g_std,
1610 .vidioc_s_std = vidioc_s_std,
1611 .vidioc_enum_input = vidioc_enum_input,
1612 .vidioc_g_input = vidioc_g_input,
1613 .vidioc_s_input = vidioc_s_input,
1614 .vidioc_streamon = vidioc_streamon,
1615 .vidioc_streamoff = vidioc_streamoff,
1616 .vidioc_g_tuner = vidioc_g_tuner,
1617 .vidioc_s_tuner = vidioc_s_tuner,
1618 .vidioc_g_frequency = vidioc_g_frequency,
1619 .vidioc_s_frequency = vidioc_s_frequency,
1620 .vidioc_g_chip_ident = vidioc_g_chip_ident,
1621#ifdef CONFIG_VIDEO_ADV_DEBUG
1622 .vidioc_g_register = vidioc_g_register,
1623 .vidioc_s_register = vidioc_s_register,
1624#endif
1625};
1626
1627static const struct video_device cx8800_vbi_template = {
1628 .name = "cx8800-vbi",
1629 .fops = &video_fops,
1630 .ioctl_ops = &vbi_ioctl_ops,
1631 .tvnorms = CX88_NORMS,
1632};
1633
1634static const struct v4l2_file_operations radio_fops =
1635{
1636 .owner = THIS_MODULE,
1637 .open = video_open,
1638 .poll = v4l2_ctrl_poll,
1639 .release = video_release,
1640 .unlocked_ioctl = video_ioctl2,
1641};
1642
1643static const struct v4l2_ioctl_ops radio_ioctl_ops = {
1644 .vidioc_querycap = vidioc_querycap,
1645 .vidioc_g_tuner = radio_g_tuner,
1646 .vidioc_s_tuner = radio_s_tuner,
1647 .vidioc_g_frequency = vidioc_g_frequency,
1648 .vidioc_s_frequency = vidioc_s_frequency,
1649 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1650 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1651 .vidioc_g_chip_ident = vidioc_g_chip_ident,
1652#ifdef CONFIG_VIDEO_ADV_DEBUG
1653 .vidioc_g_register = vidioc_g_register,
1654 .vidioc_s_register = vidioc_s_register,
1655#endif
1656};
1657
1658static const struct video_device cx8800_radio_template = {
1659 .name = "cx8800-radio",
1660 .fops = &radio_fops,
1661 .ioctl_ops = &radio_ioctl_ops,
1662};
1663
1664static const struct v4l2_ctrl_ops cx8800_ctrl_vid_ops = {
1665 .s_ctrl = cx8800_s_vid_ctrl,
1666};
1667
1668static const struct v4l2_ctrl_ops cx8800_ctrl_aud_ops = {
1669 .s_ctrl = cx8800_s_aud_ctrl,
1670};
1671
1672/* ----------------------------------------------------------- */
1673
1674static void cx8800_unregister_video(struct cx8800_dev *dev)
1675{
1676 if (dev->radio_dev) {
1677 if (video_is_registered(dev->radio_dev))
1678 video_unregister_device(dev->radio_dev);
1679 else
1680 video_device_release(dev->radio_dev);
1681 dev->radio_dev = NULL;
1682 }
1683 if (dev->vbi_dev) {
1684 if (video_is_registered(dev->vbi_dev))
1685 video_unregister_device(dev->vbi_dev);
1686 else
1687 video_device_release(dev->vbi_dev);
1688 dev->vbi_dev = NULL;
1689 }
1690 if (dev->video_dev) {
1691 if (video_is_registered(dev->video_dev))
1692 video_unregister_device(dev->video_dev);
1693 else
1694 video_device_release(dev->video_dev);
1695 dev->video_dev = NULL;
1696 }
1697}
1698
1699static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
1700 const struct pci_device_id *pci_id)
1701{
1702 struct cx8800_dev *dev;
1703 struct cx88_core *core;
1704 int err;
1705 int i;
1706
1707 dev = kzalloc(sizeof(*dev),GFP_KERNEL);
1708 if (NULL == dev)
1709 return -ENOMEM;
1710
1711 /* pci init */
1712 dev->pci = pci_dev;
1713 if (pci_enable_device(pci_dev)) {
1714 err = -EIO;
1715 goto fail_free;
1716 }
1717 core = cx88_core_get(dev->pci);
1718 if (NULL == core) {
1719 err = -EINVAL;
1720 goto fail_free;
1721 }
1722 dev->core = core;
1723
1724 /* print pci info */
1725 dev->pci_rev = pci_dev->revision;
1726 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
1727 printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
1728 "latency: %d, mmio: 0x%llx\n", core->name,
1729 pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
1730 dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
1731
1732 pci_set_master(pci_dev);
1733 if (!pci_dma_supported(pci_dev,DMA_BIT_MASK(32))) {
1734 printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
1735 err = -EIO;
1736 goto fail_core;
1737 }
1738
1739 /* initialize driver struct */
1740 spin_lock_init(&dev->slock);
1741 core->tvnorm = V4L2_STD_NTSC_M;
1742
1743 /* init video dma queues */
1744 INIT_LIST_HEAD(&dev->vidq.active);
1745 INIT_LIST_HEAD(&dev->vidq.queued);
1746 dev->vidq.timeout.function = cx8800_vid_timeout;
1747 dev->vidq.timeout.data = (unsigned long)dev;
1748 init_timer(&dev->vidq.timeout);
1749 cx88_risc_stopper(dev->pci,&dev->vidq.stopper,
1750 MO_VID_DMACNTRL,0x11,0x00);
1751
1752 /* init vbi dma queues */
1753 INIT_LIST_HEAD(&dev->vbiq.active);
1754 INIT_LIST_HEAD(&dev->vbiq.queued);
1755 dev->vbiq.timeout.function = cx8800_vbi_timeout;
1756 dev->vbiq.timeout.data = (unsigned long)dev;
1757 init_timer(&dev->vbiq.timeout);
1758 cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,
1759 MO_VID_DMACNTRL,0x88,0x00);
1760
1761 /* get irq */
1762 err = request_irq(pci_dev->irq, cx8800_irq,
1763 IRQF_SHARED | IRQF_DISABLED, core->name, dev);
1764 if (err < 0) {
1765 printk(KERN_ERR "%s/0: can't get IRQ %d\n",
1766 core->name,pci_dev->irq);
1767 goto fail_core;
1768 }
1769 cx_set(MO_PCI_INTMSK, core->pci_irqmask);
1770
1771 for (i = 0; i < CX8800_AUD_CTLS; i++) {
1772 const struct cx88_ctrl *cc = &cx8800_aud_ctls[i];
1773 struct v4l2_ctrl *vc;
1774
1775 vc = v4l2_ctrl_new_std(&core->audio_hdl, &cx8800_ctrl_aud_ops,
1776 cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
1777 if (vc == NULL) {
1778 err = core->audio_hdl.error;
1779 goto fail_core;
1780 }
1781 vc->priv = (void *)cc;
1782 }
1783
1784 for (i = 0; i < CX8800_VID_CTLS; i++) {
1785 const struct cx88_ctrl *cc = &cx8800_vid_ctls[i];
1786 struct v4l2_ctrl *vc;
1787
1788 vc = v4l2_ctrl_new_std(&core->video_hdl, &cx8800_ctrl_vid_ops,
1789 cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
1790 if (vc == NULL) {
1791 err = core->video_hdl.error;
1792 goto fail_core;
1793 }
1794 vc->priv = (void *)cc;
1795 if (vc->id == V4L2_CID_CHROMA_AGC)
1796 core->chroma_agc = vc;
1797 }
1798 v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl, NULL);
1799
1800 /* load and configure helper modules */
1801
1802 if (core->board.audio_chip == V4L2_IDENT_WM8775) {
1803 struct i2c_board_info wm8775_info = {
1804 .type = "wm8775",
1805 .addr = 0x36 >> 1,
1806 .platform_data = &core->wm8775_data,
1807 };
1808 struct v4l2_subdev *sd;
1809
1810 if (core->boardnr == CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1)
1811 core->wm8775_data.is_nova_s = true;
1812 else
1813 core->wm8775_data.is_nova_s = false;
1814
1815 sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap,
1816 &wm8775_info, NULL);
1817 if (sd != NULL) {
1818 core->sd_wm8775 = sd;
1819 sd->grp_id = WM8775_GID;
1820 }
1821 }
1822
1823 if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
1824 /* This probes for a tda9874 as is used on some
1825 Pixelview Ultra boards. */
1826 v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
1827 "tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
1828 }
1829
1830 switch (core->boardnr) {
1831 case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
1832 case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: {
1833 static const struct i2c_board_info rtc_info = {
1834 I2C_BOARD_INFO("isl1208", 0x6f)
1835 };
1836
1837 request_module("rtc-isl1208");
1838 core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info);
1839 }
1840 /* break intentionally omitted */
1841 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
1842 request_module("ir-kbd-i2c");
1843 }
1844
1845 /* Sets device info at pci_dev */
1846 pci_set_drvdata(pci_dev, dev);
1847
1848 dev->width = 320;
1849 dev->height = 240;
1850 dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
1851
1852 /* initial device configuration */
1853 mutex_lock(&core->lock);
1854 cx88_set_tvnorm(core, core->tvnorm);
1855 v4l2_ctrl_handler_setup(&core->video_hdl);
1856 v4l2_ctrl_handler_setup(&core->audio_hdl);
1857 cx88_video_mux(core, 0);
1858
1859 /* register v4l devices */
1860 dev->video_dev = cx88_vdev_init(core,dev->pci,
1861 &cx8800_video_template,"video");
1862 video_set_drvdata(dev->video_dev, dev);
1863 dev->video_dev->ctrl_handler = &core->video_hdl;
1864 err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
1865 video_nr[core->nr]);
1866 if (err < 0) {
1867 printk(KERN_ERR "%s/0: can't register video device\n",
1868 core->name);
1869 goto fail_unreg;
1870 }
1871 printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
1872 core->name, video_device_node_name(dev->video_dev));
1873
1874 dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
1875 video_set_drvdata(dev->vbi_dev, dev);
1876 err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
1877 vbi_nr[core->nr]);
1878 if (err < 0) {
1879 printk(KERN_ERR "%s/0: can't register vbi device\n",
1880 core->name);
1881 goto fail_unreg;
1882 }
1883 printk(KERN_INFO "%s/0: registered device %s\n",
1884 core->name, video_device_node_name(dev->vbi_dev));
1885
1886 if (core->board.radio.type == CX88_RADIO) {
1887 dev->radio_dev = cx88_vdev_init(core,dev->pci,
1888 &cx8800_radio_template,"radio");
1889 video_set_drvdata(dev->radio_dev, dev);
1890 dev->radio_dev->ctrl_handler = &core->audio_hdl;
1891 err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
1892 radio_nr[core->nr]);
1893 if (err < 0) {
1894 printk(KERN_ERR "%s/0: can't register radio device\n",
1895 core->name);
1896 goto fail_unreg;
1897 }
1898 printk(KERN_INFO "%s/0: registered device %s\n",
1899 core->name, video_device_node_name(dev->radio_dev));
1900 }
1901
1902 /* start tvaudio thread */
1903 if (core->board.tuner_type != TUNER_ABSENT) {
1904 core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
1905 if (IS_ERR(core->kthread)) {
1906 err = PTR_ERR(core->kthread);
1907 printk(KERN_ERR "%s/0: failed to create cx88 audio thread, err=%d\n",
1908 core->name, err);
1909 }
1910 }
1911 mutex_unlock(&core->lock);
1912
1913 return 0;
1914
1915fail_unreg:
1916 cx8800_unregister_video(dev);
1917 free_irq(pci_dev->irq, dev);
1918 mutex_unlock(&core->lock);
1919fail_core:
1920 cx88_core_put(core,dev->pci);
1921fail_free:
1922 kfree(dev);
1923 return err;
1924}
1925
1926static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
1927{
1928 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
1929 struct cx88_core *core = dev->core;
1930
1931 /* stop thread */
1932 if (core->kthread) {
1933 kthread_stop(core->kthread);
1934 core->kthread = NULL;
1935 }
1936
1937 if (core->ir)
1938 cx88_ir_stop(core);
1939
1940 cx88_shutdown(core); /* FIXME */
1941 pci_disable_device(pci_dev);
1942
1943 /* unregister stuff */
1944
1945 free_irq(pci_dev->irq, dev);
1946 cx8800_unregister_video(dev);
1947 pci_set_drvdata(pci_dev, NULL);
1948
1949 /* free memory */
1950 btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
1951 cx88_core_put(core,dev->pci);
1952 kfree(dev);
1953}
1954
1955#ifdef CONFIG_PM
1956static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
1957{
1958 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
1959 struct cx88_core *core = dev->core;
1960
1961 /* stop video+vbi capture */
1962 spin_lock(&dev->slock);
1963 if (!list_empty(&dev->vidq.active)) {
1964 printk("%s/0: suspend video\n", core->name);
1965 stop_video_dma(dev);
1966 del_timer(&dev->vidq.timeout);
1967 }
1968 if (!list_empty(&dev->vbiq.active)) {
1969 printk("%s/0: suspend vbi\n", core->name);
1970 cx8800_stop_vbi_dma(dev);
1971 del_timer(&dev->vbiq.timeout);
1972 }
1973 spin_unlock(&dev->slock);
1974
1975 if (core->ir)
1976 cx88_ir_stop(core);
1977 /* FIXME -- shutdown device */
1978 cx88_shutdown(core);
1979
1980 pci_save_state(pci_dev);
1981 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
1982 pci_disable_device(pci_dev);
1983 dev->state.disabled = 1;
1984 }
1985 return 0;
1986}
1987
1988static int cx8800_resume(struct pci_dev *pci_dev)
1989{
1990 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
1991 struct cx88_core *core = dev->core;
1992 int err;
1993
1994 if (dev->state.disabled) {
1995 err=pci_enable_device(pci_dev);
1996 if (err) {
1997 printk(KERN_ERR "%s/0: can't enable device\n",
1998 core->name);
1999 return err;
2000 }
2001
2002 dev->state.disabled = 0;
2003 }
2004 err= pci_set_power_state(pci_dev, PCI_D0);
2005 if (err) {
2006 printk(KERN_ERR "%s/0: can't set power state\n", core->name);
2007 pci_disable_device(pci_dev);
2008 dev->state.disabled = 1;
2009
2010 return err;
2011 }
2012 pci_restore_state(pci_dev);
2013
2014 /* FIXME: re-initialize hardware */
2015 cx88_reset(core);
2016 if (core->ir)
2017 cx88_ir_start(core);
2018
2019 cx_set(MO_PCI_INTMSK, core->pci_irqmask);
2020
2021 /* restart video+vbi capture */
2022 spin_lock(&dev->slock);
2023 if (!list_empty(&dev->vidq.active)) {
2024 printk("%s/0: resume video\n", core->name);
2025 restart_video_queue(dev,&dev->vidq);
2026 }
2027 if (!list_empty(&dev->vbiq.active)) {
2028 printk("%s/0: resume vbi\n", core->name);
2029 cx8800_restart_vbi_queue(dev,&dev->vbiq);
2030 }
2031 spin_unlock(&dev->slock);
2032
2033 return 0;
2034}
2035#endif
2036
2037/* ----------------------------------------------------------- */
2038
2039static const struct pci_device_id cx8800_pci_tbl[] = {
2040 {
2041 .vendor = 0x14f1,
2042 .device = 0x8800,
2043 .subvendor = PCI_ANY_ID,
2044 .subdevice = PCI_ANY_ID,
2045 },{
2046 /* --- end of list --- */
2047 }
2048};
2049MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl);
2050
2051static struct pci_driver cx8800_pci_driver = {
2052 .name = "cx8800",
2053 .id_table = cx8800_pci_tbl,
2054 .probe = cx8800_initdev,
2055 .remove = __devexit_p(cx8800_finidev),
2056#ifdef CONFIG_PM
2057 .suspend = cx8800_suspend,
2058 .resume = cx8800_resume,
2059#endif
2060};
2061
2062static int __init cx8800_init(void)
2063{
2064 printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %s loaded\n",
2065 CX88_VERSION);
2066 return pci_register_driver(&cx8800_pci_driver);
2067}
2068
2069static void __exit cx8800_fini(void)
2070{
2071 pci_unregister_driver(&cx8800_pci_driver);
2072}
2073
2074module_init(cx8800_init);
2075module_exit(cx8800_fini);
diff --git a/drivers/media/pci/cx88/cx88-vp3054-i2c.c b/drivers/media/pci/cx88/cx88-vp3054-i2c.c
new file mode 100644
index 000000000000..d77f8ecab9d7
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx88/cx88-vp3054-i2c.h b/drivers/media/pci/cx88/cx88-vp3054-i2c.h
new file mode 100644
index 000000000000..be99c931dc3e
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
new file mode 100644
index 000000000000..44ffc8b3d45f
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88.h
@@ -0,0 +1,748 @@
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/v4l2-fh.h>
30#include <media/tuner.h>
31#include <media/tveeprom.h>
32#include <media/videobuf-dma-sg.h>
33#include <media/v4l2-chip-ident.h>
34#include <media/cx2341x.h>
35#include <media/videobuf-dvb.h>
36#include <media/ir-kbd-i2c.h>
37#include <media/wm8775.h>
38
39#include "btcx-risc.h"
40#include "cx88-reg.h"
41#include "tuner-xc2028.h"
42
43#include <linux/mutex.h>
44
45#define CX88_VERSION "0.0.9"
46
47#define UNSET (-1U)
48
49#define CX88_MAXBOARDS 8
50
51/* Max number of inputs by card */
52#define MAX_CX88_INPUT 8
53
54/* ----------------------------------------------------------- */
55/* defines and enums */
56
57/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM/LC */
58#define CX88_NORMS (V4L2_STD_ALL \
59 & ~V4L2_STD_PAL_H \
60 & ~V4L2_STD_NTSC_M_KR \
61 & ~V4L2_STD_SECAM_LC)
62
63#define FORMAT_FLAGS_PACKED 0x01
64#define FORMAT_FLAGS_PLANAR 0x02
65
66#define VBI_LINE_COUNT 17
67#define VBI_LINE_LENGTH 2048
68
69#define AUD_RDS_LINES 4
70
71/* need "shadow" registers for some write-only ones ... */
72#define SHADOW_AUD_VOL_CTL 1
73#define SHADOW_AUD_BAL_CTL 2
74#define SHADOW_MAX 3
75
76/* FM Radio deemphasis type */
77enum cx88_deemph_type {
78 FM_NO_DEEMPH = 0,
79 FM_DEEMPH_50,
80 FM_DEEMPH_75
81};
82
83enum cx88_board_type {
84 CX88_BOARD_NONE = 0,
85 CX88_MPEG_DVB,
86 CX88_MPEG_BLACKBIRD
87};
88
89enum cx8802_board_access {
90 CX8802_DRVCTL_SHARED = 1,
91 CX8802_DRVCTL_EXCLUSIVE = 2,
92};
93
94/* ----------------------------------------------------------- */
95/* tv norms */
96
97static unsigned int inline norm_maxw(v4l2_std_id norm)
98{
99 return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
100}
101
102
103static unsigned int inline norm_maxh(v4l2_std_id norm)
104{
105 return (norm & V4L2_STD_625_50) ? 576 : 480;
106}
107
108/* ----------------------------------------------------------- */
109/* static data */
110
111struct cx8800_fmt {
112 const char *name;
113 u32 fourcc; /* v4l2 format id */
114 int depth;
115 int flags;
116 u32 cxformat;
117};
118
119/* ----------------------------------------------------------- */
120/* SRAM memory management data (see cx88-core.c) */
121
122#define SRAM_CH21 0 /* video */
123#define SRAM_CH22 1
124#define SRAM_CH23 2
125#define SRAM_CH24 3 /* vbi */
126#define SRAM_CH25 4 /* audio */
127#define SRAM_CH26 5
128#define SRAM_CH28 6 /* mpeg */
129#define SRAM_CH27 7 /* audio rds */
130/* more */
131
132struct sram_channel {
133 const char *name;
134 u32 cmds_start;
135 u32 ctrl_start;
136 u32 cdt;
137 u32 fifo_start;
138 u32 fifo_size;
139 u32 ptr1_reg;
140 u32 ptr2_reg;
141 u32 cnt1_reg;
142 u32 cnt2_reg;
143};
144extern const struct sram_channel cx88_sram_channels[];
145
146/* ----------------------------------------------------------- */
147/* card configuration */
148
149#define CX88_BOARD_NOAUTO UNSET
150#define CX88_BOARD_UNKNOWN 0
151#define CX88_BOARD_HAUPPAUGE 1
152#define CX88_BOARD_GDI 2
153#define CX88_BOARD_PIXELVIEW 3
154#define CX88_BOARD_ATI_WONDER_PRO 4
155#define CX88_BOARD_WINFAST2000XP_EXPERT 5
156#define CX88_BOARD_AVERTV_STUDIO_303 6
157#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7
158#define CX88_BOARD_WINFAST_DV2000 8
159#define CX88_BOARD_LEADTEK_PVR2000 9
160#define CX88_BOARD_IODATA_GVVCP3PCI 10
161#define CX88_BOARD_PROLINK_PLAYTVPVR 11
162#define CX88_BOARD_ASUS_PVR_416 12
163#define CX88_BOARD_MSI_TVANYWHERE 13
164#define CX88_BOARD_KWORLD_DVB_T 14
165#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1 15
166#define CX88_BOARD_KWORLD_LTV883 16
167#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q 17
168#define CX88_BOARD_HAUPPAUGE_DVB_T1 18
169#define CX88_BOARD_CONEXANT_DVB_T1 19
170#define CX88_BOARD_PROVIDEO_PV259 20
171#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21
172#define CX88_BOARD_PCHDTV_HD3000 22
173#define CX88_BOARD_DNTV_LIVE_DVB_T 23
174#define CX88_BOARD_HAUPPAUGE_ROSLYN 24
175#define CX88_BOARD_DIGITALLOGIC_MEC 25
176#define CX88_BOARD_IODATA_GVBCTV7E 26
177#define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27
178#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28
179#define CX88_BOARD_ADSTECH_DVB_T_PCI 29
180#define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30
181#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31
182#define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32
183#define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33
184#define CX88_BOARD_ATI_HDTVWONDER 34
185#define CX88_BOARD_WINFAST_DTV1000 35
186#define CX88_BOARD_AVERTV_303 36
187#define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1 37
188#define CX88_BOARD_HAUPPAUGE_NOVASE2_S1 38
189#define CX88_BOARD_KWORLD_DVBS_100 39
190#define CX88_BOARD_HAUPPAUGE_HVR1100 40
191#define CX88_BOARD_HAUPPAUGE_HVR1100LP 41
192#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO 42
193#define CX88_BOARD_KWORLD_DVB_T_CX22702 43
194#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
195#define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45
196#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46
197#define CX88_BOARD_PCHDTV_HD5500 47
198#define CX88_BOARD_KWORLD_MCE200_DELUXE 48
199#define CX88_BOARD_PIXELVIEW_PLAYTV_P7000 49
200#define CX88_BOARD_NPGTECH_REALTV_TOP10FM 50
201#define CX88_BOARD_WINFAST_DTV2000H 51
202#define CX88_BOARD_GENIATECH_DVBS 52
203#define CX88_BOARD_HAUPPAUGE_HVR3000 53
204#define CX88_BOARD_NORWOOD_MICRO 54
205#define CX88_BOARD_TE_DTV_250_OEM_SWANN 55
206#define CX88_BOARD_HAUPPAUGE_HVR1300 56
207#define CX88_BOARD_ADSTECH_PTV_390 57
208#define CX88_BOARD_PINNACLE_PCTV_HD_800i 58
209#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59
210#define CX88_BOARD_PINNACLE_HYBRID_PCTV 60
211#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61
212#define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62
213#define CX88_BOARD_GENIATECH_X8000_MT 63
214#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64
215#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65
216#define CX88_BOARD_PROLINK_PV_8000GT 66
217#define CX88_BOARD_KWORLD_ATSC_120 67
218#define CX88_BOARD_HAUPPAUGE_HVR4000 68
219#define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69
220#define CX88_BOARD_TEVII_S460 70
221#define CX88_BOARD_OMICOM_SS4_PCI 71
222#define CX88_BOARD_TBS_8920 72
223#define CX88_BOARD_TEVII_S420 73
224#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74
225#define CX88_BOARD_PROF_7300 75
226#define CX88_BOARD_SATTRADE_ST4200 76
227#define CX88_BOARD_TBS_8910 77
228#define CX88_BOARD_PROF_6200 78
229#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79
230#define CX88_BOARD_HAUPPAUGE_IRONLY 80
231#define CX88_BOARD_WINFAST_DTV1800H 81
232#define CX88_BOARD_WINFAST_DTV2000H_J 82
233#define CX88_BOARD_PROF_7301 83
234#define CX88_BOARD_SAMSUNG_SMT_7020 84
235#define CX88_BOARD_TWINHAN_VP1027_DVBS 85
236#define CX88_BOARD_TEVII_S464 86
237#define CX88_BOARD_WINFAST_DTV2000H_PLUS 87
238#define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
239#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89
240#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90
241
242enum cx88_itype {
243 CX88_VMUX_COMPOSITE1 = 1,
244 CX88_VMUX_COMPOSITE2,
245 CX88_VMUX_COMPOSITE3,
246 CX88_VMUX_COMPOSITE4,
247 CX88_VMUX_SVIDEO,
248 CX88_VMUX_TELEVISION,
249 CX88_VMUX_CABLE,
250 CX88_VMUX_DVB,
251 CX88_VMUX_DEBUG,
252 CX88_RADIO,
253};
254
255struct cx88_input {
256 enum cx88_itype type;
257 u32 gpio0, gpio1, gpio2, gpio3;
258 unsigned int vmux:2;
259 unsigned int audioroute:4;
260};
261
262struct cx88_board {
263 const char *name;
264 unsigned int tuner_type;
265 unsigned int radio_type;
266 unsigned char tuner_addr;
267 unsigned char radio_addr;
268 int tda9887_conf;
269 struct cx88_input input[MAX_CX88_INPUT];
270 struct cx88_input radio;
271 enum cx88_board_type mpeg;
272 unsigned int audio_chip;
273 int num_frontends;
274
275 /* Used for I2S devices */
276 int i2sinputcntl;
277};
278
279struct cx88_subid {
280 u16 subvendor;
281 u16 subdevice;
282 u32 card;
283};
284
285enum cx88_tvaudio {
286 WW_NONE = 1,
287 WW_BTSC,
288 WW_BG,
289 WW_DK,
290 WW_I,
291 WW_L,
292 WW_EIAJ,
293 WW_I2SPT,
294 WW_FM,
295 WW_I2SADC,
296 WW_M
297};
298
299#define INPUT(nr) (core->board.input[nr])
300
301/* ----------------------------------------------------------- */
302/* device / file handle status */
303
304#define RESOURCE_OVERLAY 1
305#define RESOURCE_VIDEO 2
306#define RESOURCE_VBI 4
307
308#define BUFFER_TIMEOUT msecs_to_jiffies(2000)
309
310/* buffer for one video frame */
311struct cx88_buffer {
312 /* common v4l buffer stuff -- must be first */
313 struct videobuf_buffer vb;
314
315 /* cx88 specific */
316 unsigned int bpl;
317 struct btcx_riscmem risc;
318 const struct cx8800_fmt *fmt;
319 u32 count;
320};
321
322struct cx88_dmaqueue {
323 struct list_head active;
324 struct list_head queued;
325 struct timer_list timeout;
326 struct btcx_riscmem stopper;
327 u32 count;
328};
329
330struct cx88_core {
331 struct list_head devlist;
332 atomic_t refcount;
333
334 /* board name */
335 int nr;
336 char name[32];
337
338 /* pci stuff */
339 int pci_bus;
340 int pci_slot;
341 u32 __iomem *lmmio;
342 u8 __iomem *bmmio;
343 u32 shadow[SHADOW_MAX];
344 int pci_irqmask;
345
346 /* i2c i/o */
347 struct i2c_adapter i2c_adap;
348 struct i2c_algo_bit_data i2c_algo;
349 struct i2c_client i2c_client;
350 u32 i2c_state, i2c_rc;
351
352 /* config info -- analog */
353 struct v4l2_device v4l2_dev;
354 struct v4l2_ctrl_handler video_hdl;
355 struct v4l2_ctrl *chroma_agc;
356 struct v4l2_ctrl_handler audio_hdl;
357 struct v4l2_subdev *sd_wm8775;
358 struct i2c_client *i2c_rtc;
359 unsigned int boardnr;
360 struct cx88_board board;
361
362 /* Supported V4L _STD_ tuner formats */
363 unsigned int tuner_formats;
364
365 /* config info -- dvb */
366#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
367 int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
368#endif
369 void (*gate_ctrl)(struct cx88_core *core, int open);
370
371 /* state info */
372 struct task_struct *kthread;
373 v4l2_std_id tvnorm;
374 enum cx88_tvaudio tvaudio;
375 u32 audiomode_manual;
376 u32 audiomode_current;
377 u32 input;
378 u32 last_analog_input;
379 u32 astat;
380 u32 use_nicam;
381 unsigned long last_change;
382
383 /* IR remote control state */
384 struct cx88_IR *ir;
385
386 /* I2C remote data */
387 struct IR_i2c_init_data init_data;
388 struct wm8775_platform_data wm8775_data;
389
390 struct mutex lock;
391 /* various v4l controls */
392 u32 freq;
393 int users;
394 int mpeg_users;
395
396 /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
397 struct cx8802_dev *dvbdev;
398 enum cx88_board_type active_type_id;
399 int active_ref;
400 int active_fe_id;
401};
402
403static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
404{
405 return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
406}
407
408#define call_hw(core, grpid, o, f, args...) \
409 do { \
410 if (!core->i2c_rc) { \
411 if (core->gate_ctrl) \
412 core->gate_ctrl(core, 1); \
413 v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
414 if (core->gate_ctrl) \
415 core->gate_ctrl(core, 0); \
416 } \
417 } while (0)
418
419#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
420
421#define WM8775_GID (1 << 0)
422
423#define wm8775_s_ctrl(core, id, val) \
424 do { \
425 struct v4l2_ctrl *ctrl_ = \
426 v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \
427 if (ctrl_ && !core->i2c_rc) { \
428 if (core->gate_ctrl) \
429 core->gate_ctrl(core, 1); \
430 v4l2_ctrl_s_ctrl(ctrl_, val); \
431 if (core->gate_ctrl) \
432 core->gate_ctrl(core, 0); \
433 } \
434 } while (0)
435
436#define wm8775_g_ctrl(core, id) \
437 ({ \
438 struct v4l2_ctrl *ctrl_ = \
439 v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \
440 s32 val = 0; \
441 if (ctrl_ && !core->i2c_rc) { \
442 if (core->gate_ctrl) \
443 core->gate_ctrl(core, 1); \
444 val = v4l2_ctrl_g_ctrl(ctrl_); \
445 if (core->gate_ctrl) \
446 core->gate_ctrl(core, 0); \
447 } \
448 val; \
449 })
450
451struct cx8800_dev;
452struct cx8802_dev;
453
454/* ----------------------------------------------------------- */
455/* function 0: video stuff */
456
457struct cx8800_fh {
458 struct v4l2_fh fh;
459 struct cx8800_dev *dev;
460 unsigned int resources;
461
462 /* video capture */
463 struct videobuf_queue vidq;
464
465 /* vbi capture */
466 struct videobuf_queue vbiq;
467};
468
469struct cx8800_suspend_state {
470 int disabled;
471};
472
473struct cx8800_dev {
474 struct cx88_core *core;
475 spinlock_t slock;
476
477 /* various device info */
478 unsigned int resources;
479 struct video_device *video_dev;
480 struct video_device *vbi_dev;
481 struct video_device *radio_dev;
482
483 /* pci i/o */
484 struct pci_dev *pci;
485 unsigned char pci_rev,pci_lat;
486
487 const struct cx8800_fmt *fmt;
488 unsigned int width, height;
489
490 /* capture queues */
491 struct cx88_dmaqueue vidq;
492 struct cx88_dmaqueue vbiq;
493
494 /* various v4l controls */
495
496 /* other global state info */
497 struct cx8800_suspend_state state;
498};
499
500/* ----------------------------------------------------------- */
501/* function 1: audio/alsa stuff */
502/* =============> moved to cx88-alsa.c <====================== */
503
504
505/* ----------------------------------------------------------- */
506/* function 2: mpeg stuff */
507
508struct cx8802_fh {
509 struct v4l2_fh fh;
510 struct cx8802_dev *dev;
511 struct videobuf_queue mpegq;
512};
513
514struct cx8802_suspend_state {
515 int disabled;
516};
517
518struct cx8802_driver {
519 struct cx88_core *core;
520
521 /* List of drivers attached to device */
522 struct list_head drvlist;
523
524 /* Type of driver and access required */
525 enum cx88_board_type type_id;
526 enum cx8802_board_access hw_access;
527
528 /* MPEG 8802 internal only */
529 int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
530 int (*resume)(struct pci_dev *pci_dev);
531
532 /* Callers to the following functions must hold core->lock */
533
534 /* MPEG 8802 -> mini driver - Driver probe and configuration */
535 int (*probe)(struct cx8802_driver *drv);
536 int (*remove)(struct cx8802_driver *drv);
537
538 /* MPEG 8802 -> mini driver - Access for hardware control */
539 int (*advise_acquire)(struct cx8802_driver *drv);
540 int (*advise_release)(struct cx8802_driver *drv);
541
542 /* MPEG 8802 <- mini driver - Access for hardware control */
543 int (*request_acquire)(struct cx8802_driver *drv);
544 int (*request_release)(struct cx8802_driver *drv);
545};
546
547struct cx8802_dev {
548 struct cx88_core *core;
549 spinlock_t slock;
550
551 /* pci i/o */
552 struct pci_dev *pci;
553 unsigned char pci_rev,pci_lat;
554
555 /* dma queues */
556 struct cx88_dmaqueue mpegq;
557 u32 ts_packet_size;
558 u32 ts_packet_count;
559
560 /* other global state info */
561 struct cx8802_suspend_state state;
562
563 /* for blackbird only */
564 struct list_head devlist;
565#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
566 defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
567 struct video_device *mpeg_dev;
568 u32 mailbox;
569 int width;
570 int height;
571 unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
572
573 /* mpeg params */
574 struct cx2341x_handler cxhdl;
575#endif
576
577#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
578 /* for dvb only */
579 struct videobuf_dvb_frontends frontends;
580#endif
581
582#if defined(CONFIG_VIDEO_CX88_VP3054) || \
583 defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
584 /* For VP3045 secondary I2C bus support */
585 struct vp3054_i2c_state *vp3054;
586#endif
587 /* for switching modulation types */
588 unsigned char ts_gen_cntrl;
589
590 /* List of attached drivers; must hold core->lock to access */
591 struct list_head drvlist;
592
593 struct work_struct request_module_wk;
594};
595
596/* ----------------------------------------------------------- */
597
598#define cx_read(reg) readl(core->lmmio + ((reg)>>2))
599#define cx_write(reg,value) writel((value), core->lmmio + ((reg)>>2))
600#define cx_writeb(reg,value) writeb((value), core->bmmio + (reg))
601
602#define cx_andor(reg,mask,value) \
603 writel((readl(core->lmmio+((reg)>>2)) & ~(mask)) |\
604 ((value) & (mask)), core->lmmio+((reg)>>2))
605#define cx_set(reg,bit) cx_andor((reg),(bit),(bit))
606#define cx_clear(reg,bit) cx_andor((reg),(bit),0)
607
608#define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); }
609
610/* shadow registers */
611#define cx_sread(sreg) (core->shadow[sreg])
612#define cx_swrite(sreg,reg,value) \
613 (core->shadow[sreg] = value, \
614 writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
615#define cx_sandor(sreg,reg,mask,value) \
616 (core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | ((value) & (mask)), \
617 writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
618
619/* ----------------------------------------------------------- */
620/* cx88-core.c */
621
622extern void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
623 int len, u32 bits, u32 mask);
624
625extern int cx88_core_irq(struct cx88_core *core, u32 status);
626extern void cx88_wakeup(struct cx88_core *core,
627 struct cx88_dmaqueue *q, u32 count);
628extern void cx88_shutdown(struct cx88_core *core);
629extern int cx88_reset(struct cx88_core *core);
630
631extern int
632cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
633 struct scatterlist *sglist,
634 unsigned int top_offset, unsigned int bottom_offset,
635 unsigned int bpl, unsigned int padding, unsigned int lines);
636extern int
637cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
638 struct scatterlist *sglist, unsigned int bpl,
639 unsigned int lines, unsigned int lpi);
640extern int
641cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
642 u32 reg, u32 mask, u32 value);
643extern void
644cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
645
646extern void cx88_risc_disasm(struct cx88_core *core,
647 struct btcx_riscmem *risc);
648extern int cx88_sram_channel_setup(struct cx88_core *core,
649 const struct sram_channel *ch,
650 unsigned int bpl, u32 risc);
651extern void cx88_sram_channel_dump(struct cx88_core *core,
652 const struct sram_channel *ch);
653
654extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
655 unsigned int height, enum v4l2_field field);
656extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
657
658extern struct video_device *cx88_vdev_init(struct cx88_core *core,
659 struct pci_dev *pci,
660 const struct video_device *template_,
661 const char *type);
662extern struct cx88_core* cx88_core_get(struct pci_dev *pci);
663extern void cx88_core_put(struct cx88_core *core,
664 struct pci_dev *pci);
665
666extern int cx88_start_audio_dma(struct cx88_core *core);
667extern int cx88_stop_audio_dma(struct cx88_core *core);
668
669
670/* ----------------------------------------------------------- */
671/* cx88-vbi.c */
672
673/* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */
674int cx8800_vbi_fmt (struct file *file, void *priv,
675 struct v4l2_format *f);
676
677/*
678int cx8800_start_vbi_dma(struct cx8800_dev *dev,
679 struct cx88_dmaqueue *q,
680 struct cx88_buffer *buf);
681*/
682int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
683int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
684 struct cx88_dmaqueue *q);
685void cx8800_vbi_timeout(unsigned long data);
686
687extern const struct videobuf_queue_ops cx8800_vbi_qops;
688
689/* ----------------------------------------------------------- */
690/* cx88-i2c.c */
691
692extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
693
694
695/* ----------------------------------------------------------- */
696/* cx88-cards.c */
697
698extern int cx88_tuner_callback(void *dev, int component, int command, int arg);
699extern int cx88_get_resources(const struct cx88_core *core,
700 struct pci_dev *pci);
701extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
702extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
703
704/* ----------------------------------------------------------- */
705/* cx88-tvaudio.c */
706
707void cx88_set_tvaudio(struct cx88_core *core);
708void cx88_newstation(struct cx88_core *core);
709void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
710void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
711int cx88_audio_thread(void *data);
712
713int cx8802_register_driver(struct cx8802_driver *drv);
714int cx8802_unregister_driver(struct cx8802_driver *drv);
715
716/* Caller must hold core->lock */
717struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
718
719/* ----------------------------------------------------------- */
720/* cx88-dsp.c */
721
722s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core);
723
724/* ----------------------------------------------------------- */
725/* cx88-input.c */
726
727int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
728int cx88_ir_fini(struct cx88_core *core);
729void cx88_ir_irq(struct cx88_core *core);
730int cx88_ir_start(struct cx88_core *core);
731void cx88_ir_stop(struct cx88_core *core);
732extern void cx88_i2c_init_ir(struct cx88_core *core);
733
734/* ----------------------------------------------------------- */
735/* cx88-mpeg.c */
736
737int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
738 struct cx88_buffer *buf, enum v4l2_field field);
739void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
740void cx8802_cancel_buffers(struct cx8802_dev *dev);
741
742/* ----------------------------------------------------------- */
743/* cx88-video.c*/
744int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i);
745int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f);
746int cx88_video_mux(struct cx88_core *core, unsigned int input);
747void cx88_querycap(struct file *file, struct cx88_core *core,
748 struct v4l2_capability *cap);