diff options
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/Kconfig | 25 | ||||
-rw-r--r-- | drivers/media/video/cx88/Makefile | 4 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-alsa.c | 848 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 18 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-cards.c | 227 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-core.c | 67 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 215 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-i2c.c | 13 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-input.c | 142 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 5 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-tvaudio.c | 10 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 94 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-vp3054-i2c.c | 173 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-vp3054-i2c.h | 35 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 17 |
15 files changed, 1761 insertions, 132 deletions
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 85ba4106dc79..76fcb4e995c9 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -29,6 +29,21 @@ config VIDEO_CX88_DVB | |||
29 | You must also select one or more DVB/ATSC demodulators. | 29 | You must also select one or more DVB/ATSC demodulators. |
30 | If you are unsure which you need, choose all of them. | 30 | If you are unsure which you need, choose all of them. |
31 | 31 | ||
32 | config VIDEO_CX88_ALSA | ||
33 | tristate "ALSA DMA audio support" | ||
34 | depends on VIDEO_CX88 && SND | ||
35 | select SND_PCM_OSS | ||
36 | ---help--- | ||
37 | This is a video4linux driver for direct (DMA) audio on | ||
38 | Conexant 2388x based TV cards. | ||
39 | It only works with boards with function 01 enabled. | ||
40 | To check if your board supports, use lspci -n. | ||
41 | If supported, you should see 1471:8801 or 1471:8811 | ||
42 | PCI device. | ||
43 | |||
44 | To compile this driver as a module, choose M here: the | ||
45 | module will be called cx88-alsa. | ||
46 | |||
32 | config VIDEO_CX88_DVB_ALL_FRONTENDS | 47 | config VIDEO_CX88_DVB_ALL_FRONTENDS |
33 | bool "Build all supported frontends for cx2388x based TV cards" | 48 | bool "Build all supported frontends for cx2388x based TV cards" |
34 | default y | 49 | default y |
@@ -38,6 +53,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS | |||
38 | select DVB_CX22702 | 53 | select DVB_CX22702 |
39 | select DVB_LGDT330X | 54 | select DVB_LGDT330X |
40 | select DVB_NXT200X | 55 | select DVB_NXT200X |
56 | select DVB_CX24123 | ||
41 | ---help--- | 57 | ---help--- |
42 | This builds cx88-dvb with all currently supported frontend | 58 | This builds cx88-dvb with all currently supported frontend |
43 | demodulators. If you wish to tweak your configuration, and | 59 | demodulators. If you wish to tweak your configuration, and |
@@ -89,3 +105,12 @@ config VIDEO_CX88_DVB_NXT200X | |||
89 | ---help--- | 105 | ---help--- |
90 | This adds ATSC 8VSB and QAM64/256 support for cards based on the | 106 | This adds ATSC 8VSB and QAM64/256 support for cards based on the |
91 | Connexant 2388x chip and the NXT2002/NXT2004 demodulator. | 107 | Connexant 2388x chip and the NXT2002/NXT2004 demodulator. |
108 | |||
109 | config VIDEO_CX88_DVB_CX24123 | ||
110 | bool "Conexant CX24123 DVB-S Support" | ||
111 | default y | ||
112 | depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS | ||
113 | select DVB_CX24123 | ||
114 | ---help--- | ||
115 | This adds DVB-S support for cards based on the | ||
116 | Connexant 2388x chip and the CX24123 demodulator. | ||
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 54401b02b7ce..e4b2134fe567 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile | |||
@@ -4,7 +4,7 @@ cx8800-objs := cx88-video.o cx88-vbi.o | |||
4 | cx8802-objs := cx88-mpeg.o | 4 | cx8802-objs := cx88-mpeg.o |
5 | 5 | ||
6 | obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o | 6 | obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o |
7 | obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o | 7 | obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o |
8 | 8 | ||
9 | EXTRA_CFLAGS += -I$(src)/.. | 9 | EXTRA_CFLAGS += -I$(src)/.. |
10 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core | 10 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core |
@@ -16,5 +16,7 @@ extra-cflags-$(CONFIG_DVB_OR51132) += -DHAVE_OR51132=1 | |||
16 | extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1 | 16 | extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1 |
17 | extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 | 17 | extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 |
18 | extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 | 18 | extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 |
19 | extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1 | ||
20 | extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1 | ||
19 | 21 | ||
20 | EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) | 22 | EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c new file mode 100644 index 000000000000..7695b521eb35 --- /dev/null +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -0,0 +1,848 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Support for audio capture | ||
4 | * PCI function #1 of the cx2388x. | ||
5 | * | ||
6 | * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> | ||
7 | * (c) 2005 Mauro Carvalho Chehab <mchehab@brturbo.com.br> | ||
8 | * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> | ||
9 | * Based on dummy.c by Jaroslav Kysela <perex@suse.cz> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <asm/delay.h> | ||
31 | #include <sound/driver.h> | ||
32 | #include <sound/core.h> | ||
33 | #include <sound/pcm.h> | ||
34 | #include <sound/pcm_params.h> | ||
35 | #include <sound/control.h> | ||
36 | #include <sound/initval.h> | ||
37 | |||
38 | #include "cx88.h" | ||
39 | #include "cx88-reg.h" | ||
40 | |||
41 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | ||
42 | printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg) | ||
43 | |||
44 | #define dprintk_core(level,fmt, arg...) if (debug >= level) \ | ||
45 | printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg) | ||
46 | |||
47 | |||
48 | /**************************************************************************** | ||
49 | Data type declarations - Can be moded to a header file later | ||
50 | ****************************************************************************/ | ||
51 | |||
52 | /* These can be replaced after done */ | ||
53 | #define MIXER_ADDR_LAST MAX_CX88_INPUT | ||
54 | |||
55 | struct cx88_audio_dev { | ||
56 | struct cx88_core *core; | ||
57 | struct cx88_dmaqueue q; | ||
58 | |||
59 | /* pci i/o */ | ||
60 | struct pci_dev *pci; | ||
61 | unsigned char pci_rev,pci_lat; | ||
62 | |||
63 | /* audio controls */ | ||
64 | int irq; | ||
65 | |||
66 | snd_card_t *card; | ||
67 | |||
68 | spinlock_t reg_lock; | ||
69 | |||
70 | unsigned int dma_size; | ||
71 | unsigned int period_size; | ||
72 | unsigned int num_periods; | ||
73 | |||
74 | struct videobuf_dmabuf dma_risc; | ||
75 | |||
76 | int mixer_volume[MIXER_ADDR_LAST+1][2]; | ||
77 | int capture_source[MIXER_ADDR_LAST+1][2]; | ||
78 | |||
79 | long int read_count; | ||
80 | long int read_offset; | ||
81 | |||
82 | struct cx88_buffer *buf; | ||
83 | |||
84 | long opened; | ||
85 | snd_pcm_substream_t *substream; | ||
86 | |||
87 | }; | ||
88 | typedef struct cx88_audio_dev snd_cx88_card_t; | ||
89 | |||
90 | |||
91 | |||
92 | /**************************************************************************** | ||
93 | Module global static vars | ||
94 | ****************************************************************************/ | ||
95 | |||
96 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
97 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | ||
98 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; | ||
99 | static snd_card_t *snd_cx88_cards[SNDRV_CARDS]; | ||
100 | |||
101 | module_param_array(enable, bool, NULL, 0444); | ||
102 | MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); | ||
103 | |||
104 | module_param_array(index, int, NULL, 0444); | ||
105 | MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s)."); | ||
106 | |||
107 | |||
108 | /**************************************************************************** | ||
109 | Module macros | ||
110 | ****************************************************************************/ | ||
111 | |||
112 | MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); | ||
113 | MODULE_AUTHOR("Ricardo Cerqueira"); | ||
114 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@brturbo.com.br>"); | ||
115 | MODULE_LICENSE("GPL"); | ||
116 | MODULE_SUPPORTED_DEVICE("{{Conexant,23881}," | ||
117 | "{{Conexant,23882}," | ||
118 | "{{Conexant,23883}"); | ||
119 | static unsigned int debug = 0; | ||
120 | module_param(debug,int,0644); | ||
121 | MODULE_PARM_DESC(debug,"enable debug messages"); | ||
122 | |||
123 | /**************************************************************************** | ||
124 | Module specific funtions | ||
125 | ****************************************************************************/ | ||
126 | |||
127 | /* | ||
128 | * BOARD Specific: Sets audio DMA | ||
129 | */ | ||
130 | |||
131 | int _cx88_start_audio_dma(snd_cx88_card_t *chip) | ||
132 | { | ||
133 | struct cx88_buffer *buf = chip->buf; | ||
134 | struct cx88_core *core=chip->core; | ||
135 | struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; | ||
136 | |||
137 | |||
138 | dprintk(1, "Starting audio DMA for %i bytes/line and %i (%i) lines at address %08x\n",buf->bpl, chip->num_periods, audio_ch->fifo_size / buf->bpl, audio_ch->fifo_start); | ||
139 | |||
140 | /* setup fifo + format - out channel */ | ||
141 | cx88_sram_channel_setup(chip->core, &cx88_sram_channels[SRAM_CH25], | ||
142 | buf->bpl, buf->risc.dma); | ||
143 | |||
144 | /* sets bpl size */ | ||
145 | cx_write(MO_AUDD_LNGTH, buf->bpl); | ||
146 | |||
147 | /* reset counter */ | ||
148 | cx_write(MO_AUDD_GPCNTRL,GP_COUNT_CONTROL_RESET); | ||
149 | |||
150 | dprintk(1,"Enabling IRQ, setting mask from 0x%x to 0x%x\n",chip->core->pci_irqmask,(chip->core->pci_irqmask | 0x02)); | ||
151 | /* enable irqs */ | ||
152 | cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | 0x02); | ||
153 | |||
154 | |||
155 | /* Enables corresponding bits at AUD_INT_STAT */ | ||
156 | cx_write(MO_AUD_INTMSK, | ||
157 | (1<<16)| | ||
158 | (1<<12)| | ||
159 | (1<<4)| | ||
160 | (1<<0) | ||
161 | ); | ||
162 | |||
163 | /* start dma */ | ||
164 | cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ | ||
165 | cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */ | ||
166 | |||
167 | if (debug) | ||
168 | cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * BOARD Specific: Resets audio DMA | ||
175 | */ | ||
176 | int _cx88_stop_audio_dma(snd_cx88_card_t *chip) | ||
177 | { | ||
178 | struct cx88_core *core=chip->core; | ||
179 | dprintk(1, "Stopping audio DMA\n"); | ||
180 | |||
181 | /* stop dma */ | ||
182 | cx_clear(MO_AUD_DMACNTRL, 0x11); | ||
183 | |||
184 | /* disable irqs */ | ||
185 | cx_clear(MO_PCI_INTMSK, 0x02); | ||
186 | cx_clear(MO_AUD_INTMSK, | ||
187 | (1<<16)| | ||
188 | (1<<12)| | ||
189 | (1<<4)| | ||
190 | (1<<0) | ||
191 | ); | ||
192 | |||
193 | if (debug) | ||
194 | cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | #define MAX_IRQ_LOOP 10 | ||
200 | |||
201 | /* | ||
202 | * BOARD Specific: IRQ dma bits | ||
203 | */ | ||
204 | static char *cx88_aud_irqs[32] = { | ||
205 | "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ | ||
206 | NULL, /* reserved */ | ||
207 | "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ | ||
208 | NULL, /* reserved */ | ||
209 | "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ | ||
210 | NULL, /* reserved */ | ||
211 | "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ | ||
212 | NULL, /* reserved */ | ||
213 | "opc_err", "par_err", "rip_err", /* 16-18 */ | ||
214 | "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ | ||
215 | }; | ||
216 | |||
217 | /* | ||
218 | * BOARD Specific: Threats IRQ audio specific calls | ||
219 | */ | ||
220 | static void cx8801_aud_irq(snd_cx88_card_t *chip) | ||
221 | { | ||
222 | struct cx88_core *core = chip->core; | ||
223 | u32 status, mask; | ||
224 | u32 count; | ||
225 | |||
226 | status = cx_read(MO_AUD_INTSTAT); | ||
227 | mask = cx_read(MO_AUD_INTMSK); | ||
228 | if (0 == (status & mask)) { | ||
229 | spin_unlock(&chip->reg_lock); | ||
230 | return; | ||
231 | } | ||
232 | cx_write(MO_AUD_INTSTAT, status); | ||
233 | if (debug > 1 || (status & mask & ~0xff)) | ||
234 | cx88_print_irqbits(core->name, "irq aud", | ||
235 | cx88_aud_irqs, status, mask); | ||
236 | /* risc op code error */ | ||
237 | if (status & (1 << 16)) { | ||
238 | printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name); | ||
239 | cx_clear(MO_AUD_DMACNTRL, 0x11); | ||
240 | cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); | ||
241 | } | ||
242 | |||
243 | /* risc1 downstream */ | ||
244 | if (status & 0x01) { | ||
245 | spin_lock(&chip->reg_lock); | ||
246 | count = cx_read(MO_AUDD_GPCNT); | ||
247 | spin_unlock(&chip->reg_lock); | ||
248 | if (chip->read_count == 0) | ||
249 | chip->read_count += chip->dma_size; | ||
250 | } | ||
251 | |||
252 | if (chip->read_count >= chip->period_size) { | ||
253 | dprintk(2, "Elapsing period\n"); | ||
254 | snd_pcm_period_elapsed(chip->substream); | ||
255 | } | ||
256 | |||
257 | dprintk(3,"Leaving audio IRQ handler...\n"); | ||
258 | |||
259 | /* FIXME: Any other status should deserve a special handling? */ | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * BOARD Specific: Handles IRQ calls | ||
264 | */ | ||
265 | static irqreturn_t cx8801_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
266 | { | ||
267 | snd_cx88_card_t *chip = dev_id; | ||
268 | struct cx88_core *core = chip->core; | ||
269 | u32 status; | ||
270 | int loop, handled = 0; | ||
271 | |||
272 | for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { | ||
273 | status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x02); | ||
274 | if (0 == status) | ||
275 | goto out; | ||
276 | dprintk( 3, "cx8801_irq\n" ); | ||
277 | dprintk( 3, " loop: %d/%d\n", loop, MAX_IRQ_LOOP ); | ||
278 | dprintk( 3, " status: %d\n", status ); | ||
279 | handled = 1; | ||
280 | cx_write(MO_PCI_INTSTAT, status); | ||
281 | |||
282 | if (status & 0x02) | ||
283 | { | ||
284 | dprintk( 2, " ALSA IRQ handling\n" ); | ||
285 | cx8801_aud_irq(chip); | ||
286 | } | ||
287 | }; | ||
288 | |||
289 | if (MAX_IRQ_LOOP == loop) { | ||
290 | dprintk( 0, "clearing mask\n" ); | ||
291 | dprintk(1,"%s/0: irq loop -- clearing mask\n", | ||
292 | core->name); | ||
293 | cx_clear(MO_PCI_INTMSK,0x02); | ||
294 | } | ||
295 | |||
296 | out: | ||
297 | return IRQ_RETVAL(handled); | ||
298 | } | ||
299 | |||
300 | |||
301 | static int dsp_buffer_free(snd_cx88_card_t *chip) | ||
302 | { | ||
303 | BUG_ON(!chip->dma_size); | ||
304 | |||
305 | dprintk(2,"Freeing buffer\n"); | ||
306 | videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc); | ||
307 | videobuf_dma_free(&chip->dma_risc); | ||
308 | btcx_riscmem_free(chip->pci,&chip->buf->risc); | ||
309 | kfree(chip->buf); | ||
310 | |||
311 | chip->dma_size = 0; | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | /**************************************************************************** | ||
317 | ALSA PCM Interface | ||
318 | ****************************************************************************/ | ||
319 | |||
320 | /* | ||
321 | * Digital hardware definition | ||
322 | */ | ||
323 | static snd_pcm_hardware_t snd_cx88_digital_hw = { | ||
324 | .info = SNDRV_PCM_INFO_MMAP | | ||
325 | SNDRV_PCM_INFO_INTERLEAVED | | ||
326 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
327 | SNDRV_PCM_INFO_MMAP_VALID, | ||
328 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
329 | |||
330 | .rates = SNDRV_PCM_RATE_48000, | ||
331 | .rate_min = 48000, | ||
332 | .rate_max = 48000, | ||
333 | .channels_min = 1, | ||
334 | .channels_max = 2, | ||
335 | .buffer_bytes_max = (2*2048), | ||
336 | .period_bytes_min = 256, | ||
337 | .period_bytes_max = 2048, | ||
338 | .periods_min = 2, | ||
339 | .periods_max = 16, | ||
340 | }; | ||
341 | |||
342 | /* | ||
343 | * audio pcm capture runtime free | ||
344 | */ | ||
345 | static void snd_card_cx88_runtime_free(snd_pcm_runtime_t *runtime) | ||
346 | { | ||
347 | } | ||
348 | /* | ||
349 | * audio pcm capture open callback | ||
350 | */ | ||
351 | static int snd_cx88_pcm_open(snd_pcm_substream_t *substream) | ||
352 | { | ||
353 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | ||
354 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
355 | int err; | ||
356 | |||
357 | if (test_and_set_bit(0, &chip->opened)) | ||
358 | return -EBUSY; | ||
359 | |||
360 | err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
361 | if (err < 0) | ||
362 | goto _error; | ||
363 | |||
364 | chip->substream = substream; | ||
365 | |||
366 | chip->read_count = 0; | ||
367 | chip->read_offset = 0; | ||
368 | |||
369 | runtime->private_free = snd_card_cx88_runtime_free; | ||
370 | runtime->hw = snd_cx88_digital_hw; | ||
371 | |||
372 | return 0; | ||
373 | _error: | ||
374 | dprintk(1,"Error opening PCM!\n"); | ||
375 | clear_bit(0, &chip->opened); | ||
376 | smp_mb__after_clear_bit(); | ||
377 | return err; | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * audio close callback | ||
382 | */ | ||
383 | static int snd_cx88_close(snd_pcm_substream_t *substream) | ||
384 | { | ||
385 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | ||
386 | |||
387 | clear_bit(0, &chip->opened); | ||
388 | smp_mb__after_clear_bit(); | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * hw_params callback | ||
395 | */ | ||
396 | static int snd_cx88_hw_params(snd_pcm_substream_t * substream, | ||
397 | snd_pcm_hw_params_t * hw_params) | ||
398 | { | ||
399 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | ||
400 | struct cx88_buffer *buf; | ||
401 | |||
402 | if (substream->runtime->dma_area) { | ||
403 | dsp_buffer_free(chip); | ||
404 | substream->runtime->dma_area = NULL; | ||
405 | } | ||
406 | |||
407 | |||
408 | chip->period_size = params_period_bytes(hw_params); | ||
409 | chip->num_periods = params_periods(hw_params); | ||
410 | chip->dma_size = chip->period_size * params_periods(hw_params); | ||
411 | |||
412 | BUG_ON(!chip->dma_size); | ||
413 | |||
414 | dprintk(1,"Setting buffer\n"); | ||
415 | |||
416 | buf = kmalloc(sizeof(*buf),GFP_KERNEL); | ||
417 | if (NULL == buf) | ||
418 | return -ENOMEM; | ||
419 | memset(buf,0,sizeof(*buf)); | ||
420 | |||
421 | |||
422 | buf->vb.memory = V4L2_MEMORY_MMAP; | ||
423 | buf->vb.width = chip->period_size; | ||
424 | buf->vb.height = chip->num_periods; | ||
425 | buf->vb.size = chip->dma_size; | ||
426 | buf->vb.field = V4L2_FIELD_NONE; | ||
427 | |||
428 | videobuf_dma_init(&buf->vb.dma); | ||
429 | videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE, | ||
430 | (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); | ||
431 | |||
432 | videobuf_dma_pci_map(chip->pci,&buf->vb.dma); | ||
433 | |||
434 | |||
435 | cx88_risc_databuffer(chip->pci, &buf->risc, | ||
436 | buf->vb.dma.sglist, | ||
437 | buf->vb.width, buf->vb.height); | ||
438 | |||
439 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | ||
440 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
441 | |||
442 | buf->vb.state = STATE_PREPARED; | ||
443 | |||
444 | buf->bpl = chip->period_size; | ||
445 | chip->buf = buf; | ||
446 | chip->dma_risc = buf->vb.dma; | ||
447 | |||
448 | dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages); | ||
449 | substream->runtime->dma_area = chip->dma_risc.vmalloc; | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | /* | ||
454 | * hw free callback | ||
455 | */ | ||
456 | static int snd_cx88_hw_free(snd_pcm_substream_t * substream) | ||
457 | { | ||
458 | |||
459 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | ||
460 | |||
461 | if (substream->runtime->dma_area) { | ||
462 | dsp_buffer_free(chip); | ||
463 | substream->runtime->dma_area = NULL; | ||
464 | } | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | * prepare callback | ||
471 | */ | ||
472 | static int snd_cx88_prepare(snd_pcm_substream_t *substream) | ||
473 | { | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | |||
478 | /* | ||
479 | * trigger callback | ||
480 | */ | ||
481 | static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd) | ||
482 | { | ||
483 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | ||
484 | int err; | ||
485 | |||
486 | spin_lock(&chip->reg_lock); | ||
487 | |||
488 | switch (cmd) { | ||
489 | case SNDRV_PCM_TRIGGER_START: | ||
490 | err=_cx88_start_audio_dma(chip); | ||
491 | break; | ||
492 | case SNDRV_PCM_TRIGGER_STOP: | ||
493 | err=_cx88_stop_audio_dma(chip); | ||
494 | break; | ||
495 | default: | ||
496 | err=-EINVAL; | ||
497 | break; | ||
498 | } | ||
499 | |||
500 | spin_unlock(&chip->reg_lock); | ||
501 | |||
502 | return err; | ||
503 | } | ||
504 | |||
505 | /* | ||
506 | * pointer callback | ||
507 | */ | ||
508 | static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream) | ||
509 | { | ||
510 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | ||
511 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
512 | |||
513 | if (chip->read_count) { | ||
514 | chip->read_count -= snd_pcm_lib_period_bytes(substream); | ||
515 | chip->read_offset += snd_pcm_lib_period_bytes(substream); | ||
516 | if (chip->read_offset == chip->dma_size) | ||
517 | chip->read_offset = 0; | ||
518 | } | ||
519 | |||
520 | dprintk(2, "Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count); | ||
521 | return bytes_to_frames(runtime, chip->read_offset); | ||
522 | |||
523 | } | ||
524 | |||
525 | /* | ||
526 | * operators | ||
527 | */ | ||
528 | static snd_pcm_ops_t snd_cx88_pcm_ops = { | ||
529 | .open = snd_cx88_pcm_open, | ||
530 | .close = snd_cx88_close, | ||
531 | .ioctl = snd_pcm_lib_ioctl, | ||
532 | .hw_params = snd_cx88_hw_params, | ||
533 | .hw_free = snd_cx88_hw_free, | ||
534 | .prepare = snd_cx88_prepare, | ||
535 | .trigger = snd_cx88_card_trigger, | ||
536 | .pointer = snd_cx88_pointer, | ||
537 | }; | ||
538 | |||
539 | /* | ||
540 | * create a PCM device | ||
541 | */ | ||
542 | static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name) | ||
543 | { | ||
544 | int err; | ||
545 | snd_pcm_t *pcm; | ||
546 | |||
547 | err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); | ||
548 | if (err < 0) | ||
549 | return err; | ||
550 | pcm->private_data = chip; | ||
551 | strcpy(pcm->name, name); | ||
552 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops); | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /**************************************************************************** | ||
558 | CONTROL INTERFACE | ||
559 | ****************************************************************************/ | ||
560 | static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info) | ||
561 | { | ||
562 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
563 | info->count = 1; | ||
564 | info->value.integer.min = 0; | ||
565 | info->value.integer.max = 0x3f; | ||
566 | |||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | /* OK - TODO: test it */ | ||
571 | static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) | ||
572 | { | ||
573 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | ||
574 | struct cx88_core *core=chip->core; | ||
575 | |||
576 | value->value.integer.value[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); | ||
577 | |||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | /* OK - TODO: test it */ | ||
582 | static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) | ||
583 | { | ||
584 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | ||
585 | struct cx88_core *core=chip->core; | ||
586 | int v; | ||
587 | u32 old_control; | ||
588 | |||
589 | spin_lock_irq(&chip->reg_lock); | ||
590 | old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); | ||
591 | v = 0x3f - (value->value.integer.value[0] & 0x3f); | ||
592 | cx_andor(AUD_VOL_CTL, 0x3f, v); | ||
593 | spin_unlock_irq(&chip->reg_lock); | ||
594 | |||
595 | return v != old_control; | ||
596 | } | ||
597 | |||
598 | static snd_kcontrol_new_t snd_cx88_capture_volume = { | ||
599 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
600 | .name = "Capture Volume", | ||
601 | .info = snd_cx88_capture_volume_info, | ||
602 | .get = snd_cx88_capture_volume_get, | ||
603 | .put = snd_cx88_capture_volume_put, | ||
604 | }; | ||
605 | |||
606 | |||
607 | /**************************************************************************** | ||
608 | Basic Flow for Sound Devices | ||
609 | ****************************************************************************/ | ||
610 | |||
611 | /* | ||
612 | * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio | ||
613 | * Only boards with eeprom and byte 1 at eeprom=1 have it | ||
614 | */ | ||
615 | |||
616 | struct pci_device_id cx88_audio_pci_tbl[] = { | ||
617 | {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, | ||
618 | {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, | ||
619 | {0, } | ||
620 | }; | ||
621 | MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl); | ||
622 | |||
623 | /* | ||
624 | * Chip-specific destructor | ||
625 | */ | ||
626 | |||
627 | static int snd_cx88_free(snd_cx88_card_t *chip) | ||
628 | { | ||
629 | |||
630 | if (chip->irq >= 0){ | ||
631 | synchronize_irq(chip->irq); | ||
632 | free_irq(chip->irq, chip); | ||
633 | } | ||
634 | |||
635 | cx88_core_put(chip->core,chip->pci); | ||
636 | |||
637 | pci_disable_device(chip->pci); | ||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | /* | ||
642 | * Component Destructor | ||
643 | */ | ||
644 | static void snd_cx88_dev_free(snd_card_t * card) | ||
645 | { | ||
646 | snd_cx88_card_t *chip = card->private_data; | ||
647 | |||
648 | snd_cx88_free(chip); | ||
649 | } | ||
650 | |||
651 | |||
652 | /* | ||
653 | * Alsa Constructor - Component probe | ||
654 | */ | ||
655 | |||
656 | static int devno=0; | ||
657 | static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, | ||
658 | snd_cx88_card_t **rchip) | ||
659 | { | ||
660 | snd_cx88_card_t *chip; | ||
661 | struct cx88_core *core; | ||
662 | int err; | ||
663 | |||
664 | *rchip = NULL; | ||
665 | |||
666 | err = pci_enable_device(pci); | ||
667 | if (err < 0) | ||
668 | return err; | ||
669 | |||
670 | pci_set_master(pci); | ||
671 | |||
672 | chip = (snd_cx88_card_t *) card->private_data; | ||
673 | |||
674 | core = cx88_core_get(pci); | ||
675 | |||
676 | if (!pci_dma_supported(pci,0xffffffff)) { | ||
677 | dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name); | ||
678 | err = -EIO; | ||
679 | cx88_core_put(core,pci); | ||
680 | return err; | ||
681 | } | ||
682 | |||
683 | |||
684 | /* pci init */ | ||
685 | chip->card = card; | ||
686 | chip->pci = pci; | ||
687 | chip->irq = -1; | ||
688 | spin_lock_init(&chip->reg_lock); | ||
689 | |||
690 | cx88_reset(core); | ||
691 | if (NULL == core) { | ||
692 | err = -EINVAL; | ||
693 | kfree (chip); | ||
694 | return err; | ||
695 | } | ||
696 | chip->core = core; | ||
697 | |||
698 | /* get irq */ | ||
699 | err = request_irq(chip->pci->irq, cx8801_irq, | ||
700 | SA_SHIRQ | SA_INTERRUPT, chip->core->name, chip); | ||
701 | if (err < 0) { | ||
702 | dprintk(0, "%s: can't get IRQ %d\n", | ||
703 | chip->core->name, chip->pci->irq); | ||
704 | return err; | ||
705 | } | ||
706 | |||
707 | /* print pci info */ | ||
708 | pci_read_config_byte(pci, PCI_CLASS_REVISION, &chip->pci_rev); | ||
709 | pci_read_config_byte(pci, PCI_LATENCY_TIMER, &chip->pci_lat); | ||
710 | |||
711 | dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, " | ||
712 | "latency: %d, mmio: 0x%lx\n", core->name, devno, | ||
713 | pci_name(pci), chip->pci_rev, pci->irq, | ||
714 | chip->pci_lat,pci_resource_start(pci,0)); | ||
715 | |||
716 | chip->irq = pci->irq; | ||
717 | synchronize_irq(chip->irq); | ||
718 | |||
719 | snd_card_set_dev(card, &pci->dev); | ||
720 | |||
721 | *rchip = chip; | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static int __devinit cx88_audio_initdev(struct pci_dev *pci, | ||
727 | const struct pci_device_id *pci_id) | ||
728 | { | ||
729 | snd_card_t *card; | ||
730 | snd_cx88_card_t *chip; | ||
731 | int err; | ||
732 | |||
733 | if (devno >= SNDRV_CARDS) | ||
734 | return (-ENODEV); | ||
735 | |||
736 | if (!enable[devno]) { | ||
737 | ++devno; | ||
738 | return (-ENOENT); | ||
739 | } | ||
740 | |||
741 | card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t)); | ||
742 | if (!card) | ||
743 | return (-ENOMEM); | ||
744 | |||
745 | card->private_free = snd_cx88_dev_free; | ||
746 | |||
747 | err = snd_cx88_create(card, pci, &chip); | ||
748 | if (err < 0) | ||
749 | return (err); | ||
750 | |||
751 | err = snd_cx88_pcm(chip, 0, "CX88 Digital"); | ||
752 | |||
753 | if (err < 0) { | ||
754 | snd_card_free(card); | ||
755 | return (err); | ||
756 | } | ||
757 | |||
758 | err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip)); | ||
759 | if (err < 0) { | ||
760 | snd_card_free(card); | ||
761 | return (err); | ||
762 | } | ||
763 | |||
764 | strcpy (card->driver, "CX88x"); | ||
765 | sprintf(card->shortname, "Conexant CX%x", pci->device); | ||
766 | sprintf(card->longname, "%s at %#lx", | ||
767 | card->shortname, pci_resource_start(pci, 0)); | ||
768 | strcpy (card->mixername, "CX88"); | ||
769 | |||
770 | dprintk (0, "%s/%i: ALSA support for cx2388x boards\n", | ||
771 | card->driver,devno); | ||
772 | |||
773 | err = snd_card_register(card); | ||
774 | if (err < 0) { | ||
775 | snd_card_free(card); | ||
776 | return (err); | ||
777 | } | ||
778 | snd_cx88_cards[devno] = card; | ||
779 | |||
780 | pci_set_drvdata(pci,card); | ||
781 | |||
782 | devno++; | ||
783 | return 0; | ||
784 | } | ||
785 | /* | ||
786 | * ALSA destructor | ||
787 | */ | ||
788 | static void __devexit cx88_audio_finidev(struct pci_dev *pci) | ||
789 | { | ||
790 | struct cx88_audio_dev *card = pci_get_drvdata(pci); | ||
791 | |||
792 | snd_card_free((void *)card); | ||
793 | |||
794 | pci_set_drvdata(pci, NULL); | ||
795 | |||
796 | devno--; | ||
797 | } | ||
798 | |||
799 | /* | ||
800 | * PCI driver definition | ||
801 | */ | ||
802 | |||
803 | static struct pci_driver cx88_audio_pci_driver = { | ||
804 | .name = "cx88_audio", | ||
805 | .id_table = cx88_audio_pci_tbl, | ||
806 | .probe = cx88_audio_initdev, | ||
807 | .remove = cx88_audio_finidev, | ||
808 | SND_PCI_PM_CALLBACKS | ||
809 | }; | ||
810 | |||
811 | /**************************************************************************** | ||
812 | LINUX MODULE INIT | ||
813 | ****************************************************************************/ | ||
814 | |||
815 | /* | ||
816 | * module init | ||
817 | */ | ||
818 | static int cx88_audio_init(void) | ||
819 | { | ||
820 | printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n", | ||
821 | (CX88_VERSION_CODE >> 16) & 0xff, | ||
822 | (CX88_VERSION_CODE >> 8) & 0xff, | ||
823 | CX88_VERSION_CODE & 0xff); | ||
824 | #ifdef SNAPSHOT | ||
825 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | ||
826 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | ||
827 | #endif | ||
828 | return pci_register_driver(&cx88_audio_pci_driver); | ||
829 | } | ||
830 | |||
831 | /* | ||
832 | * module remove | ||
833 | */ | ||
834 | static void cx88_audio_fini(void) | ||
835 | { | ||
836 | |||
837 | pci_unregister_driver(&cx88_audio_pci_driver); | ||
838 | } | ||
839 | |||
840 | module_init(cx88_audio_init); | ||
841 | module_exit(cx88_audio_fini); | ||
842 | |||
843 | /* ----------------------------------------------------------- */ | ||
844 | /* | ||
845 | * Local variables: | ||
846 | * c-basic-offset: 8 | ||
847 | * End: | ||
848 | */ | ||
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 74e57a53116f..a49062119313 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -32,10 +32,10 @@ | |||
32 | #include <linux/firmware.h> | 32 | #include <linux/firmware.h> |
33 | 33 | ||
34 | #include "cx88.h" | 34 | #include "cx88.h" |
35 | #include <media/v4l2-common.h> | ||
35 | 36 | ||
36 | MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards"); | 37 | MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards"); |
37 | MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>"); | 38 | MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); |
38 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | ||
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | 40 | ||
41 | static unsigned int mpegbufs = 32; | 41 | static unsigned int mpegbufs = 32; |
@@ -1375,7 +1375,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, | |||
1375 | struct cx88_core *core = dev->core; | 1375 | struct cx88_core *core = dev->core; |
1376 | 1376 | ||
1377 | if (debug > 1) | 1377 | if (debug > 1) |
1378 | cx88_print_ioctl(core->name,cmd); | 1378 | v4l_print_ioctl(core->name,cmd); |
1379 | 1379 | ||
1380 | switch (cmd) { | 1380 | switch (cmd) { |
1381 | 1381 | ||
@@ -1689,6 +1689,18 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, | |||
1689 | memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params)); | 1689 | memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params)); |
1690 | memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params)); | 1690 | memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params)); |
1691 | 1691 | ||
1692 | if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) { | ||
1693 | |||
1694 | if (core->tuner_formats & V4L2_STD_525_60) { | ||
1695 | dev->height = 480; | ||
1696 | dev->params.vi_frame_rate = 30; | ||
1697 | } else { | ||
1698 | dev->height = 576; | ||
1699 | dev->params.vi_frame_rate = 25; | ||
1700 | } | ||
1701 | |||
1702 | } | ||
1703 | |||
1692 | err = cx8802_init_common(dev); | 1704 | err = cx8802_init_common(dev); |
1693 | if (0 != err) | 1705 | if (0 != err) |
1694 | goto fail_free; | 1706 | goto fail_free; |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 951709aa88ba..a76d54503b6f 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -611,12 +611,12 @@ struct cx88_board cx88_boards[] = { | |||
611 | .input = {{ | 611 | .input = {{ |
612 | .type = CX88_VMUX_TELEVISION, | 612 | .type = CX88_VMUX_TELEVISION, |
613 | .vmux = 0, | 613 | .vmux = 0, |
614 | .gpio0 = 0xed12, /* internal decoder */ | 614 | .gpio0 = 0xed1a, |
615 | .gpio2 = 0x00ff, | 615 | .gpio2 = 0x00ff, |
616 | },{ | 616 | },{ |
617 | .type = CX88_VMUX_DEBUG, | 617 | .type = CX88_VMUX_DEBUG, |
618 | .vmux = 0, | 618 | .vmux = 0, |
619 | .gpio0 = 0xff01, /* mono from tuner chip */ | 619 | .gpio0 = 0xff01, |
620 | },{ | 620 | },{ |
621 | .type = CX88_VMUX_COMPOSITE1, | 621 | .type = CX88_VMUX_COMPOSITE1, |
622 | .vmux = 1, | 622 | .vmux = 1, |
@@ -708,7 +708,7 @@ struct cx88_board cx88_boards[] = { | |||
708 | }, | 708 | }, |
709 | [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { | 709 | [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { |
710 | .name = "DViCO FusionHDTV 3 Gold-T", | 710 | .name = "DViCO FusionHDTV 3 Gold-T", |
711 | .tuner_type = TUNER_THOMSON_DTT7611, | 711 | .tuner_type = TUNER_THOMSON_DTT761X, |
712 | .radio_type = UNSET, | 712 | .radio_type = UNSET, |
713 | .tuner_addr = ADDR_UNSET, | 713 | .tuner_addr = ADDR_UNSET, |
714 | .radio_addr = ADDR_UNSET, | 714 | .radio_addr = ADDR_UNSET, |
@@ -897,6 +897,158 @@ struct cx88_board cx88_boards[] = { | |||
897 | .gpio3 = 0x0000, | 897 | .gpio3 = 0x0000, |
898 | }}, | 898 | }}, |
899 | }, | 899 | }, |
900 | [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = { | ||
901 | .name = "Hauppauge Nova-S-Plus DVB-S", | ||
902 | .tuner_type = TUNER_ABSENT, | ||
903 | .radio_type = UNSET, | ||
904 | .tuner_addr = ADDR_UNSET, | ||
905 | .radio_addr = ADDR_UNSET, | ||
906 | .input = {{ | ||
907 | .type = CX88_VMUX_DVB, | ||
908 | .vmux = 0, | ||
909 | },{ | ||
910 | .type = CX88_VMUX_COMPOSITE1, | ||
911 | .vmux = 1, | ||
912 | },{ | ||
913 | .type = CX88_VMUX_SVIDEO, | ||
914 | .vmux = 2, | ||
915 | }}, | ||
916 | .dvb = 1, | ||
917 | }, | ||
918 | [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = { | ||
919 | .name = "Hauppauge Nova-SE2 DVB-S", | ||
920 | .tuner_type = TUNER_ABSENT, | ||
921 | .radio_type = UNSET, | ||
922 | .tuner_addr = ADDR_UNSET, | ||
923 | .radio_addr = ADDR_UNSET, | ||
924 | .input = {{ | ||
925 | .type = CX88_VMUX_DVB, | ||
926 | .vmux = 0, | ||
927 | }}, | ||
928 | .dvb = 1, | ||
929 | }, | ||
930 | [CX88_BOARD_KWORLD_DVBS_100] = { | ||
931 | .name = "KWorld DVB-S 100", | ||
932 | .tuner_type = TUNER_ABSENT, | ||
933 | .radio_type = UNSET, | ||
934 | .tuner_addr = ADDR_UNSET, | ||
935 | .radio_addr = ADDR_UNSET, | ||
936 | .input = {{ | ||
937 | .type = CX88_VMUX_DVB, | ||
938 | .vmux = 0, | ||
939 | },{ | ||
940 | .type = CX88_VMUX_COMPOSITE1, | ||
941 | .vmux = 1, | ||
942 | },{ | ||
943 | .type = CX88_VMUX_SVIDEO, | ||
944 | .vmux = 2, | ||
945 | }}, | ||
946 | .dvb = 1, | ||
947 | }, | ||
948 | [CX88_BOARD_HAUPPAUGE_HVR1100] = { | ||
949 | .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid", | ||
950 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | ||
951 | .radio_type = UNSET, | ||
952 | .tuner_addr = ADDR_UNSET, | ||
953 | .radio_addr = ADDR_UNSET, | ||
954 | .tda9887_conf = TDA9887_PRESENT, | ||
955 | .input = {{ | ||
956 | .type = CX88_VMUX_TELEVISION, | ||
957 | .vmux = 0, | ||
958 | },{ | ||
959 | .type = CX88_VMUX_COMPOSITE1, | ||
960 | .vmux = 1, | ||
961 | },{ | ||
962 | .type = CX88_VMUX_SVIDEO, | ||
963 | .vmux = 2, | ||
964 | }}, | ||
965 | /* fixme: Add radio support */ | ||
966 | .dvb = 1, | ||
967 | }, | ||
968 | [CX88_BOARD_HAUPPAUGE_HVR1100LP] = { | ||
969 | .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)", | ||
970 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | ||
971 | .radio_type = UNSET, | ||
972 | .tuner_addr = ADDR_UNSET, | ||
973 | .radio_addr = ADDR_UNSET, | ||
974 | .tda9887_conf = TDA9887_PRESENT, | ||
975 | .input = {{ | ||
976 | .type = CX88_VMUX_TELEVISION, | ||
977 | .vmux = 0, | ||
978 | },{ | ||
979 | .type = CX88_VMUX_COMPOSITE1, | ||
980 | .vmux = 1, | ||
981 | }}, | ||
982 | /* fixme: Add radio support */ | ||
983 | .dvb = 1, | ||
984 | }, | ||
985 | [CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = { | ||
986 | .name = "digitalnow DNTV Live! DVB-T Pro", | ||
987 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | ||
988 | .radio_type = UNSET, | ||
989 | .tuner_addr = ADDR_UNSET, | ||
990 | .radio_addr = ADDR_UNSET, | ||
991 | .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | | ||
992 | TDA9887_PORT2_ACTIVE, | ||
993 | .input = {{ | ||
994 | .type = CX88_VMUX_TELEVISION, | ||
995 | .vmux = 0, | ||
996 | .gpio0 = 0xf80808, | ||
997 | },{ | ||
998 | .type = CX88_VMUX_COMPOSITE1, | ||
999 | .vmux = 1, | ||
1000 | .gpio0 = 0xf80808, | ||
1001 | },{ | ||
1002 | .type = CX88_VMUX_SVIDEO, | ||
1003 | .vmux = 2, | ||
1004 | .gpio0 = 0xf80808, | ||
1005 | }}, | ||
1006 | .radio = { | ||
1007 | .type = CX88_RADIO, | ||
1008 | .gpio0 = 0xf80808, | ||
1009 | }, | ||
1010 | .dvb = 1, | ||
1011 | }, | ||
1012 | [CX88_BOARD_KWORLD_DVB_T_CX22702] = { | ||
1013 | /* Kworld V-stream Xpert DVB-T with Thomson tuner */ | ||
1014 | /* DTT 7579 Conexant CX22702-19 Conexant CX2388x */ | ||
1015 | /* Manenti Marco <marco_manenti@colman.it> */ | ||
1016 | .name = "KWorld/VStream XPert DVB-T with cx22702", | ||
1017 | .tuner_type = TUNER_ABSENT, | ||
1018 | .radio_type = UNSET, | ||
1019 | .tuner_addr = ADDR_UNSET, | ||
1020 | .radio_addr = ADDR_UNSET, | ||
1021 | .input = {{ | ||
1022 | .type = CX88_VMUX_COMPOSITE1, | ||
1023 | .vmux = 1, | ||
1024 | .gpio0 = 0x0700, | ||
1025 | .gpio2 = 0x0101, | ||
1026 | },{ | ||
1027 | .type = CX88_VMUX_SVIDEO, | ||
1028 | .vmux = 2, | ||
1029 | .gpio0 = 0x0700, | ||
1030 | .gpio2 = 0x0101, | ||
1031 | }}, | ||
1032 | .dvb = 1, | ||
1033 | }, | ||
1034 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = { | ||
1035 | .name = "DViCO FusionHDTV DVB-T Dual Digital", | ||
1036 | .tuner_type = TUNER_ABSENT, /* No analog tuner */ | ||
1037 | .radio_type = UNSET, | ||
1038 | .tuner_addr = ADDR_UNSET, | ||
1039 | .radio_addr = ADDR_UNSET, | ||
1040 | .input = {{ | ||
1041 | .type = CX88_VMUX_COMPOSITE1, | ||
1042 | .vmux = 1, | ||
1043 | .gpio0 = 0x000027df, | ||
1044 | },{ | ||
1045 | .type = CX88_VMUX_SVIDEO, | ||
1046 | .vmux = 2, | ||
1047 | .gpio0 = 0x000027df, | ||
1048 | }}, | ||
1049 | .dvb = 1, | ||
1050 | }, | ||
1051 | |||
900 | }; | 1052 | }; |
901 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); | 1053 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); |
902 | 1054 | ||
@@ -1044,6 +1196,54 @@ struct cx88_subid cx88_subids[] = { | |||
1044 | .subvendor = 0x1461, | 1196 | .subvendor = 0x1461, |
1045 | .subdevice = 0x000a, | 1197 | .subdevice = 0x000a, |
1046 | .card = CX88_BOARD_AVERTV_303, | 1198 | .card = CX88_BOARD_AVERTV_303, |
1199 | },{ | ||
1200 | .subvendor = 0x0070, | ||
1201 | .subdevice = 0x9200, | ||
1202 | .card = CX88_BOARD_HAUPPAUGE_NOVASE2_S1, | ||
1203 | },{ | ||
1204 | .subvendor = 0x0070, | ||
1205 | .subdevice = 0x9201, | ||
1206 | .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1, | ||
1207 | },{ | ||
1208 | .subvendor = 0x0070, | ||
1209 | .subdevice = 0x9202, | ||
1210 | .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1, | ||
1211 | },{ | ||
1212 | .subvendor = 0x17de, | ||
1213 | .subdevice = 0x08b2, | ||
1214 | .card = CX88_BOARD_KWORLD_DVBS_100, | ||
1215 | },{ | ||
1216 | .subvendor = 0x0070, | ||
1217 | .subdevice = 0x9400, | ||
1218 | .card = CX88_BOARD_HAUPPAUGE_HVR1100, | ||
1219 | },{ | ||
1220 | .subvendor = 0x0070, | ||
1221 | .subdevice = 0x9402, | ||
1222 | .card = CX88_BOARD_HAUPPAUGE_HVR1100, | ||
1223 | },{ | ||
1224 | .subvendor = 0x0070, | ||
1225 | .subdevice = 0x9800, | ||
1226 | .card = CX88_BOARD_HAUPPAUGE_HVR1100LP, | ||
1227 | },{ | ||
1228 | .subvendor = 0x0070, | ||
1229 | .subdevice = 0x9802, | ||
1230 | .card = CX88_BOARD_HAUPPAUGE_HVR1100LP, | ||
1231 | },{ | ||
1232 | .subvendor = 0x0070, | ||
1233 | .subdevice = 0x9001, | ||
1234 | .card = CX88_BOARD_HAUPPAUGE_DVB_T1, | ||
1235 | },{ | ||
1236 | .subvendor = 0x1822, | ||
1237 | .subdevice = 0x0025, | ||
1238 | .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO, | ||
1239 | },{ | ||
1240 | .subvendor = 0x17de, | ||
1241 | .subdevice = 0x08a1, | ||
1242 | .card = CX88_BOARD_KWORLD_DVB_T_CX22702, | ||
1243 | },{ | ||
1244 | .subvendor = 0x18ac, | ||
1245 | .subdevice = 0xdb50, | ||
1246 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, | ||
1047 | }, | 1247 | }, |
1048 | }; | 1248 | }; |
1049 | const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); | 1249 | const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); |
@@ -1075,20 +1275,19 @@ static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
1075 | core->name, core->tuner_type, eeprom_data[0]); | 1275 | core->name, core->tuner_type, eeprom_data[0]); |
1076 | } | 1276 | } |
1077 | 1277 | ||
1078 | |||
1079 | /* ----------------------------------------------------------------------- */ | ||
1080 | |||
1081 | static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | 1278 | static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) |
1082 | { | 1279 | { |
1083 | struct tveeprom tv; | 1280 | struct tveeprom tv; |
1084 | 1281 | ||
1085 | tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data); | 1282 | tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data); |
1086 | core->tuner_type = tv.tuner_type; | 1283 | core->tuner_type = tv.tuner_type; |
1284 | core->tuner_formats = tv.tuner_formats; | ||
1087 | core->has_radio = tv.has_radio; | 1285 | core->has_radio = tv.has_radio; |
1088 | 1286 | ||
1089 | /* Make sure we support the board model */ | 1287 | /* Make sure we support the board model */ |
1090 | switch (tv.model) | 1288 | switch (tv.model) |
1091 | { | 1289 | { |
1290 | case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ | ||
1092 | case 90002: /* Nova-T-PCI (9002) */ | 1291 | case 90002: /* Nova-T-PCI (9002) */ |
1093 | case 92001: /* Nova-S-Plus (Video and IR) */ | 1292 | case 92001: /* Nova-S-Plus (Video and IR) */ |
1094 | case 92002: /* Nova-S-Plus (Video and IR) */ | 1293 | case 92002: /* Nova-S-Plus (Video and IR) */ |
@@ -1096,7 +1295,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
1096 | case 90500: /* Nova-T-PCI (oem) */ | 1295 | case 90500: /* Nova-T-PCI (oem) */ |
1097 | case 90501: /* Nova-T-PCI (oem/IR) */ | 1296 | case 90501: /* Nova-T-PCI (oem/IR) */ |
1098 | case 92000: /* Nova-SE2 (OEM, No Video or IR) */ | 1297 | case 92000: /* Nova-SE2 (OEM, No Video or IR) */ |
1099 | 1298 | case 94009: /* WinTV-HVR1100 (Video and IR Retail) */ | |
1299 | case 94501: /* WinTV-HVR1100 (Video and IR OEM) */ | ||
1300 | case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */ | ||
1100 | /* known */ | 1301 | /* known */ |
1101 | break; | 1302 | break; |
1102 | default: | 1303 | default: |
@@ -1211,12 +1412,21 @@ void cx88_card_setup(struct cx88_core *core) | |||
1211 | if (0 == core->i2c_rc) | 1412 | if (0 == core->i2c_rc) |
1212 | leadtek_eeprom(core,eeprom); | 1413 | leadtek_eeprom(core,eeprom); |
1213 | break; | 1414 | break; |
1415 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | ||
1416 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | ||
1214 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 1417 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
1418 | case CX88_BOARD_HAUPPAUGE_HVR1100: | ||
1419 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | ||
1215 | if (0 == core->i2c_rc) | 1420 | if (0 == core->i2c_rc) |
1216 | hauppauge_eeprom(core,eeprom); | 1421 | hauppauge_eeprom(core,eeprom); |
1217 | break; | 1422 | break; |
1423 | case CX88_BOARD_KWORLD_DVBS_100: | ||
1424 | cx_write(MO_GP0_IO, 0x000007f8); | ||
1425 | cx_write(MO_GP1_IO, 0x00000001); | ||
1426 | break; | ||
1218 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: | 1427 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: |
1219 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | 1428 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: |
1429 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: | ||
1220 | /* GPIO0:0 is hooked to mt352 reset pin */ | 1430 | /* GPIO0:0 is hooked to mt352 reset pin */ |
1221 | cx_set(MO_GP0_IO, 0x00000101); | 1431 | cx_set(MO_GP0_IO, 0x00000101); |
1222 | cx_clear(MO_GP0_IO, 0x00000001); | 1432 | cx_clear(MO_GP0_IO, 0x00000001); |
@@ -1232,6 +1442,9 @@ void cx88_card_setup(struct cx88_core *core) | |||
1232 | cx_clear(MO_GP0_IO, 0x00000007); | 1442 | cx_clear(MO_GP0_IO, 0x00000007); |
1233 | cx_set(MO_GP2_IO, 0x00000101); | 1443 | cx_set(MO_GP2_IO, 0x00000101); |
1234 | break; | 1444 | break; |
1445 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | ||
1446 | cx_write(MO_GP0_IO, 0x00080808); | ||
1447 | break; | ||
1235 | case CX88_BOARD_ATI_HDTVWONDER: | 1448 | case CX88_BOARD_ATI_HDTVWONDER: |
1236 | if (0 == core->i2c_rc) { | 1449 | if (0 == core->i2c_rc) { |
1237 | /* enable tuner */ | 1450 | /* enable tuner */ |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index bb6eb54e19ce..9975be1aca38 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/videodev2.h> | 34 | #include <linux/videodev2.h> |
35 | 35 | ||
36 | #include "cx88.h" | 36 | #include "cx88.h" |
37 | #include <media/v4l2-common.h> | ||
37 | 38 | ||
38 | MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); | 39 | MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); |
39 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | 40 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); |
@@ -76,60 +77,6 @@ static unsigned int cx88_devcount; | |||
76 | static LIST_HEAD(cx88_devlist); | 77 | static LIST_HEAD(cx88_devlist); |
77 | static DECLARE_MUTEX(devlist); | 78 | static DECLARE_MUTEX(devlist); |
78 | 79 | ||
79 | /* ------------------------------------------------------------------ */ | ||
80 | /* debug help functions */ | ||
81 | |||
82 | static const char *v4l1_ioctls[] = { | ||
83 | "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT", | ||
84 | "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ", | ||
85 | "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT", | ||
86 | "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", | ||
87 | "SMICROCODE", "GVBIFMT", "SVBIFMT" }; | ||
88 | #define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) | ||
89 | |||
90 | static const char *v4l2_ioctls[] = { | ||
91 | "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT", | ||
92 | "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF", | ||
93 | "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON", | ||
94 | "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD", | ||
95 | "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER", | ||
96 | "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL", | ||
97 | "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43", | ||
98 | "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT", | ||
99 | "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR", | ||
100 | "S_MODULATOR" | ||
101 | }; | ||
102 | #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) | ||
103 | |||
104 | void cx88_print_ioctl(char *name, unsigned int cmd) | ||
105 | { | ||
106 | char *dir; | ||
107 | |||
108 | switch (_IOC_DIR(cmd)) { | ||
109 | case _IOC_NONE: dir = "--"; break; | ||
110 | case _IOC_READ: dir = "r-"; break; | ||
111 | case _IOC_WRITE: dir = "-w"; break; | ||
112 | case _IOC_READ | _IOC_WRITE: dir = "rw"; break; | ||
113 | default: dir = "??"; break; | ||
114 | } | ||
115 | switch (_IOC_TYPE(cmd)) { | ||
116 | case 'v': | ||
117 | printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n", | ||
118 | name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ? | ||
119 | v4l1_ioctls[_IOC_NR(cmd)] : "???"); | ||
120 | break; | ||
121 | case 'V': | ||
122 | printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n", | ||
123 | name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ? | ||
124 | v4l2_ioctls[_IOC_NR(cmd)] : "???"); | ||
125 | break; | ||
126 | default: | ||
127 | printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n", | ||
128 | name, cmd, dir, _IOC_NR(cmd)); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /* ------------------------------------------------------------------ */ | ||
133 | #define NO_SYNC_LINE (-1U) | 80 | #define NO_SYNC_LINE (-1U) |
134 | 81 | ||
135 | static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, | 82 | static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, |
@@ -291,9 +238,9 @@ cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf) | |||
291 | * channel 22 (u video) - 2.0k | 238 | * channel 22 (u video) - 2.0k |
292 | * channel 23 (v video) - 2.0k | 239 | * channel 23 (v video) - 2.0k |
293 | * channel 24 (vbi) - 4.0k | 240 | * channel 24 (vbi) - 4.0k |
294 | * channels 25+26 (audio) - 0.5k | 241 | * channels 25+26 (audio) - 4.0k |
295 | * channel 28 (mpeg) - 4.0k | 242 | * channel 28 (mpeg) - 4.0k |
296 | * TOTAL = 25.5k | 243 | * TOTAL = 29.0k |
297 | * | 244 | * |
298 | * Every channel has 160 bytes control data (64 bytes instruction | 245 | * Every channel has 160 bytes control data (64 bytes instruction |
299 | * queue and 6 CDT entries), which is close to 2k total. | 246 | * queue and 6 CDT entries), which is close to 2k total. |
@@ -359,7 +306,7 @@ struct sram_channel cx88_sram_channels[] = { | |||
359 | .ctrl_start = 0x180680, | 306 | .ctrl_start = 0x180680, |
360 | .cdt = 0x180680 + 64, | 307 | .cdt = 0x180680 + 64, |
361 | .fifo_start = 0x185400, | 308 | .fifo_start = 0x185400, |
362 | .fifo_size = 0x000200, | 309 | .fifo_size = 0x001000, |
363 | .ptr1_reg = MO_DMA25_PTR1, | 310 | .ptr1_reg = MO_DMA25_PTR1, |
364 | .ptr2_reg = MO_DMA25_PTR2, | 311 | .ptr2_reg = MO_DMA25_PTR2, |
365 | .cnt1_reg = MO_DMA25_CNT1, | 312 | .cnt1_reg = MO_DMA25_CNT1, |
@@ -371,7 +318,7 @@ struct sram_channel cx88_sram_channels[] = { | |||
371 | .ctrl_start = 0x180720, | 318 | .ctrl_start = 0x180720, |
372 | .cdt = 0x180680 + 64, /* same as audio IN */ | 319 | .cdt = 0x180680 + 64, /* same as audio IN */ |
373 | .fifo_start = 0x185400, /* same as audio IN */ | 320 | .fifo_start = 0x185400, /* same as audio IN */ |
374 | .fifo_size = 0x000200, /* same as audio IN */ | 321 | .fifo_size = 0x001000, /* same as audio IN */ |
375 | .ptr1_reg = MO_DMA26_PTR1, | 322 | .ptr1_reg = MO_DMA26_PTR1, |
376 | .ptr2_reg = MO_DMA26_PTR2, | 323 | .ptr2_reg = MO_DMA26_PTR2, |
377 | .cnt1_reg = MO_DMA26_CNT1, | 324 | .cnt1_reg = MO_DMA26_CNT1, |
@@ -382,7 +329,7 @@ struct sram_channel cx88_sram_channels[] = { | |||
382 | .cmds_start = 0x180200, | 329 | .cmds_start = 0x180200, |
383 | .ctrl_start = 0x1807C0, | 330 | .ctrl_start = 0x1807C0, |
384 | .cdt = 0x1807C0 + 64, | 331 | .cdt = 0x1807C0 + 64, |
385 | .fifo_start = 0x185600, | 332 | .fifo_start = 0x186400, |
386 | .fifo_size = 0x001000, | 333 | .fifo_size = 0x001000, |
387 | .ptr1_reg = MO_DMA28_PTR1, | 334 | .ptr1_reg = MO_DMA28_PTR1, |
388 | .ptr2_reg = MO_DMA28_PTR2, | 335 | .ptr2_reg = MO_DMA28_PTR2, |
@@ -848,7 +795,6 @@ int cx88_start_audio_dma(struct cx88_core *core) | |||
848 | 795 | ||
849 | /* start dma */ | 796 | /* start dma */ |
850 | cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */ | 797 | cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */ |
851 | |||
852 | return 0; | 798 | return 0; |
853 | } | 799 | } |
854 | 800 | ||
@@ -1208,7 +1154,6 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) | |||
1208 | 1154 | ||
1209 | /* ------------------------------------------------------------------ */ | 1155 | /* ------------------------------------------------------------------ */ |
1210 | 1156 | ||
1211 | EXPORT_SYMBOL(cx88_print_ioctl); | ||
1212 | EXPORT_SYMBOL(cx88_print_irqbits); | 1157 | EXPORT_SYMBOL(cx88_print_irqbits); |
1213 | 1158 | ||
1214 | EXPORT_SYMBOL(cx88_core_irq); | 1159 | EXPORT_SYMBOL(cx88_core_irq); |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 99ea955f5987..42c012aaa849 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * device driver for Conexant 2388x based TV cards | 3 | * device driver for Conexant 2388x based TV cards |
4 | * MPEG Transport Stream (DVB) routines | 4 | * MPEG Transport Stream (DVB) routines |
5 | * | 5 | * |
6 | * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au> | 6 | * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> |
7 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | 7 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
@@ -31,10 +31,14 @@ | |||
31 | 31 | ||
32 | #include "cx88.h" | 32 | #include "cx88.h" |
33 | #include "dvb-pll.h" | 33 | #include "dvb-pll.h" |
34 | #include <media/v4l2-common.h> | ||
34 | 35 | ||
35 | #ifdef HAVE_MT352 | 36 | #ifdef HAVE_MT352 |
36 | # include "mt352.h" | 37 | # include "mt352.h" |
37 | # include "mt352_priv.h" | 38 | # include "mt352_priv.h" |
39 | # ifdef HAVE_VP3054_I2C | ||
40 | # include "cx88-vp3054-i2c.h" | ||
41 | # endif | ||
38 | #endif | 42 | #endif |
39 | #ifdef HAVE_CX22702 | 43 | #ifdef HAVE_CX22702 |
40 | # include "cx22702.h" | 44 | # include "cx22702.h" |
@@ -48,6 +52,9 @@ | |||
48 | #ifdef HAVE_NXT200X | 52 | #ifdef HAVE_NXT200X |
49 | # include "nxt200x.h" | 53 | # include "nxt200x.h" |
50 | #endif | 54 | #endif |
55 | #ifdef HAVE_CX24123 | ||
56 | # include "cx24123.h" | ||
57 | #endif | ||
51 | 58 | ||
52 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); | 59 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); |
53 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | 60 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); |
@@ -125,6 +132,27 @@ static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) | |||
125 | return 0; | 132 | return 0; |
126 | } | 133 | } |
127 | 134 | ||
135 | static int dvico_dual_demod_init(struct dvb_frontend *fe) | ||
136 | { | ||
137 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; | ||
138 | static u8 reset [] = { RESET, 0x80 }; | ||
139 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | ||
140 | static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; | ||
141 | static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | ||
142 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | ||
143 | |||
144 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
145 | udelay(200); | ||
146 | mt352_write(fe, reset, sizeof(reset)); | ||
147 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
148 | |||
149 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
150 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | ||
151 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
128 | static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) | 156 | static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) |
129 | { | 157 | { |
130 | static u8 clock_config [] = { 0x89, 0x38, 0x39 }; | 158 | static u8 clock_config [] = { 0x89, 0x38, 0x39 }; |
@@ -172,6 +200,98 @@ static struct mt352_config dntv_live_dvbt_config = { | |||
172 | .demod_init = dntv_live_dvbt_demod_init, | 200 | .demod_init = dntv_live_dvbt_demod_init, |
173 | .pll_set = mt352_pll_set, | 201 | .pll_set = mt352_pll_set, |
174 | }; | 202 | }; |
203 | |||
204 | static struct mt352_config dvico_fusionhdtv_dual = { | ||
205 | .demod_address = 0x0F, | ||
206 | .demod_init = dvico_dual_demod_init, | ||
207 | .pll_set = mt352_pll_set, | ||
208 | }; | ||
209 | |||
210 | #ifdef HAVE_VP3054_I2C | ||
211 | static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) | ||
212 | { | ||
213 | static u8 clock_config [] = { 0x89, 0x38, 0x38 }; | ||
214 | static u8 reset [] = { 0x50, 0x80 }; | ||
215 | static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; | ||
216 | static u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF, | ||
217 | 0x00, 0xFF, 0x00, 0x40, 0x40 }; | ||
218 | static u8 dntv_extra[] = { 0xB5, 0x7A }; | ||
219 | static u8 capt_range_cfg[] = { 0x75, 0x32 }; | ||
220 | |||
221 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
222 | udelay(2000); | ||
223 | mt352_write(fe, reset, sizeof(reset)); | ||
224 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
225 | |||
226 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
227 | udelay(2000); | ||
228 | mt352_write(fe, dntv_extra, sizeof(dntv_extra)); | ||
229 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int philips_fmd1216_pll_init(struct dvb_frontend *fe) | ||
235 | { | ||
236 | struct cx8802_dev *dev= fe->dvb->priv; | ||
237 | |||
238 | /* this message is to set up ATC and ALC */ | ||
239 | static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; | ||
240 | struct i2c_msg msg = | ||
241 | { .addr = dev->core->pll_addr, .flags = 0, | ||
242 | .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; | ||
243 | int err; | ||
244 | |||
245 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | ||
246 | if (err < 0) | ||
247 | return err; | ||
248 | else | ||
249 | return -EREMOTEIO; | ||
250 | } | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe, | ||
256 | struct dvb_frontend_parameters* params, | ||
257 | u8* pllbuf) | ||
258 | { | ||
259 | struct cx8802_dev *dev= fe->dvb->priv; | ||
260 | struct i2c_msg msg = | ||
261 | { .addr = dev->core->pll_addr, .flags = 0, | ||
262 | .buf = pllbuf+1, .len = 4 }; | ||
263 | int err; | ||
264 | |||
265 | /* Switch PLL to DVB mode */ | ||
266 | err = philips_fmd1216_pll_init(fe); | ||
267 | if (err) | ||
268 | return err; | ||
269 | |||
270 | /* Tune PLL */ | ||
271 | pllbuf[0] = dev->core->pll_addr << 1; | ||
272 | dvb_pll_configure(dev->core->pll_desc, pllbuf+1, | ||
273 | params->frequency, | ||
274 | params->u.ofdm.bandwidth); | ||
275 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | ||
276 | printk(KERN_WARNING "cx88-dvb: %s error " | ||
277 | "(addr %02x <- %02x, err = %i)\n", | ||
278 | __FUNCTION__, pllbuf[0], pllbuf[1], err); | ||
279 | if (err < 0) | ||
280 | return err; | ||
281 | else | ||
282 | return -EREMOTEIO; | ||
283 | } | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static struct mt352_config dntv_live_dvbt_pro_config = { | ||
289 | .demod_address = 0x0f, | ||
290 | .no_tuner = 1, | ||
291 | .demod_init = dntv_live_dvbt_pro_demod_init, | ||
292 | .pll_set = dntv_live_dvbt_pro_pll_set, | ||
293 | }; | ||
294 | #endif | ||
175 | #endif | 295 | #endif |
176 | 296 | ||
177 | #ifdef HAVE_CX22702 | 297 | #ifdef HAVE_CX22702 |
@@ -188,6 +308,12 @@ static struct cx22702_config hauppauge_novat_config = { | |||
188 | .pll_address = 0x61, | 308 | .pll_address = 0x61, |
189 | .pll_desc = &dvb_pll_thomson_dtt759x, | 309 | .pll_desc = &dvb_pll_thomson_dtt759x, |
190 | }; | 310 | }; |
311 | static struct cx22702_config hauppauge_hvr1100_config = { | ||
312 | .demod_address = 0x63, | ||
313 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
314 | .pll_address = 0x61, | ||
315 | .pll_desc = &dvb_pll_fmd1216me, | ||
316 | }; | ||
191 | #endif | 317 | #endif |
192 | 318 | ||
193 | #ifdef HAVE_OR51132 | 319 | #ifdef HAVE_OR51132 |
@@ -314,6 +440,40 @@ static struct nxt200x_config ati_hdtvwonder = { | |||
314 | }; | 440 | }; |
315 | #endif | 441 | #endif |
316 | 442 | ||
443 | #ifdef HAVE_CX24123 | ||
444 | static int cx24123_set_ts_param(struct dvb_frontend* fe, | ||
445 | int is_punctured) | ||
446 | { | ||
447 | struct cx8802_dev *dev= fe->dvb->priv; | ||
448 | dev->ts_gen_cntrl = 0x2; | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on) | ||
453 | { | ||
454 | struct cx8802_dev *dev= fe->dvb->priv; | ||
455 | struct cx88_core *core = dev->core; | ||
456 | |||
457 | if (on) | ||
458 | cx_write(MO_GP0_IO, 0x000006f9); | ||
459 | else | ||
460 | cx_write(MO_GP0_IO, 0x000006fB); | ||
461 | } | ||
462 | |||
463 | static struct cx24123_config hauppauge_novas_config = { | ||
464 | .demod_address = 0x55, | ||
465 | .use_isl6421 = 1, | ||
466 | .set_ts_params = cx24123_set_ts_param, | ||
467 | }; | ||
468 | |||
469 | static struct cx24123_config kworld_dvbs_100_config = { | ||
470 | .demod_address = 0x15, | ||
471 | .use_isl6421 = 0, | ||
472 | .set_ts_params = cx24123_set_ts_param, | ||
473 | .enable_lnb_voltage = cx24123_enable_lnb_voltage, | ||
474 | }; | ||
475 | #endif | ||
476 | |||
317 | static int dvb_register(struct cx8802_dev *dev) | 477 | static int dvb_register(struct cx8802_dev *dev) |
318 | { | 478 | { |
319 | /* init struct videobuf_dvb */ | 479 | /* init struct videobuf_dvb */ |
@@ -329,10 +489,16 @@ static int dvb_register(struct cx8802_dev *dev) | |||
329 | break; | 489 | break; |
330 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: | 490 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
331 | case CX88_BOARD_CONEXANT_DVB_T1: | 491 | case CX88_BOARD_CONEXANT_DVB_T1: |
492 | case CX88_BOARD_KWORLD_DVB_T_CX22702: | ||
332 | case CX88_BOARD_WINFAST_DTV1000: | 493 | case CX88_BOARD_WINFAST_DTV1000: |
333 | dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, | 494 | dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, |
334 | &dev->core->i2c_adap); | 495 | &dev->core->i2c_adap); |
335 | break; | 496 | break; |
497 | case CX88_BOARD_HAUPPAUGE_HVR1100: | ||
498 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | ||
499 | dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, | ||
500 | &dev->core->i2c_adap); | ||
501 | break; | ||
336 | #endif | 502 | #endif |
337 | #ifdef HAVE_MT352 | 503 | #ifdef HAVE_MT352 |
338 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: | 504 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: |
@@ -355,6 +521,24 @@ static int dvb_register(struct cx8802_dev *dev) | |||
355 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, | 521 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, |
356 | &dev->core->i2c_adap); | 522 | &dev->core->i2c_adap); |
357 | break; | 523 | break; |
524 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | ||
525 | #ifdef HAVE_VP3054_I2C | ||
526 | dev->core->pll_addr = 0x61; | ||
527 | dev->core->pll_desc = &dvb_pll_fmd1216me; | ||
528 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config, | ||
529 | &((struct vp3054_i2c_state *)dev->card_priv)->adap); | ||
530 | #else | ||
531 | printk("%s: built without vp3054 support\n", dev->core->name); | ||
532 | #endif | ||
533 | break; | ||
534 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: | ||
535 | /* The tin box says DEE1601, but it seems to be DTT7579 | ||
536 | * compatible, with a slightly different MT352 AGC gain. */ | ||
537 | dev->core->pll_addr = 0x61; | ||
538 | dev->core->pll_desc = &dvb_pll_thomson_dtt7579; | ||
539 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual, | ||
540 | &dev->core->i2c_adap); | ||
541 | break; | ||
358 | #endif | 542 | #endif |
359 | #ifdef HAVE_OR51132 | 543 | #ifdef HAVE_OR51132 |
360 | case CX88_BOARD_PCHDTV_HD3000: | 544 | case CX88_BOARD_PCHDTV_HD3000: |
@@ -393,7 +577,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
393 | cx_set(MO_GP0_IO, 9); | 577 | cx_set(MO_GP0_IO, 9); |
394 | mdelay(200); | 578 | mdelay(200); |
395 | dev->core->pll_addr = 0x61; | 579 | dev->core->pll_addr = 0x61; |
396 | dev->core->pll_desc = &dvb_pll_thomson_dtt7611; | 580 | dev->core->pll_desc = &dvb_pll_thomson_dtt761x; |
397 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, | 581 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, |
398 | &dev->core->i2c_adap); | 582 | &dev->core->i2c_adap); |
399 | } | 583 | } |
@@ -421,6 +605,17 @@ static int dvb_register(struct cx8802_dev *dev) | |||
421 | &dev->core->i2c_adap); | 605 | &dev->core->i2c_adap); |
422 | break; | 606 | break; |
423 | #endif | 607 | #endif |
608 | #ifdef HAVE_CX24123 | ||
609 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | ||
610 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | ||
611 | dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, | ||
612 | &dev->core->i2c_adap); | ||
613 | break; | ||
614 | case CX88_BOARD_KWORLD_DVBS_100: | ||
615 | dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, | ||
616 | &dev->core->i2c_adap); | ||
617 | break; | ||
618 | #endif | ||
424 | default: | 619 | default: |
425 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", | 620 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
426 | dev->core->name); | 621 | dev->core->name); |
@@ -473,6 +668,12 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, | |||
473 | if (0 != err) | 668 | if (0 != err) |
474 | goto fail_free; | 669 | goto fail_free; |
475 | 670 | ||
671 | #ifdef HAVE_VP3054_I2C | ||
672 | err = vp3054_i2c_probe(dev); | ||
673 | if (0 != err) | ||
674 | goto fail_free; | ||
675 | #endif | ||
676 | |||
476 | /* dvb stuff */ | 677 | /* dvb stuff */ |
477 | printk("%s/2: cx2388x based dvb card\n", core->name); | 678 | printk("%s/2: cx2388x based dvb card\n", core->name); |
478 | videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, | 679 | videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, |
@@ -484,6 +685,9 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, | |||
484 | err = dvb_register(dev); | 685 | err = dvb_register(dev); |
485 | if (0 != err) | 686 | if (0 != err) |
486 | goto fail_fini; | 687 | goto fail_fini; |
688 | |||
689 | /* Maintain a reference to cx88-video can query the 8802 device. */ | ||
690 | core->dvbdev = dev; | ||
487 | return 0; | 691 | return 0; |
488 | 692 | ||
489 | fail_fini: | 693 | fail_fini: |
@@ -499,9 +703,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev) | |||
499 | { | 703 | { |
500 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); | 704 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); |
501 | 705 | ||
706 | /* Destroy any 8802 reference. */ | ||
707 | dev->core->dvbdev = NULL; | ||
708 | |||
502 | /* dvb */ | 709 | /* dvb */ |
503 | videobuf_dvb_unregister(&dev->dvb); | 710 | videobuf_dvb_unregister(&dev->dvb); |
504 | 711 | ||
712 | #ifdef HAVE_VP3054_I2C | ||
713 | vp3054_i2c_remove(dev); | ||
714 | #endif | ||
715 | |||
505 | /* common */ | 716 | /* common */ |
506 | cx8802_fini_common(dev); | 717 | cx8802_fini_common(dev); |
507 | cx88_core_put(dev->core,dev->pci); | 718 | cx88_core_put(dev->core,dev->pci); |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 4a8fb161b16a..f720901e9638 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | 31 | ||
32 | #include "cx88.h" | 32 | #include "cx88.h" |
33 | #include <media/v4l2-common.h> | ||
33 | 34 | ||
34 | static unsigned int i2c_debug = 0; | 35 | static unsigned int i2c_debug = 0; |
35 | module_param(i2c_debug, int, 0644); | 36 | module_param(i2c_debug, int, 0644); |
@@ -135,7 +136,17 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) | |||
135 | { | 136 | { |
136 | if (0 != core->i2c_rc) | 137 | if (0 != core->i2c_rc) |
137 | return; | 138 | return; |
138 | i2c_clients_command(&core->i2c_adap, cmd, arg); | 139 | |
140 | if (core->dvbdev) { | ||
141 | if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl) | ||
142 | core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); | ||
143 | |||
144 | i2c_clients_command(&core->i2c_adap, cmd, arg); | ||
145 | |||
146 | if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl) | ||
147 | core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); | ||
148 | } else | ||
149 | i2c_clients_command(&core->i2c_adap, cmd, arg); | ||
139 | } | 150 | } |
140 | 151 | ||
141 | static struct i2c_algo_bit_data cx8800_i2c_algo_template = { | 152 | static struct i2c_algo_bit_data cx8800_i2c_algo_template = { |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 461019dca901..286c85b6bdf9 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * Copyright (c) 2003 Pavel Machek | 6 | * Copyright (c) 2003 Pavel Machek |
7 | * Copyright (c) 2004 Gerd Knorr | 7 | * Copyright (c) 2004 Gerd Knorr |
8 | * Copyright (c) 2004 Chris Pascoe | 8 | * Copyright (c) 2004, 2005 Chris Pascoe |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of the GNU General Public License as published by |
@@ -29,9 +29,8 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
31 | 31 | ||
32 | #include <media/ir-common.h> | ||
33 | |||
34 | #include "cx88.h" | 32 | #include "cx88.h" |
33 | #include <media/ir-common.h> | ||
35 | 34 | ||
36 | /* ---------------------------------------------------------------------- */ | 35 | /* ---------------------------------------------------------------------- */ |
37 | 36 | ||
@@ -258,6 +257,114 @@ static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { | |||
258 | 257 | ||
259 | /* ---------------------------------------------------------------------- */ | 258 | /* ---------------------------------------------------------------------- */ |
260 | 259 | ||
260 | /* AVERTV STUDIO 303 Remote */ | ||
261 | static IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { | ||
262 | [ 0x2a ] = KEY_KP1, | ||
263 | [ 0x32 ] = KEY_KP2, | ||
264 | [ 0x3a ] = KEY_KP3, | ||
265 | [ 0x4a ] = KEY_KP4, | ||
266 | [ 0x52 ] = KEY_KP5, | ||
267 | [ 0x5a ] = KEY_KP6, | ||
268 | [ 0x6a ] = KEY_KP7, | ||
269 | [ 0x72 ] = KEY_KP8, | ||
270 | [ 0x7a ] = KEY_KP9, | ||
271 | [ 0x0e ] = KEY_KP0, | ||
272 | |||
273 | [ 0x02 ] = KEY_POWER, | ||
274 | [ 0x22 ] = KEY_VIDEO, | ||
275 | [ 0x42 ] = KEY_AUDIO, | ||
276 | [ 0x62 ] = KEY_ZOOM, | ||
277 | [ 0x0a ] = KEY_TV, | ||
278 | [ 0x12 ] = KEY_CD, | ||
279 | [ 0x1a ] = KEY_TEXT, | ||
280 | |||
281 | [ 0x16 ] = KEY_SUBTITLE, | ||
282 | [ 0x1e ] = KEY_REWIND, | ||
283 | [ 0x06 ] = KEY_PRINT, | ||
284 | |||
285 | [ 0x2e ] = KEY_SEARCH, | ||
286 | [ 0x36 ] = KEY_SLEEP, | ||
287 | [ 0x3e ] = KEY_SHUFFLE, | ||
288 | [ 0x26 ] = KEY_MUTE, | ||
289 | |||
290 | [ 0x4e ] = KEY_RECORD, | ||
291 | [ 0x56 ] = KEY_PAUSE, | ||
292 | [ 0x5e ] = KEY_STOP, | ||
293 | [ 0x46 ] = KEY_PLAY, | ||
294 | |||
295 | [ 0x6e ] = KEY_RED, | ||
296 | [ 0x0b ] = KEY_GREEN, | ||
297 | [ 0x66 ] = KEY_YELLOW, | ||
298 | [ 0x03 ] = KEY_BLUE, | ||
299 | |||
300 | [ 0x76 ] = KEY_LEFT, | ||
301 | [ 0x7e ] = KEY_RIGHT, | ||
302 | [ 0x13 ] = KEY_DOWN, | ||
303 | [ 0x1b ] = KEY_UP, | ||
304 | }; | ||
305 | |||
306 | /* ---------------------------------------------------------------------- */ | ||
307 | |||
308 | /* DigitalNow DNTV Live! DVB-T Pro Remote */ | ||
309 | static IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { | ||
310 | [ 0x16 ] = KEY_POWER, | ||
311 | [ 0x5b ] = KEY_HOME, | ||
312 | |||
313 | [ 0x55 ] = KEY_TV, /* live tv */ | ||
314 | [ 0x58 ] = KEY_TUNER, /* digital Radio */ | ||
315 | [ 0x5a ] = KEY_RADIO, /* FM radio */ | ||
316 | [ 0x59 ] = KEY_DVD, /* dvd menu */ | ||
317 | [ 0x03 ] = KEY_1, | ||
318 | [ 0x01 ] = KEY_2, | ||
319 | [ 0x06 ] = KEY_3, | ||
320 | [ 0x09 ] = KEY_4, | ||
321 | [ 0x1d ] = KEY_5, | ||
322 | [ 0x1f ] = KEY_6, | ||
323 | [ 0x0d ] = KEY_7, | ||
324 | [ 0x19 ] = KEY_8, | ||
325 | [ 0x1b ] = KEY_9, | ||
326 | [ 0x0c ] = KEY_CANCEL, | ||
327 | [ 0x15 ] = KEY_0, | ||
328 | [ 0x4a ] = KEY_CLEAR, | ||
329 | [ 0x13 ] = KEY_BACK, | ||
330 | [ 0x00 ] = KEY_TAB, | ||
331 | [ 0x4b ] = KEY_UP, | ||
332 | [ 0x4e ] = KEY_LEFT, | ||
333 | [ 0x4f ] = KEY_OK, | ||
334 | [ 0x52 ] = KEY_RIGHT, | ||
335 | [ 0x51 ] = KEY_DOWN, | ||
336 | [ 0x1e ] = KEY_VOLUMEUP, | ||
337 | [ 0x0a ] = KEY_VOLUMEDOWN, | ||
338 | [ 0x02 ] = KEY_CHANNELDOWN, | ||
339 | [ 0x05 ] = KEY_CHANNELUP, | ||
340 | [ 0x11 ] = KEY_RECORD, | ||
341 | [ 0x14 ] = KEY_PLAY, | ||
342 | [ 0x4c ] = KEY_PAUSE, | ||
343 | [ 0x1a ] = KEY_STOP, | ||
344 | [ 0x40 ] = KEY_REWIND, | ||
345 | [ 0x12 ] = KEY_FASTFORWARD, | ||
346 | [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */ | ||
347 | [ 0x42 ] = KEY_NEXTSONG, /* skip >| */ | ||
348 | [ 0x54 ] = KEY_CAMERA, /* capture */ | ||
349 | [ 0x50 ] = KEY_LANGUAGE, /* sap */ | ||
350 | [ 0x47 ] = KEY_TV2, /* pip */ | ||
351 | [ 0x4d ] = KEY_SCREEN, | ||
352 | [ 0x43 ] = KEY_SUBTITLE, | ||
353 | [ 0x10 ] = KEY_MUTE, | ||
354 | [ 0x49 ] = KEY_AUDIO, /* l/r */ | ||
355 | [ 0x07 ] = KEY_SLEEP, | ||
356 | [ 0x08 ] = KEY_VIDEO, /* a/v */ | ||
357 | [ 0x0e ] = KEY_PREVIOUS, /* recall */ | ||
358 | [ 0x45 ] = KEY_ZOOM, /* zoom + */ | ||
359 | [ 0x46 ] = KEY_ANGLE, /* zoom - */ | ||
360 | [ 0x56 ] = KEY_RED, | ||
361 | [ 0x57 ] = KEY_GREEN, | ||
362 | [ 0x5c ] = KEY_YELLOW, | ||
363 | [ 0x5d ] = KEY_BLUE, | ||
364 | }; | ||
365 | |||
366 | /* ---------------------------------------------------------------------- */ | ||
367 | |||
261 | struct cx88_IR { | 368 | struct cx88_IR { |
262 | struct cx88_core *core; | 369 | struct cx88_core *core; |
263 | struct input_dev *input; | 370 | struct input_dev *input; |
@@ -266,7 +373,7 @@ struct cx88_IR { | |||
266 | char phys[32]; | 373 | char phys[32]; |
267 | 374 | ||
268 | /* sample from gpio pin 16 */ | 375 | /* sample from gpio pin 16 */ |
269 | int sampling; | 376 | u32 sampling; |
270 | u32 samples[16]; | 377 | u32 samples[16]; |
271 | int scount; | 378 | int scount; |
272 | unsigned long release; | 379 | unsigned long release; |
@@ -384,10 +491,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
384 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: | 491 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
385 | ir_codes = ir_codes_cinergy_1400; | 492 | ir_codes = ir_codes_cinergy_1400; |
386 | ir_type = IR_TYPE_PD; | 493 | ir_type = IR_TYPE_PD; |
387 | ir->sampling = 1; | 494 | ir->sampling = 0xeb04; /* address */ |
388 | break; | 495 | break; |
389 | case CX88_BOARD_HAUPPAUGE: | 496 | case CX88_BOARD_HAUPPAUGE: |
390 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 497 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
498 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | ||
499 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | ||
500 | case CX88_BOARD_HAUPPAUGE_HVR1100: | ||
391 | ir_codes = ir_codes_hauppauge_new; | 501 | ir_codes = ir_codes_hauppauge_new; |
392 | ir_type = IR_TYPE_RC5; | 502 | ir_type = IR_TYPE_RC5; |
393 | ir->sampling = 1; | 503 | ir->sampling = 1; |
@@ -427,6 +537,19 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
427 | ir->mask_keyup = 0x40; | 537 | ir->mask_keyup = 0x40; |
428 | ir->polling = 1; /* ms */ | 538 | ir->polling = 1; /* ms */ |
429 | break; | 539 | break; |
540 | case CX88_BOARD_AVERTV_303: | ||
541 | case CX88_BOARD_AVERTV_STUDIO_303: | ||
542 | ir_codes = ir_codes_avertv_303; | ||
543 | ir->gpio_addr = MO_GP2_IO; | ||
544 | ir->mask_keycode = 0xfb; | ||
545 | ir->mask_keydown = 0x02; | ||
546 | ir->polling = 50; /* ms */ | ||
547 | break; | ||
548 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | ||
549 | ir_codes = ir_codes_dntv_live_dvbt_pro; | ||
550 | ir_type = IR_TYPE_PD; | ||
551 | ir->sampling = 0xff00; /* address */ | ||
552 | break; | ||
430 | } | 553 | } |
431 | 554 | ||
432 | if (NULL == ir_codes) { | 555 | if (NULL == ir_codes) { |
@@ -484,6 +607,10 @@ int cx88_ir_fini(struct cx88_core *core) | |||
484 | if (NULL == ir) | 607 | if (NULL == ir) |
485 | return 0; | 608 | return 0; |
486 | 609 | ||
610 | if (ir->sampling) { | ||
611 | cx_write(MO_DDSCFG_IO, 0x0); | ||
612 | core->pci_irqmask &= ~(1 << 18); | ||
613 | } | ||
487 | if (ir->polling) { | 614 | if (ir->polling) { |
488 | del_timer(&ir->timer); | 615 | del_timer(&ir->timer); |
489 | flush_scheduled_work(); | 616 | flush_scheduled_work(); |
@@ -535,6 +662,7 @@ void cx88_ir_irq(struct cx88_core *core) | |||
535 | /* decode it */ | 662 | /* decode it */ |
536 | switch (core->board) { | 663 | switch (core->board) { |
537 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: | 664 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
665 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | ||
538 | ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); | 666 | ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); |
539 | 667 | ||
540 | if (ircode == 0xffffffff) { /* decoding error */ | 668 | if (ircode == 0xffffffff) { /* decoding error */ |
@@ -550,7 +678,7 @@ void cx88_ir_irq(struct cx88_core *core) | |||
550 | break; | 678 | break; |
551 | } | 679 | } |
552 | 680 | ||
553 | if ((ircode & 0xffff) != 0xeb04) { /* wrong address */ | 681 | if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */ |
554 | ir_dprintk("pulse distance decoded wrong address\n"); | 682 | ir_dprintk("pulse distance decoded wrong address\n"); |
555 | break; | 683 | break; |
556 | } | 684 | } |
@@ -567,6 +695,8 @@ void cx88_ir_irq(struct cx88_core *core) | |||
567 | break; | 695 | break; |
568 | case CX88_BOARD_HAUPPAUGE: | 696 | case CX88_BOARD_HAUPPAUGE: |
569 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 697 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
698 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | ||
699 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | ||
570 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); | 700 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); |
571 | ir_dprintk("biphase decoded: %x\n", ircode); | 701 | ir_dprintk("biphase decoded: %x\n", ircode); |
572 | if ((ircode & 0xfffff000) != 0x3000) | 702 | if ((ircode & 0xfffff000) != 0x3000) |
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 35e6d0c2b872..c79cc1d2bf8b 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -78,6 +78,11 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
78 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: | 78 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: |
79 | cx_write(TS_SOP_STAT, 1<<13); | 79 | cx_write(TS_SOP_STAT, 1<<13); |
80 | break; | 80 | break; |
81 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | ||
82 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | ||
83 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ | ||
84 | udelay(100); | ||
85 | break; | ||
81 | default: | 86 | default: |
82 | cx_write(TS_SOP_STAT, 0x00); | 87 | cx_write(TS_SOP_STAT, 0x00); |
83 | break; | 88 | break; |
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index a1b120c8a9b5..24118e43e73a 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -132,14 +132,22 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) | |||
132 | { | 132 | { |
133 | u32 volume; | 133 | u32 volume; |
134 | 134 | ||
135 | #ifndef USING_CX88_ALSA | ||
135 | /* restart dma; This avoids buzz in NICAM and is good in others */ | 136 | /* restart dma; This avoids buzz in NICAM and is good in others */ |
136 | cx88_stop_audio_dma(core); | 137 | cx88_stop_audio_dma(core); |
138 | #endif | ||
137 | cx_write(AUD_RATE_THRES_DMD, 0x000000C0); | 139 | cx_write(AUD_RATE_THRES_DMD, 0x000000C0); |
140 | #ifndef USING_CX88_ALSA | ||
138 | cx88_start_audio_dma(core); | 141 | cx88_start_audio_dma(core); |
142 | #endif | ||
139 | 143 | ||
140 | if (cx88_boards[core->board].blackbird) { | 144 | if (cx88_boards[core->board].blackbird) { |
141 | /* sets sound input from external adc */ | 145 | /* sets sound input from external adc */ |
142 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | 146 | if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) |
147 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | ||
148 | else | ||
149 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | ||
150 | |||
143 | cx_write(AUD_I2SINPUTCNTL, 4); | 151 | cx_write(AUD_I2SINPUTCNTL, 4); |
144 | cx_write(AUD_BAUDRATE, 1); | 152 | cx_write(AUD_BAUDRATE, 1); |
145 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ | 153 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 24a48f8a48c1..9a02515fe18b 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/div64.h> | 33 | #include <asm/div64.h> |
34 | 34 | ||
35 | #include "cx88.h" | 35 | #include "cx88.h" |
36 | #include <media/v4l2-common.h> | ||
36 | 37 | ||
37 | /* Include V4L1 specific functions. Should be removed soon */ | 38 | /* Include V4L1 specific functions. Should be removed soon */ |
38 | #include <linux/videodev.h> | 39 | #include <linux/videodev.h> |
@@ -240,7 +241,7 @@ static struct cx88_ctrl cx8800_ctls[] = { | |||
240 | .minimum = 0, | 241 | .minimum = 0, |
241 | .maximum = 0xff, | 242 | .maximum = 0xff, |
242 | .step = 1, | 243 | .step = 1, |
243 | .default_value = 0, | 244 | .default_value = 0x3f, |
244 | .type = V4L2_CTRL_TYPE_INTEGER, | 245 | .type = V4L2_CTRL_TYPE_INTEGER, |
245 | }, | 246 | }, |
246 | .off = 0, | 247 | .off = 0, |
@@ -271,7 +272,7 @@ static struct cx88_ctrl cx8800_ctls[] = { | |||
271 | .minimum = 0, | 272 | .minimum = 0, |
272 | .maximum = 0xff, | 273 | .maximum = 0xff, |
273 | .step = 1, | 274 | .step = 1, |
274 | .default_value = 0, | 275 | .default_value = 0x7f, |
275 | .type = V4L2_CTRL_TYPE_INTEGER, | 276 | .type = V4L2_CTRL_TYPE_INTEGER, |
276 | }, | 277 | }, |
277 | .off = 0, | 278 | .off = 0, |
@@ -285,6 +286,7 @@ static struct cx88_ctrl cx8800_ctls[] = { | |||
285 | .name = "Mute", | 286 | .name = "Mute", |
286 | .minimum = 0, | 287 | .minimum = 0, |
287 | .maximum = 1, | 288 | .maximum = 1, |
289 | .default_value = 1, | ||
288 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 290 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
289 | }, | 291 | }, |
290 | .reg = AUD_VOL_CTL, | 292 | .reg = AUD_VOL_CTL, |
@@ -298,7 +300,7 @@ static struct cx88_ctrl cx8800_ctls[] = { | |||
298 | .minimum = 0, | 300 | .minimum = 0, |
299 | .maximum = 0x3f, | 301 | .maximum = 0x3f, |
300 | .step = 1, | 302 | .step = 1, |
301 | .default_value = 0, | 303 | .default_value = 0x1f, |
302 | .type = V4L2_CTRL_TYPE_INTEGER, | 304 | .type = V4L2_CTRL_TYPE_INTEGER, |
303 | }, | 305 | }, |
304 | .reg = AUD_VOL_CTL, | 306 | .reg = AUD_VOL_CTL, |
@@ -917,6 +919,9 @@ static int get_control(struct cx88_core *core, struct v4l2_control *ctl) | |||
917 | ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift; | 919 | ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift; |
918 | break; | 920 | break; |
919 | } | 921 | } |
922 | printk("get_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", | ||
923 | ctl->id, c->reg, ctl->value, | ||
924 | c->mask, c->sreg ? " [shadowed]" : ""); | ||
920 | return 0; | 925 | return 0; |
921 | } | 926 | } |
922 | 927 | ||
@@ -925,13 +930,13 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) | |||
925 | { | 930 | { |
926 | /* struct cx88_core *core = dev->core; */ | 931 | /* struct cx88_core *core = dev->core; */ |
927 | struct cx88_ctrl *c = NULL; | 932 | struct cx88_ctrl *c = NULL; |
928 | u32 v_sat_value; | 933 | u32 value,mask; |
929 | u32 value; | ||
930 | int i; | 934 | int i; |
931 | 935 | for (i = 0; i < CX8800_CTLS; i++) { | |
932 | for (i = 0; i < CX8800_CTLS; i++) | 936 | if (cx8800_ctls[i].v.id == ctl->id) { |
933 | if (cx8800_ctls[i].v.id == ctl->id) | ||
934 | c = &cx8800_ctls[i]; | 937 | c = &cx8800_ctls[i]; |
938 | } | ||
939 | } | ||
935 | if (NULL == c) | 940 | if (NULL == c) |
936 | return -EINVAL; | 941 | return -EINVAL; |
937 | 942 | ||
@@ -939,6 +944,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) | |||
939 | ctl->value = c->v.minimum; | 944 | ctl->value = c->v.minimum; |
940 | if (ctl->value > c->v.maximum) | 945 | if (ctl->value > c->v.maximum) |
941 | ctl->value = c->v.maximum; | 946 | ctl->value = c->v.maximum; |
947 | mask=c->mask; | ||
942 | switch (ctl->id) { | 948 | switch (ctl->id) { |
943 | case V4L2_CID_AUDIO_BALANCE: | 949 | case V4L2_CID_AUDIO_BALANCE: |
944 | value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value; | 950 | value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value; |
@@ -948,56 +954,44 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) | |||
948 | break; | 954 | break; |
949 | case V4L2_CID_SATURATION: | 955 | case V4L2_CID_SATURATION: |
950 | /* special v_sat handling */ | 956 | /* special v_sat handling */ |
951 | v_sat_value = ctl->value - (0x7f - 0x5a); | 957 | |
952 | if (v_sat_value > 0xff) | 958 | value = ((ctl->value - c->off) << c->shift) & c->mask; |
953 | v_sat_value = 0xff; | 959 | |
954 | if (v_sat_value < 0x00) | 960 | if (core->tvnorm->id & V4L2_STD_SECAM) { |
955 | v_sat_value = 0x00; | 961 | /* For SECAM, both U and V sat should be equal */ |
956 | cx_andor(MO_UV_SATURATION, 0xff00, v_sat_value << 8); | 962 | value=value<<8|value; |
957 | /* fall through to default route for u_sat */ | 963 | } else { |
964 | /* Keeps U Saturation proportional to V Sat */ | ||
965 | value=(value*0x5a)/0x7f<<8|value; | ||
966 | } | ||
967 | mask=0xffff; | ||
968 | break; | ||
958 | default: | 969 | default: |
959 | value = ((ctl->value - c->off) << c->shift) & c->mask; | 970 | value = ((ctl->value - c->off) << c->shift) & c->mask; |
960 | break; | 971 | break; |
961 | } | 972 | } |
962 | dprintk(1,"set_control id=0x%X reg=0x%x val=0x%x%s\n", | 973 | printk("set_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", |
963 | ctl->id, c->reg, value, c->sreg ? " [shadowed]" : ""); | 974 | ctl->id, c->reg, value, |
975 | mask, c->sreg ? " [shadowed]" : ""); | ||
964 | if (c->sreg) { | 976 | if (c->sreg) { |
965 | cx_sandor(c->sreg, c->reg, c->mask, value); | 977 | cx_sandor(c->sreg, c->reg, mask, value); |
966 | } else { | 978 | } else { |
967 | cx_andor(c->reg, c->mask, value); | 979 | cx_andor(c->reg, mask, value); |
968 | } | 980 | } |
969 | return 0; | 981 | return 0; |
970 | } | 982 | } |
971 | 983 | ||
972 | /* static void init_controls(struct cx8800_dev *dev) */ | ||
973 | static void init_controls(struct cx88_core *core) | 984 | static void init_controls(struct cx88_core *core) |
974 | { | 985 | { |
975 | static struct v4l2_control mute = { | 986 | struct v4l2_control ctrl; |
976 | .id = V4L2_CID_AUDIO_MUTE, | 987 | int i; |
977 | .value = 1, | ||
978 | }; | ||
979 | static struct v4l2_control volume = { | ||
980 | .id = V4L2_CID_AUDIO_VOLUME, | ||
981 | .value = 0x3f, | ||
982 | }; | ||
983 | static struct v4l2_control hue = { | ||
984 | .id = V4L2_CID_HUE, | ||
985 | .value = 0x80, | ||
986 | }; | ||
987 | static struct v4l2_control contrast = { | ||
988 | .id = V4L2_CID_CONTRAST, | ||
989 | .value = 0x80, | ||
990 | }; | ||
991 | static struct v4l2_control brightness = { | ||
992 | .id = V4L2_CID_BRIGHTNESS, | ||
993 | .value = 0x80, | ||
994 | }; | ||
995 | 988 | ||
996 | set_control(core,&mute); | 989 | for (i = 0; i < CX8800_CTLS; i++) { |
997 | set_control(core,&volume); | 990 | ctrl.id=cx8800_ctls[i].v.id; |
998 | set_control(core,&hue); | 991 | ctrl.value=cx8800_ctls[i].v.default_value |
999 | set_control(core,&contrast); | 992 | +cx8800_ctls[i].off; |
1000 | set_control(core,&brightness); | 993 | set_control(core, &ctrl); |
994 | } | ||
1001 | } | 995 | } |
1002 | 996 | ||
1003 | /* ------------------------------------------------------------------ */ | 997 | /* ------------------------------------------------------------------ */ |
@@ -1125,7 +1119,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, | |||
1125 | int err; | 1119 | int err; |
1126 | 1120 | ||
1127 | if (video_debug > 1) | 1121 | if (video_debug > 1) |
1128 | cx88_print_ioctl(core->name,cmd); | 1122 | v4l_print_ioctl(core->name,cmd); |
1129 | switch (cmd) { | 1123 | switch (cmd) { |
1130 | 1124 | ||
1131 | /* --- capabilities ------------------------------------------ */ | 1125 | /* --- capabilities ------------------------------------------ */ |
@@ -1261,7 +1255,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | |||
1261 | 1255 | ||
1262 | dprintk( 1, "CORE IOCTL: 0x%x\n", cmd ); | 1256 | dprintk( 1, "CORE IOCTL: 0x%x\n", cmd ); |
1263 | if (video_debug > 1) | 1257 | if (video_debug > 1) |
1264 | cx88_print_ioctl(core->name,cmd); | 1258 | v4l_print_ioctl(core->name,cmd); |
1265 | 1259 | ||
1266 | switch (cmd) { | 1260 | switch (cmd) { |
1267 | /* ---------- tv norms ---------- */ | 1261 | /* ---------- tv norms ---------- */ |
@@ -1481,7 +1475,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, | |||
1481 | struct cx88_core *core = dev->core; | 1475 | struct cx88_core *core = dev->core; |
1482 | 1476 | ||
1483 | if (video_debug > 1) | 1477 | if (video_debug > 1) |
1484 | cx88_print_ioctl(core->name,cmd); | 1478 | v4l_print_ioctl(core->name,cmd); |
1485 | 1479 | ||
1486 | switch (cmd) { | 1480 | switch (cmd) { |
1487 | case VIDIOC_QUERYCAP: | 1481 | case VIDIOC_QUERYCAP: |
@@ -1740,6 +1734,7 @@ static struct file_operations video_fops = | |||
1740 | .poll = video_poll, | 1734 | .poll = video_poll, |
1741 | .mmap = video_mmap, | 1735 | .mmap = video_mmap, |
1742 | .ioctl = video_ioctl, | 1736 | .ioctl = video_ioctl, |
1737 | .compat_ioctl = v4l_compat_ioctl32, | ||
1743 | .llseek = no_llseek, | 1738 | .llseek = no_llseek, |
1744 | }; | 1739 | }; |
1745 | 1740 | ||
@@ -1767,6 +1762,7 @@ static struct file_operations radio_fops = | |||
1767 | .open = video_open, | 1762 | .open = video_open, |
1768 | .release = video_release, | 1763 | .release = video_release, |
1769 | .ioctl = radio_ioctl, | 1764 | .ioctl = radio_ioctl, |
1765 | .compat_ioctl = v4l_compat_ioctl32, | ||
1770 | .llseek = no_llseek, | 1766 | .llseek = no_llseek, |
1771 | }; | 1767 | }; |
1772 | 1768 | ||
@@ -1928,8 +1924,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1928 | 1924 | ||
1929 | /* initial device configuration */ | 1925 | /* initial device configuration */ |
1930 | down(&core->lock); | 1926 | down(&core->lock); |
1931 | init_controls(core); | ||
1932 | cx88_set_tvnorm(core,tvnorms); | 1927 | cx88_set_tvnorm(core,tvnorms); |
1928 | init_controls(core); | ||
1933 | video_mux(core,0); | 1929 | video_mux(core,0); |
1934 | up(&core->lock); | 1930 | up(&core->lock); |
1935 | 1931 | ||
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c new file mode 100644 index 000000000000..372cd29cedbd --- /dev/null +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c | |||
@@ -0,0 +1,173 @@ | |||
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/moduleparam.h> | ||
27 | #include <linux/init.h> | ||
28 | |||
29 | #include <asm/io.h> | ||
30 | |||
31 | #include "cx88.h" | ||
32 | #include "cx88-vp3054-i2c.h" | ||
33 | |||
34 | |||
35 | /* ----------------------------------------------------------------------- */ | ||
36 | |||
37 | static void vp3054_bit_setscl(void *data, int state) | ||
38 | { | ||
39 | struct cx8802_dev *dev = data; | ||
40 | struct cx88_core *core = dev->core; | ||
41 | struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; | ||
42 | |||
43 | if (state) { | ||
44 | vp3054_i2c->state |= 0x0001; /* SCL high */ | ||
45 | vp3054_i2c->state &= ~0x0100; /* external pullup */ | ||
46 | } else { | ||
47 | vp3054_i2c->state &= ~0x0001; /* SCL low */ | ||
48 | vp3054_i2c->state |= 0x0100; /* drive pin */ | ||
49 | } | ||
50 | cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state); | ||
51 | cx_read(MO_GP0_IO); | ||
52 | } | ||
53 | |||
54 | static void vp3054_bit_setsda(void *data, int state) | ||
55 | { | ||
56 | struct cx8802_dev *dev = data; | ||
57 | struct cx88_core *core = dev->core; | ||
58 | struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; | ||
59 | |||
60 | if (state) { | ||
61 | vp3054_i2c->state |= 0x0002; /* SDA high */ | ||
62 | vp3054_i2c->state &= ~0x0200; /* tristate pin */ | ||
63 | } else { | ||
64 | vp3054_i2c->state &= ~0x0002; /* SDA low */ | ||
65 | vp3054_i2c->state |= 0x0200; /* drive pin */ | ||
66 | } | ||
67 | cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state); | ||
68 | cx_read(MO_GP0_IO); | ||
69 | } | ||
70 | |||
71 | static int vp3054_bit_getscl(void *data) | ||
72 | { | ||
73 | struct cx8802_dev *dev = data; | ||
74 | struct cx88_core *core = dev->core; | ||
75 | u32 state; | ||
76 | |||
77 | state = cx_read(MO_GP0_IO); | ||
78 | return (state & 0x01) ? 1 : 0; | ||
79 | } | ||
80 | |||
81 | static int vp3054_bit_getsda(void *data) | ||
82 | { | ||
83 | struct cx8802_dev *dev = data; | ||
84 | struct cx88_core *core = dev->core; | ||
85 | u32 state; | ||
86 | |||
87 | state = cx_read(MO_GP0_IO); | ||
88 | return (state & 0x02) ? 1 : 0; | ||
89 | } | ||
90 | |||
91 | /* ----------------------------------------------------------------------- */ | ||
92 | |||
93 | static struct i2c_algo_bit_data vp3054_i2c_algo_template = { | ||
94 | .setsda = vp3054_bit_setsda, | ||
95 | .setscl = vp3054_bit_setscl, | ||
96 | .getsda = vp3054_bit_getsda, | ||
97 | .getscl = vp3054_bit_getscl, | ||
98 | .udelay = 16, | ||
99 | .mdelay = 10, | ||
100 | .timeout = 200, | ||
101 | }; | ||
102 | |||
103 | /* ----------------------------------------------------------------------- */ | ||
104 | |||
105 | static struct i2c_adapter vp3054_i2c_adap_template = { | ||
106 | .name = "cx2388x", | ||
107 | .owner = THIS_MODULE, | ||
108 | .id = I2C_HW_B_CX2388x, | ||
109 | }; | ||
110 | |||
111 | static struct i2c_client vp3054_i2c_client_template = { | ||
112 | .name = "VP-3054", | ||
113 | }; | ||
114 | |||
115 | int vp3054_i2c_probe(struct cx8802_dev *dev) | ||
116 | { | ||
117 | struct cx88_core *core = dev->core; | ||
118 | struct vp3054_i2c_state *vp3054_i2c; | ||
119 | int rc; | ||
120 | |||
121 | if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) | ||
122 | return 0; | ||
123 | |||
124 | dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL); | ||
125 | if (dev->card_priv == NULL) | ||
126 | return -ENOMEM; | ||
127 | vp3054_i2c = dev->card_priv; | ||
128 | |||
129 | memcpy(&vp3054_i2c->adap, &vp3054_i2c_adap_template, | ||
130 | sizeof(vp3054_i2c->adap)); | ||
131 | memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, | ||
132 | sizeof(vp3054_i2c->algo)); | ||
133 | memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template, | ||
134 | sizeof(vp3054_i2c->client)); | ||
135 | |||
136 | vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL; | ||
137 | |||
138 | vp3054_i2c->adap.dev.parent = &dev->pci->dev; | ||
139 | strlcpy(vp3054_i2c->adap.name, core->name, | ||
140 | sizeof(vp3054_i2c->adap.name)); | ||
141 | vp3054_i2c->algo.data = dev; | ||
142 | i2c_set_adapdata(&vp3054_i2c->adap, dev); | ||
143 | vp3054_i2c->adap.algo_data = &vp3054_i2c->algo; | ||
144 | vp3054_i2c->client.adapter = &vp3054_i2c->adap; | ||
145 | |||
146 | vp3054_bit_setscl(dev,1); | ||
147 | vp3054_bit_setsda(dev,1); | ||
148 | |||
149 | rc = i2c_bit_add_bus(&vp3054_i2c->adap); | ||
150 | if (0 != rc) { | ||
151 | printk("%s: vp3054_i2c register FAILED\n", core->name); | ||
152 | |||
153 | kfree(dev->card_priv); | ||
154 | dev->card_priv = NULL; | ||
155 | } | ||
156 | |||
157 | return rc; | ||
158 | } | ||
159 | |||
160 | void vp3054_i2c_remove(struct cx8802_dev *dev) | ||
161 | { | ||
162 | struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; | ||
163 | |||
164 | if (vp3054_i2c == NULL || | ||
165 | dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) | ||
166 | return; | ||
167 | |||
168 | i2c_bit_del_bus(&vp3054_i2c->adap); | ||
169 | kfree(vp3054_i2c); | ||
170 | } | ||
171 | |||
172 | EXPORT_SYMBOL(vp3054_i2c_probe); | ||
173 | EXPORT_SYMBOL(vp3054_i2c_remove); | ||
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h new file mode 100644 index 000000000000..b7a0a04d2423 --- /dev/null +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h | |||
@@ -0,0 +1,35 @@ | |||
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 | /* ----------------------------------------------------------------------- */ | ||
26 | struct vp3054_i2c_state { | ||
27 | struct i2c_adapter adap; | ||
28 | struct i2c_algo_bit_data algo; | ||
29 | struct i2c_client client; | ||
30 | u32 state; | ||
31 | }; | ||
32 | |||
33 | /* ----------------------------------------------------------------------- */ | ||
34 | int vp3054_i2c_probe(struct cx8802_dev *dev); | ||
35 | void vp3054_i2c_remove(struct cx8802_dev *dev); | ||
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 77beafc5c327..e9fd55b57fa6 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -179,6 +179,14 @@ extern struct sram_channel cx88_sram_channels[]; | |||
179 | #define CX88_BOARD_ATI_HDTVWONDER 34 | 179 | #define CX88_BOARD_ATI_HDTVWONDER 34 |
180 | #define CX88_BOARD_WINFAST_DTV1000 35 | 180 | #define CX88_BOARD_WINFAST_DTV1000 35 |
181 | #define CX88_BOARD_AVERTV_303 36 | 181 | #define CX88_BOARD_AVERTV_303 36 |
182 | #define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1 37 | ||
183 | #define CX88_BOARD_HAUPPAUGE_NOVASE2_S1 38 | ||
184 | #define CX88_BOARD_KWORLD_DVBS_100 39 | ||
185 | #define CX88_BOARD_HAUPPAUGE_HVR1100 40 | ||
186 | #define CX88_BOARD_HAUPPAUGE_HVR1100LP 41 | ||
187 | #define CX88_BOARD_DNTV_LIVE_DVB_T_PRO 42 | ||
188 | #define CX88_BOARD_KWORLD_DVB_T_CX22702 43 | ||
189 | #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44 | ||
182 | 190 | ||
183 | enum cx88_itype { | 191 | enum cx88_itype { |
184 | CX88_VMUX_COMPOSITE1 = 1, | 192 | CX88_VMUX_COMPOSITE1 = 1, |
@@ -280,6 +288,9 @@ struct cx88_core { | |||
280 | unsigned int tda9887_conf; | 288 | unsigned int tda9887_conf; |
281 | unsigned int has_radio; | 289 | unsigned int has_radio; |
282 | 290 | ||
291 | /* Supported V4L _STD_ tuner formats */ | ||
292 | unsigned int tuner_formats; | ||
293 | |||
283 | /* config info -- dvb */ | 294 | /* config info -- dvb */ |
284 | struct dvb_pll_desc *pll_desc; | 295 | struct dvb_pll_desc *pll_desc; |
285 | unsigned int pll_addr; | 296 | unsigned int pll_addr; |
@@ -301,6 +312,9 @@ struct cx88_core { | |||
301 | 312 | ||
302 | /* various v4l controls */ | 313 | /* various v4l controls */ |
303 | u32 freq; | 314 | u32 freq; |
315 | |||
316 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ | ||
317 | struct cx8802_dev *dvbdev; | ||
304 | }; | 318 | }; |
305 | 319 | ||
306 | struct cx8800_dev; | 320 | struct cx8800_dev; |
@@ -411,6 +425,8 @@ struct cx8802_dev { | |||
411 | struct videobuf_dvb dvb; | 425 | struct videobuf_dvb dvb; |
412 | void* fe_handle; | 426 | void* fe_handle; |
413 | int (*fe_release)(void *handle); | 427 | int (*fe_release)(void *handle); |
428 | |||
429 | void *card_priv; | ||
414 | /* for switching modulation types */ | 430 | /* for switching modulation types */ |
415 | unsigned char ts_gen_cntrl; | 431 | unsigned char ts_gen_cntrl; |
416 | 432 | ||
@@ -447,7 +463,6 @@ struct cx8802_dev { | |||
447 | 463 | ||
448 | extern void cx88_print_irqbits(char *name, char *tag, char **strings, | 464 | extern void cx88_print_irqbits(char *name, char *tag, char **strings, |
449 | u32 bits, u32 mask); | 465 | u32 bits, u32 mask); |
450 | extern void cx88_print_ioctl(char *name, unsigned int cmd); | ||
451 | 466 | ||
452 | extern int cx88_core_irq(struct cx88_core *core, u32 status); | 467 | extern int cx88_core_irq(struct cx88_core *core, u32 status); |
453 | extern void cx88_wakeup(struct cx88_core *core, | 468 | extern void cx88_wakeup(struct cx88_core *core, |