diff options
author | Sri Deevi <Srinivasa.Deevi@conexant.com> | 2009-03-03 12:37:50 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-04-06 20:44:01 -0400 |
commit | e0d3bafd02586cfde286c320f56906fd9fa8d256 (patch) | |
tree | bf9a37d90b902dfcc9d37a6f252c8c97de1c40ff /drivers/media/video/cx231xx | |
parent | 95b14fb23b543e0a9213b4ba3cc4fc640d9e453f (diff) |
V4L/DVB (10954): Add cx231xx USB driver
Signed-off-by: Srinivasa Deevi <srinivasa.deevi@conexant.com>
[mchehab@redhat.com: Remove the Kconfig changes, to avoid git breakages]
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx231xx')
-rw-r--r-- | drivers/media/video/cx231xx/Kconfig | 35 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/Makefile | 15 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-audio.c | 581 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-avcore.c | 2289 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-cards.c | 935 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-conf-reg.h | 491 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-core.c | 1167 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-dvb.c | 565 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-i2c.c | 577 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-input.c | 250 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-reg.h | 1574 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-vbi.c | 693 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-vbi.h | 61 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-video.c | 2440 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx.h | 762 |
15 files changed, 12435 insertions, 0 deletions
diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig new file mode 100644 index 000000000000..0f0e2b9d9853 --- /dev/null +++ b/drivers/media/video/cx231xx/Kconfig | |||
@@ -0,0 +1,35 @@ | |||
1 | config VIDEO_CX231XX | ||
2 | tristate "Conexant cx231xx USB video capture support" | ||
3 | depends on VIDEO_DEV && I2C && INPUT | ||
4 | select VIDEO_TUNER | ||
5 | select VIDEO_TVEEPROM | ||
6 | select VIDEO_IR | ||
7 | select VIDEOBUF_VMALLOC | ||
8 | select VIDEO_CX25840 | ||
9 | select VIDEO_CX231XX_ALSA | ||
10 | |||
11 | ---help--- | ||
12 | This is a video4linux driver for Conexant 231xx USB based TV cards. | ||
13 | |||
14 | To compile this driver as a module, choose M here: the | ||
15 | module will be called cx231xx | ||
16 | |||
17 | config VIDEO_CX231XX_ALSA | ||
18 | tristate "Conexant Cx231xx ALSA audio module" | ||
19 | depends on VIDEO_CX231XX && SND | ||
20 | select SND_PCM | ||
21 | |||
22 | ---help--- | ||
23 | This is an ALSA driver for Cx231xx USB based TV cards. | ||
24 | |||
25 | To compile this driver as a module, choose M here: the | ||
26 | module will be called cx231xx-alsa | ||
27 | |||
28 | config VIDEO_CX231XX_DVB | ||
29 | tristate "DVB/ATSC Support for Cx231xx based TV cards" | ||
30 | depends on VIDEO_CX231XX && DVB_CORE | ||
31 | select VIDEOBUF_DVB | ||
32 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE | ||
33 | ---help--- | ||
34 | This adds support for DVB cards based on the | ||
35 | Conexant cx231xx chips. | ||
diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile new file mode 100644 index 000000000000..2590a09f3442 --- /dev/null +++ b/drivers/media/video/cx231xx/Makefile | |||
@@ -0,0 +1,15 @@ | |||
1 | cx231xx-objs := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \ | ||
2 | cx231xx-avcore.o cx231xx-pcb-config.o cx231xx-vbi.o | ||
3 | |||
4 | cx231xx-alsa-objs := cx231xx-audio.o | ||
5 | |||
6 | |||
7 | obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o | ||
8 | obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o | ||
9 | obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o | ||
10 | |||
11 | EXTRA_CFLAGS += -Idrivers/media/video | ||
12 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | ||
13 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | ||
14 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | ||
15 | |||
diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c new file mode 100644 index 000000000000..e4335e2a4103 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-audio.c | |||
@@ -0,0 +1,581 @@ | |||
1 | /* | ||
2 | * Conexant Cx231xx audio extension | ||
3 | * | ||
4 | * Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | * Based on em28xx driver | ||
6 | * | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/usb.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/sound.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/soundcard.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/vmalloc.h> | ||
31 | #include <linux/proc_fs.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <sound/core.h> | ||
34 | #include <sound/pcm.h> | ||
35 | #include <sound/pcm_params.h> | ||
36 | #include <sound/info.h> | ||
37 | #include <sound/initval.h> | ||
38 | #include <sound/control.h> | ||
39 | #include <media/v4l2-common.h> | ||
40 | #include "cx231xx.h" | ||
41 | #include "cx231xx-pcb-config.h" | ||
42 | |||
43 | static int debug; | ||
44 | module_param(debug, int, 0644); | ||
45 | MODULE_PARM_DESC(debug, "activates debug info"); | ||
46 | |||
47 | #define dprintk(fmt, arg...) do { \ | ||
48 | if (debug) \ | ||
49 | printk(KERN_INFO "cx231xx-audio %s: " fmt, \ | ||
50 | __func__, ##arg); \ | ||
51 | } while (0) | ||
52 | |||
53 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
54 | |||
55 | static int cx231xx_isoc_audio_deinit(struct cx231xx *dev) | ||
56 | { | ||
57 | int i; | ||
58 | |||
59 | dprintk("Stopping isoc\n"); | ||
60 | |||
61 | |||
62 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { | ||
63 | if(dev->adev.urb[i]) { | ||
64 | if (!irqs_disabled()) | ||
65 | usb_kill_urb(dev->adev.urb[i]); | ||
66 | else | ||
67 | usb_unlink_urb(dev->adev.urb[i]); | ||
68 | |||
69 | usb_free_urb(dev->adev.urb[i]); | ||
70 | dev->adev.urb[i] = NULL; | ||
71 | |||
72 | kfree(dev->adev.transfer_buffer[i]); | ||
73 | dev->adev.transfer_buffer[i] = NULL; | ||
74 | |||
75 | } | ||
76 | } | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static void cx231xx_audio_isocirq(struct urb *urb) | ||
82 | { | ||
83 | struct cx231xx *dev = urb->context; | ||
84 | int i; | ||
85 | unsigned int oldptr; | ||
86 | int period_elapsed = 0; | ||
87 | int status; | ||
88 | unsigned char *cp; | ||
89 | unsigned int stride; | ||
90 | struct snd_pcm_substream *substream; | ||
91 | struct snd_pcm_runtime *runtime; | ||
92 | |||
93 | switch (urb->status) { | ||
94 | case 0: /* success */ | ||
95 | case -ETIMEDOUT: /* NAK */ | ||
96 | break; | ||
97 | case -ECONNRESET: /* kill */ | ||
98 | case -ENOENT: | ||
99 | case -ESHUTDOWN: | ||
100 | return; | ||
101 | default: /* error */ | ||
102 | dprintk("urb completition error %d.\n", urb->status); | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | if (dev->adev.capture_pcm_substream) { | ||
107 | substream = dev->adev.capture_pcm_substream; | ||
108 | runtime = substream->runtime; | ||
109 | stride = runtime->frame_bits >> 3; | ||
110 | |||
111 | for (i = 0; i < urb->number_of_packets; i++) { | ||
112 | int length = | ||
113 | urb->iso_frame_desc[i].actual_length / stride; | ||
114 | cp = (unsigned char *)urb->transfer_buffer + | ||
115 | urb->iso_frame_desc[i].offset; | ||
116 | |||
117 | if (!length) | ||
118 | continue; | ||
119 | |||
120 | oldptr = dev->adev.hwptr_done_capture; | ||
121 | if (oldptr + length >= runtime->buffer_size) { | ||
122 | unsigned int cnt = | ||
123 | runtime->buffer_size - oldptr; | ||
124 | memcpy(runtime->dma_area + oldptr * stride, cp, | ||
125 | cnt * stride); | ||
126 | memcpy(runtime->dma_area, cp + cnt * stride, | ||
127 | length * stride - cnt * stride); | ||
128 | } else { | ||
129 | memcpy(runtime->dma_area + oldptr * stride, cp, | ||
130 | length * stride); | ||
131 | } | ||
132 | |||
133 | snd_pcm_stream_lock(substream); | ||
134 | |||
135 | dev->adev.hwptr_done_capture += length; | ||
136 | if (dev->adev.hwptr_done_capture >= | ||
137 | runtime->buffer_size) | ||
138 | dev->adev.hwptr_done_capture -= | ||
139 | runtime->buffer_size; | ||
140 | |||
141 | dev->adev.capture_transfer_done += length; | ||
142 | if (dev->adev.capture_transfer_done >= | ||
143 | runtime->period_size) { | ||
144 | dev->adev.capture_transfer_done -= | ||
145 | runtime->period_size; | ||
146 | period_elapsed = 1; | ||
147 | } | ||
148 | |||
149 | snd_pcm_stream_unlock(substream); | ||
150 | } | ||
151 | if (period_elapsed) | ||
152 | snd_pcm_period_elapsed(substream); | ||
153 | } | ||
154 | urb->status = 0; | ||
155 | |||
156 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
157 | if (status < 0) { | ||
158 | cx231xx_errdev("resubmit of audio urb failed (error=%i)\n", | ||
159 | status); | ||
160 | } | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | static int cx231xx_init_audio_isoc(struct cx231xx *dev) | ||
165 | { | ||
166 | int i, errCode; | ||
167 | int sb_size; | ||
168 | |||
169 | cx231xx_info("%s: Starting AUDIO transfers\n",__func__); | ||
170 | |||
171 | sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; | ||
172 | |||
173 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { | ||
174 | struct urb *urb; | ||
175 | int j, k; | ||
176 | |||
177 | dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); | ||
178 | if (!dev->adev.transfer_buffer[i]) | ||
179 | return -ENOMEM; | ||
180 | |||
181 | memset(dev->adev.transfer_buffer[i], 0x80, sb_size); | ||
182 | urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); | ||
183 | if (!urb) { | ||
184 | cx231xx_errdev("usb_alloc_urb failed!\n"); | ||
185 | for (j = 0; j < i; j++) { | ||
186 | usb_free_urb(dev->adev.urb[j]); | ||
187 | kfree(dev->adev.transfer_buffer[j]); | ||
188 | } | ||
189 | return -ENOMEM; | ||
190 | } | ||
191 | |||
192 | urb->dev = dev->udev; | ||
193 | urb->context = dev; | ||
194 | urb->pipe = usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); | ||
195 | urb->transfer_flags = URB_ISO_ASAP; | ||
196 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | ||
197 | urb->interval = 1; | ||
198 | urb->complete = cx231xx_audio_isocirq; | ||
199 | urb->number_of_packets = CX231XX_NUM_AUDIO_PACKETS; | ||
200 | urb->transfer_buffer_length = sb_size; | ||
201 | |||
202 | for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS; | ||
203 | j++, k += dev->adev.max_pkt_size) { | ||
204 | urb->iso_frame_desc[j].offset = k; | ||
205 | urb->iso_frame_desc[j].length = | ||
206 | dev->adev.max_pkt_size; | ||
207 | } | ||
208 | dev->adev.urb[i] = urb; | ||
209 | } | ||
210 | |||
211 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { | ||
212 | errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); | ||
213 | if (errCode < 0) { | ||
214 | cx231xx_isoc_audio_deinit(dev); | ||
215 | return errCode; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | return errCode; | ||
220 | } | ||
221 | |||
222 | static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg) | ||
223 | { | ||
224 | dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON)? | ||
225 | "stop" : "start"); | ||
226 | |||
227 | switch (cmd) { | ||
228 | case CX231XX_CAPTURE_STREAM_EN: | ||
229 | if (dev->adev.capture_stream == STREAM_OFF && arg == 1) { | ||
230 | dev->adev.capture_stream = STREAM_ON; | ||
231 | cx231xx_init_audio_isoc(dev); | ||
232 | } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { | ||
233 | dev->adev.capture_stream = STREAM_OFF; | ||
234 | cx231xx_isoc_audio_deinit(dev); | ||
235 | } else { | ||
236 | cx231xx_errdev( "An underrun very likely occurred. " | ||
237 | "Ignoring it.\n"); | ||
238 | } | ||
239 | return 0; | ||
240 | default: | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, | ||
246 | size_t size) | ||
247 | { | ||
248 | struct snd_pcm_runtime *runtime = subs->runtime; | ||
249 | |||
250 | dprintk("Allocating vbuffer\n"); | ||
251 | if (runtime->dma_area) { | ||
252 | if (runtime->dma_bytes > size) | ||
253 | return 0; | ||
254 | |||
255 | vfree(runtime->dma_area); | ||
256 | } | ||
257 | runtime->dma_area = vmalloc(size); | ||
258 | if (!runtime->dma_area) | ||
259 | return -ENOMEM; | ||
260 | |||
261 | runtime->dma_bytes = size; | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static struct snd_pcm_hardware snd_cx231xx_hw_capture = { | ||
267 | .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
268 | SNDRV_PCM_INFO_MMAP | | ||
269 | SNDRV_PCM_INFO_INTERLEAVED | | ||
270 | SNDRV_PCM_INFO_MMAP_VALID, | ||
271 | |||
272 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
273 | |||
274 | .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, | ||
275 | |||
276 | .rate_min = 48000, | ||
277 | .rate_max = 48000, | ||
278 | .channels_min = 2, | ||
279 | .channels_max = 2, | ||
280 | .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ | ||
281 | .period_bytes_min = 64, /* 12544/2, */ | ||
282 | .period_bytes_max = 12544, | ||
283 | .periods_min = 2, | ||
284 | .periods_max = 98, /* 12544, */ | ||
285 | }; | ||
286 | |||
287 | static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) | ||
288 | { | ||
289 | struct cx231xx *dev = snd_pcm_substream_chip(substream); | ||
290 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
291 | int ret = 0; | ||
292 | |||
293 | dprintk("opening device and trying to acquire exclusive lock\n"); | ||
294 | |||
295 | if (!dev) { | ||
296 | cx231xx_errdev("BUG: cx231xx can't find device struct." | ||
297 | " Can't proceed with open\n"); | ||
298 | return -ENODEV; | ||
299 | } | ||
300 | |||
301 | /* Sets volume, mute, etc */ | ||
302 | dev->mute = 0; | ||
303 | |||
304 | /* set alternate setting for audio interface */ | ||
305 | ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); /* 1 - 48000 samples per sec */ | ||
306 | if (ret < 0) { | ||
307 | cx231xx_errdev("failed to set alternate setting !\n"); | ||
308 | |||
309 | return ret; | ||
310 | } | ||
311 | |||
312 | /* inform hardware to start streaming */ | ||
313 | ret = cx231xx_capture_start(dev, 1, Audio); | ||
314 | |||
315 | runtime->hw = snd_cx231xx_hw_capture; | ||
316 | |||
317 | mutex_lock(&dev->lock); | ||
318 | dev->adev.users++; | ||
319 | mutex_unlock(&dev->lock); | ||
320 | |||
321 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
322 | dev->adev.capture_pcm_substream = substream; | ||
323 | runtime->private_data = dev; | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) | ||
329 | { | ||
330 | int ret; | ||
331 | struct cx231xx *dev = snd_pcm_substream_chip(substream); | ||
332 | |||
333 | |||
334 | dprintk("closing device\n"); | ||
335 | |||
336 | /* set alternate setting for audio interface */ | ||
337 | ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); /* 1 - 48000 samples per sec */ | ||
338 | if (ret < 0) { | ||
339 | cx231xx_errdev("failed to set alternate setting !\n"); | ||
340 | |||
341 | return ret; | ||
342 | } | ||
343 | |||
344 | /* inform hardware to start streaming */ | ||
345 | ret = cx231xx_capture_start(dev, 0, Audio); | ||
346 | |||
347 | dev->mute = 1; | ||
348 | mutex_lock(&dev->lock); | ||
349 | dev->adev.users--; | ||
350 | mutex_unlock(&dev->lock); | ||
351 | |||
352 | if (dev->adev.users == 0 && dev->adev.shutdown == 1) { | ||
353 | dprintk("audio users: %d\n", dev->adev.users); | ||
354 | dprintk("disabling audio stream!\n"); | ||
355 | dev->adev.shutdown = 0; | ||
356 | dprintk("released lock\n"); | ||
357 | cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, 0); | ||
358 | } | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, | ||
363 | struct snd_pcm_hw_params *hw_params) | ||
364 | { | ||
365 | unsigned int channels, rate, format; | ||
366 | int ret; | ||
367 | |||
368 | dprintk("Setting capture parameters\n"); | ||
369 | |||
370 | ret = snd_pcm_alloc_vmalloc_buffer(substream, | ||
371 | params_buffer_bytes(hw_params)); | ||
372 | format = params_format(hw_params); | ||
373 | rate = params_rate(hw_params); | ||
374 | channels = params_channels(hw_params); | ||
375 | |||
376 | /* TODO: set up cx231xx audio chip to deliver the correct audio format, | ||
377 | current default is 48000hz multiplexed => 96000hz mono | ||
378 | which shouldn't matter since analogue TV only supports mono */ | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) | ||
383 | { | ||
384 | struct cx231xx *dev = snd_pcm_substream_chip(substream); | ||
385 | |||
386 | dprintk("Stop capture, if needed\n"); | ||
387 | |||
388 | if (dev->adev.capture_stream == STREAM_ON) | ||
389 | cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO); | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) | ||
395 | { | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, | ||
400 | int cmd) | ||
401 | { | ||
402 | struct cx231xx *dev = snd_pcm_substream_chip(substream); | ||
403 | int retval; | ||
404 | |||
405 | |||
406 | dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)? | ||
407 | "start": "stop"); | ||
408 | |||
409 | spin_lock(&dev->adev.slock); | ||
410 | switch (cmd) { | ||
411 | case SNDRV_PCM_TRIGGER_START: | ||
412 | cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_START_AUDIO); | ||
413 | retval = 0; | ||
414 | break; | ||
415 | case SNDRV_PCM_TRIGGER_STOP: | ||
416 | cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO); | ||
417 | retval = 0; | ||
418 | break; | ||
419 | default: | ||
420 | retval = -EINVAL; | ||
421 | } | ||
422 | |||
423 | spin_unlock(&dev->adev.slock); | ||
424 | return retval; | ||
425 | } | ||
426 | |||
427 | static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream | ||
428 | *substream) | ||
429 | { | ||
430 | struct cx231xx *dev; | ||
431 | unsigned long flags; | ||
432 | snd_pcm_uframes_t hwptr_done; | ||
433 | |||
434 | dev = snd_pcm_substream_chip(substream); | ||
435 | |||
436 | spin_lock_irqsave(&dev->adev.slock, flags); | ||
437 | hwptr_done = dev->adev.hwptr_done_capture; | ||
438 | spin_unlock_irqrestore(&dev->adev.slock, flags); | ||
439 | |||
440 | return hwptr_done; | ||
441 | } | ||
442 | |||
443 | static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, | ||
444 | unsigned long offset) | ||
445 | { | ||
446 | void *pageptr = subs->runtime->dma_area + offset; | ||
447 | |||
448 | return vmalloc_to_page(pageptr); | ||
449 | } | ||
450 | |||
451 | static struct snd_pcm_ops snd_cx231xx_pcm_capture = { | ||
452 | .open = snd_cx231xx_capture_open, | ||
453 | .close = snd_cx231xx_pcm_close, | ||
454 | .ioctl = snd_pcm_lib_ioctl, | ||
455 | .hw_params = snd_cx231xx_hw_capture_params, | ||
456 | .hw_free = snd_cx231xx_hw_capture_free, | ||
457 | .prepare = snd_cx231xx_prepare, | ||
458 | .trigger = snd_cx231xx_capture_trigger, | ||
459 | .pointer = snd_cx231xx_capture_pointer, | ||
460 | .page = snd_pcm_get_vmalloc_page, | ||
461 | }; | ||
462 | |||
463 | static int cx231xx_audio_init(struct cx231xx *dev) | ||
464 | { | ||
465 | struct cx231xx_audio *adev = &dev->adev; | ||
466 | struct snd_pcm *pcm; | ||
467 | struct snd_card *card; | ||
468 | static int devnr; | ||
469 | int err; | ||
470 | struct usb_interface *uif; | ||
471 | int i, isoc_pipe = 0; | ||
472 | |||
473 | if (dev->has_alsa_audio != 1) { | ||
474 | /* This device does not support the extension (in this case | ||
475 | the device is expecting the snd-usb-audio module or | ||
476 | doesn't have analog audio support at all) */ | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | cx231xx_info("cx231xx-audio.c: probing for cx231xx " | ||
481 | "non standard usbaudio\n"); | ||
482 | |||
483 | card = snd_card_new(index[devnr], "Cx231xx Audio", THIS_MODULE, 0); | ||
484 | if (card == NULL) { | ||
485 | return -ENOMEM; | ||
486 | } | ||
487 | |||
488 | spin_lock_init(&adev->slock); | ||
489 | err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); | ||
490 | if (err < 0) { | ||
491 | snd_card_free(card); | ||
492 | return err; | ||
493 | } | ||
494 | |||
495 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx231xx_pcm_capture); | ||
496 | pcm->info_flags = 0; | ||
497 | pcm->private_data = dev; | ||
498 | strcpy(pcm->name, "Conexant cx231xx Capture"); | ||
499 | strcpy(card->driver, "Conexant cx231xx Audio"); | ||
500 | strcpy(card->shortname, "Cx231xx Audio"); | ||
501 | strcpy(card->longname, "Conexant cx231xx Audio"); | ||
502 | |||
503 | err = snd_card_register(card); | ||
504 | if (err < 0) { | ||
505 | snd_card_free(card); | ||
506 | return err; | ||
507 | } | ||
508 | adev->sndcard = card; | ||
509 | adev->udev = dev->udev; | ||
510 | |||
511 | /* compute alternate max packet sizes for Audio */ | ||
512 | uif = dev->udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.audio_index+1]; | ||
513 | |||
514 | adev->end_point_addr = le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); | ||
515 | |||
516 | adev->num_alt = uif->num_altsetting; | ||
517 | cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", adev->end_point_addr, | ||
518 | adev->num_alt); | ||
519 | adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); | ||
520 | |||
521 | if (adev->alt_max_pkt_size == NULL) { | ||
522 | cx231xx_errdev("out of memory!\n"); | ||
523 | return -ENOMEM; | ||
524 | } | ||
525 | |||
526 | for (i = 0; i < adev->num_alt ; i++) { | ||
527 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. | ||
528 | wMaxPacketSize); | ||
529 | adev->alt_max_pkt_size[i] = | ||
530 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
531 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
532 | adev->alt_max_pkt_size[i]); | ||
533 | } | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int cx231xx_audio_fini(struct cx231xx *dev) | ||
539 | { | ||
540 | if (dev == NULL) | ||
541 | return 0; | ||
542 | |||
543 | if (dev->has_alsa_audio != 1) { | ||
544 | /* This device does not support the extension (in this case | ||
545 | the device is expecting the snd-usb-audio module or | ||
546 | doesn't have analog audio support at all) */ | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | if (dev->adev.sndcard) { | ||
551 | snd_card_free(dev->adev.sndcard); | ||
552 | kfree(dev->adev.alt_max_pkt_size); | ||
553 | dev->adev.sndcard = NULL; | ||
554 | } | ||
555 | |||
556 | return 0; | ||
557 | } | ||
558 | |||
559 | static struct cx231xx_ops audio_ops = { | ||
560 | .id = CX231XX_AUDIO, | ||
561 | .name = "Cx231xx Audio Extension", | ||
562 | .init = cx231xx_audio_init, | ||
563 | .fini = cx231xx_audio_fini, | ||
564 | }; | ||
565 | |||
566 | static int __init cx231xx_alsa_register(void) | ||
567 | { | ||
568 | return cx231xx_register_extension(&audio_ops); | ||
569 | } | ||
570 | |||
571 | static void __exit cx231xx_alsa_unregister(void) | ||
572 | { | ||
573 | cx231xx_unregister_extension(&audio_ops); | ||
574 | } | ||
575 | |||
576 | MODULE_LICENSE("GPL"); | ||
577 | MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); | ||
578 | MODULE_DESCRIPTION("Cx231xx Audio driver"); | ||
579 | |||
580 | module_init(cx231xx_alsa_register); | ||
581 | module_exit(cx231xx_alsa_unregister); | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c new file mode 100644 index 000000000000..b5597337966f --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-avcore.c | |||
@@ -0,0 +1,2289 @@ | |||
1 | /* | ||
2 | cx231xx_avcore.c - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | |||
6 | This program contains the specific code to control the avdecoder chip and | ||
7 | other related usb control functions for cx231xx based chipset. | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation; either version 2 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | GNU General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/init.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/bitmap.h> | ||
29 | #include <linux/usb.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/version.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/mutex.h> | ||
34 | |||
35 | #include <media/v4l2-common.h> | ||
36 | #include <media/v4l2-ioctl.h> | ||
37 | #include <media/v4l2-chip-ident.h> | ||
38 | |||
39 | #include "cx231xx.h" | ||
40 | |||
41 | |||
42 | /************************************************************************************* | ||
43 | * C O L I B R I - B L O C K C O N T R O L functions * | ||
44 | *************************************************************************************/ | ||
45 | int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) | ||
46 | { | ||
47 | int status = 0; | ||
48 | u8 temp = 0; | ||
49 | u32 colibri_power_status = 0; | ||
50 | int i = 0; | ||
51 | |||
52 | /* super block initialize */ | ||
53 | temp = (u8)(ref_count & 0xff); | ||
54 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, temp, 1); | ||
55 | |||
56 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, &colibri_power_status, 1); | ||
57 | |||
58 | temp = (u8)((ref_count & 0x300) >> 8); | ||
59 | temp |= 0x40; | ||
60 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE1, 2, temp, 1); | ||
61 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PLL2, 2, 0x0f, 1); | ||
62 | |||
63 | /* enable pll */ | ||
64 | while(colibri_power_status != 0x18) | ||
65 | { | ||
66 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, 0x18, 1); | ||
67 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, 1); | ||
68 | colibri_power_status &= 0xff; | ||
69 | if(status < 0) { | ||
70 | cx231xx_info(": Init Super Block failed in sending/receiving cmds\n"); | ||
71 | break; | ||
72 | } | ||
73 | i++; | ||
74 | if( i == 10) { | ||
75 | cx231xx_info(": Init Super Block force break in loop !!!!\n"); | ||
76 | status = -1; | ||
77 | break; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | if(status < 0 ) | ||
82 | return status; | ||
83 | |||
84 | /* start tuning filter */ | ||
85 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, 2, 0x40, 1); | ||
86 | msleep(5); | ||
87 | |||
88 | /* exit tuning */ | ||
89 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, 2, 0x00, 1); | ||
90 | |||
91 | return status; | ||
92 | } | ||
93 | |||
94 | int cx231xx_colibri_init_channels(struct cx231xx *dev) | ||
95 | { | ||
96 | int status = 0; | ||
97 | |||
98 | /* power up all 3 channels, clear pd_buffer */ | ||
99 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); | ||
100 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); | ||
101 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); | ||
102 | |||
103 | /* Enable quantizer calibration */ | ||
104 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_COM_QUANT, 2, 0x02, 1); | ||
105 | |||
106 | /* channel initialize, force modulator (fb) reset */ | ||
107 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x17, 1); | ||
108 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x17, 1); | ||
109 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x17, 1); | ||
110 | |||
111 | /* start quantilizer calibration */ | ||
112 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH1, 2, 0x10, 1); | ||
113 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH2, 2, 0x10, 1); | ||
114 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH3, 2, 0x10, 1); | ||
115 | msleep(5); | ||
116 | |||
117 | /* exit modulator (fb) reset */ | ||
118 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x07, 1); | ||
119 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x07, 1); | ||
120 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x07, 1); | ||
121 | |||
122 | /* enable the pre_clamp in each channel for single-ended input */ | ||
123 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH1, 2, 0xf0, 1); | ||
124 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH2, 2, 0xf0, 1); | ||
125 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH3, 2, 0xf0, 1); | ||
126 | |||
127 | /* use diode instead of resistor, so set term_en to 0, res_en to 0 */ | ||
128 | status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00); | ||
129 | status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00); | ||
130 | status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00); | ||
131 | |||
132 | /* dynamic element matching off */ | ||
133 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH1, 2, 0x03, 1); | ||
134 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH2, 2, 0x03, 1); | ||
135 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH3, 2, 0x03, 1); | ||
136 | |||
137 | return status; | ||
138 | } | ||
139 | |||
140 | int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev) | ||
141 | { | ||
142 | u32 c_value = 0; | ||
143 | int status = 0; | ||
144 | |||
145 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, &c_value, 1); | ||
146 | c_value &= (~(0x50)); | ||
147 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, c_value, 1); | ||
148 | |||
149 | return status; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | we have 3 channel | ||
154 | channel 1 ----- pin 1 to pin4(in reg is 1-4) | ||
155 | channel 2 ----- pin 5 to pin8(in reg is 5-8) | ||
156 | channel 3 ----- pin 9 to pin 12(in reg is 9-11) | ||
157 | */ | ||
158 | int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux) | ||
159 | { | ||
160 | u8 ch1_setting = (u8)input_mux; | ||
161 | u8 ch2_setting = (u8)(input_mux >> 8); | ||
162 | u8 ch3_setting = (u8)(input_mux >> 16); | ||
163 | int status = 0; | ||
164 | u32 value = 0; | ||
165 | |||
166 | if(ch1_setting != 0) | ||
167 | { | ||
168 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, &value, 1); | ||
169 | value &= (!INPUT_SEL_MASK); | ||
170 | value |= (ch1_setting-1)<<4; | ||
171 | value &= 0xff; | ||
172 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, value, 1); | ||
173 | } | ||
174 | |||
175 | if(ch2_setting != 0) | ||
176 | { | ||
177 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH2, 2, &value, 1); | ||
178 | value &= (!INPUT_SEL_MASK); | ||
179 | value |= (ch2_setting-1)<<4; | ||
180 | value &= 0xff; | ||
181 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH2, 2, value, 1); | ||
182 | } | ||
183 | |||
184 | /* For ch3_setting, the value to put in the register is 7 less than the input number */ | ||
185 | if(ch3_setting != 0) | ||
186 | { | ||
187 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &value, 1); | ||
188 | value &= (!INPUT_SEL_MASK); | ||
189 | value |= (ch3_setting-1)<<4; | ||
190 | value &= 0xff; | ||
191 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, value, 1); | ||
192 | } | ||
193 | |||
194 | return status; | ||
195 | } | ||
196 | |||
197 | int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) | ||
198 | { | ||
199 | int status = 0; | ||
200 | |||
201 | switch(mode) { | ||
202 | case AFE_MODE_LOW_IF: | ||
203 | /* SetupAFEforLowIF(); */ | ||
204 | break; | ||
205 | case AFE_MODE_BASEBAND: | ||
206 | status = cx231xx_colibri_setup_AFE_for_baseband(dev); | ||
207 | break; | ||
208 | case AFE_MODE_EU_HI_IF: | ||
209 | /* SetupAFEforEuHiIF(); */ | ||
210 | break; | ||
211 | case AFE_MODE_US_HI_IF: | ||
212 | /* SetupAFEforUsHiIF(); */ | ||
213 | break; | ||
214 | case AFE_MODE_JAPAN_HI_IF: | ||
215 | /* SetupAFEforJapanHiIF(); */ | ||
216 | break; | ||
217 | } | ||
218 | |||
219 | if((mode != dev->colibri_mode) && (dev->video_input == CX231XX_VMUX_TELEVISION)) { | ||
220 | status = cx231xx_colibri_adjust_ref_count(dev, CX231XX_VMUX_TELEVISION); | ||
221 | } | ||
222 | |||
223 | dev->colibri_mode = mode; | ||
224 | |||
225 | return status; | ||
226 | } | ||
227 | |||
228 | /* For power saving in the EVK */ | ||
229 | int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) | ||
230 | { | ||
231 | u32 colibri_power_status = 0; | ||
232 | int status = 0; | ||
233 | |||
234 | switch (dev->model) { | ||
235 | case CX231XX_BOARD_CNXT_RDE_250: | ||
236 | case CX231XX_BOARD_CNXT_RDU_250: | ||
237 | |||
238 | if(avmode==POLARIS_AVMODE_ANALOGT_TV) | ||
239 | { | ||
240 | while(colibri_power_status != 0x18) { | ||
241 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
242 | SUP_BLK_PWRDN, 2, 0x18, 1); | ||
243 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
244 | SUP_BLK_PWRDN, 2, &colibri_power_status, 1); | ||
245 | if(status < 0 ) | ||
246 | break; | ||
247 | } | ||
248 | |||
249 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
250 | ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); | ||
251 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
252 | ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); | ||
253 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
254 | ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); | ||
255 | } | ||
256 | else if(avmode==POLARIS_AVMODE_DIGITAL) { | ||
257 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
258 | ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1); | ||
259 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
260 | ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1); | ||
261 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
262 | ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1); | ||
263 | |||
264 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
265 | SUP_BLK_PWRDN, 2, &colibri_power_status, 1); | ||
266 | colibri_power_status |=0x07; | ||
267 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
268 | SUP_BLK_PWRDN, 2, colibri_power_status, 1); | ||
269 | } | ||
270 | else if(avmode==POLARIS_AVMODE_ENXTERNAL_AV) { | ||
271 | |||
272 | while(colibri_power_status != 0x18) { | ||
273 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
274 | SUP_BLK_PWRDN, 2, 0x18, 1); | ||
275 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
276 | SUP_BLK_PWRDN, 2, &colibri_power_status, 1); | ||
277 | if(status < 0 ) | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
282 | ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); | ||
283 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
284 | ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); | ||
285 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
286 | ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); | ||
287 | } | ||
288 | else { | ||
289 | cx231xx_info("Invalid AV mode input\n"); | ||
290 | status = -1; | ||
291 | } | ||
292 | break; | ||
293 | default: | ||
294 | if(avmode==POLARIS_AVMODE_ANALOGT_TV) | ||
295 | { | ||
296 | while(colibri_power_status != 0x18) { | ||
297 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
298 | SUP_BLK_PWRDN, 2, 0x18, 1); | ||
299 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
300 | SUP_BLK_PWRDN, 2, &colibri_power_status, 1); | ||
301 | if(status < 0 ) | ||
302 | break; | ||
303 | } | ||
304 | |||
305 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
306 | ADC_PWRDN_CLAMP_CH1, 2, 0x40, 1); | ||
307 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
308 | ADC_PWRDN_CLAMP_CH2, 2, 0x40, 1); | ||
309 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
310 | ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); | ||
311 | } | ||
312 | else if(avmode==POLARIS_AVMODE_DIGITAL) { | ||
313 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
314 | ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1); | ||
315 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
316 | ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1); | ||
317 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
318 | ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1); | ||
319 | |||
320 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
321 | SUP_BLK_PWRDN, 2, &colibri_power_status, 1); | ||
322 | colibri_power_status |=0x07; | ||
323 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
324 | SUP_BLK_PWRDN, 2, colibri_power_status, 1); | ||
325 | } | ||
326 | else if(avmode==POLARIS_AVMODE_ENXTERNAL_AV) { | ||
327 | while(colibri_power_status != 0x18) { | ||
328 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
329 | SUP_BLK_PWRDN, 2, 0x18, 1); | ||
330 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
331 | SUP_BLK_PWRDN, 2, &colibri_power_status, 1); | ||
332 | if(status < 0 ) | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
337 | ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); | ||
338 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
339 | ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); | ||
340 | status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
341 | ADC_PWRDN_CLAMP_CH3, 2, 0x40, 1); | ||
342 | } | ||
343 | else { | ||
344 | cx231xx_info("Invalid AV mode input\n"); | ||
345 | status = -1; | ||
346 | } | ||
347 | } /* switch */ | ||
348 | |||
349 | return status; | ||
350 | } | ||
351 | |||
352 | int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input) | ||
353 | { | ||
354 | u32 input_mode = 0; | ||
355 | u32 ntf_mode = 0; | ||
356 | int status = 0; | ||
357 | |||
358 | dev->video_input = video_input; | ||
359 | |||
360 | if(video_input == CX231XX_VMUX_TELEVISION) { | ||
361 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &input_mode, 1); | ||
362 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
363 | ADC_NTF_PRECLMP_EN_CH3, 2, &ntf_mode, 1); | ||
364 | } | ||
365 | else { | ||
366 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, &input_mode, 1); | ||
367 | status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, | ||
368 | ADC_NTF_PRECLMP_EN_CH1, 2, &ntf_mode, 1); | ||
369 | } | ||
370 | |||
371 | input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1); | ||
372 | |||
373 | switch(input_mode) | ||
374 | { | ||
375 | case SINGLE_ENDED: | ||
376 | dev->colibri_ref_count = 0x23C; | ||
377 | break; | ||
378 | case LOW_IF: | ||
379 | dev->colibri_ref_count = 0x24C; | ||
380 | break; | ||
381 | case EU_IF: | ||
382 | dev->colibri_ref_count = 0x258; | ||
383 | break; | ||
384 | case US_IF: | ||
385 | dev->colibri_ref_count = 0x260; | ||
386 | break; | ||
387 | default: | ||
388 | break; | ||
389 | } | ||
390 | |||
391 | status = cx231xx_colibri_init_super_block(dev, dev->colibri_ref_count); | ||
392 | |||
393 | return status; | ||
394 | } | ||
395 | |||
396 | |||
397 | |||
398 | /************************************************************************************* | ||
399 | * V I D E O / A U D I O D E C O D E R C O N T R O L functions * | ||
400 | *************************************************************************************/ | ||
401 | int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) | ||
402 | { | ||
403 | int status = 0; | ||
404 | |||
405 | switch(INPUT(input)->type) { | ||
406 | case CX231XX_VMUX_COMPOSITE1: | ||
407 | case CX231XX_VMUX_SVIDEO: | ||
408 | if((dev->current_pcb_config.type == USB_BUS_POWER) && | ||
409 | (dev->power_mode != POLARIS_AVMODE_ENXTERNAL_AV)) { | ||
410 | status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ENXTERNAL_AV); /* External AV */ | ||
411 | if (status < 0) { | ||
412 | cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", | ||
413 | __func__, status); | ||
414 | return status; | ||
415 | } | ||
416 | } | ||
417 | status = cx231xx_set_decoder_video_input(dev, INPUT(input)->type, INPUT(input)->vmux); | ||
418 | break; | ||
419 | case CX231XX_VMUX_TELEVISION: | ||
420 | case CX231XX_VMUX_CABLE: | ||
421 | if((dev->current_pcb_config.type == USB_BUS_POWER) && | ||
422 | (dev->power_mode != POLARIS_AVMODE_ANALOGT_TV)) { | ||
423 | status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); /* Tuner */ | ||
424 | if (status < 0) { | ||
425 | cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", | ||
426 | __func__, status); | ||
427 | return status; | ||
428 | } | ||
429 | } | ||
430 | status = cx231xx_set_decoder_video_input(dev, CX231XX_VMUX_COMPOSITE1, INPUT(input)->vmux); | ||
431 | break; | ||
432 | default: | ||
433 | cx231xx_errdev("%s: cx231xx_set_power_mode : Unknown Input %d !\n", | ||
434 | __func__, INPUT(input)->type); | ||
435 | break; | ||
436 | } | ||
437 | |||
438 | /* save the selection */ | ||
439 | dev->video_input = input; | ||
440 | |||
441 | return status; | ||
442 | } | ||
443 | |||
444 | int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) | ||
445 | { | ||
446 | int status = 0; | ||
447 | u32 value = 0; | ||
448 | |||
449 | if(pin_type != dev->video_input) { | ||
450 | status = cx231xx_colibri_adjust_ref_count(dev, pin_type); | ||
451 | if(status < 0 ) { | ||
452 | cx231xx_errdev("%s: cx231xx_colibri_adjust_ref_count :Failed to set Colibri input mux - errCode [%d]!\n", | ||
453 | __func__, status); | ||
454 | return status; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | /* call colibri block to set video inputs */ | ||
459 | status = cx231xx_colibri_set_input_mux(dev, input); | ||
460 | if(status < 0 ) { | ||
461 | cx231xx_errdev("%s: cx231xx_colibri_set_input_mux :Failed to set Colibri input mux - errCode [%d]!\n", | ||
462 | __func__, status); | ||
463 | return status; | ||
464 | } | ||
465 | |||
466 | switch(pin_type) { | ||
467 | case CX231XX_VMUX_COMPOSITE1: | ||
468 | { | ||
469 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); | ||
470 | value |= (0<<13)|(1<<4); | ||
471 | value &= ~(1<<5); | ||
472 | |||
473 | value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ | ||
474 | value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ | ||
475 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); | ||
476 | |||
477 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4); | ||
478 | value |= (1<<7); | ||
479 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); | ||
480 | |||
481 | /* Set vip 1.1 output mode */ | ||
482 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
483 | OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); | ||
484 | |||
485 | /* Tell DIF object to go to baseband mode */ | ||
486 | status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); | ||
487 | if (status < 0) { | ||
488 | cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", | ||
489 | __func__, status); | ||
490 | return status; | ||
491 | } | ||
492 | |||
493 | /* Read the DFE_CTRL1 register */ | ||
494 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); | ||
495 | |||
496 | /* enable the VBI_GATE_EN */ | ||
497 | value |= FLD_VBI_GATE_EN; | ||
498 | |||
499 | /* Enable the auto-VGA enable */ | ||
500 | value |= FLD_VGA_AUTO_EN; | ||
501 | |||
502 | /* Write it back */ | ||
503 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); | ||
504 | |||
505 | /* Disable auto config of registers */ | ||
506 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
507 | MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); | ||
508 | |||
509 | /* Set CVBS input mode */ | ||
510 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
511 | MODE_CTRL, FLD_INPUT_MODE, | ||
512 | cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); | ||
513 | } | ||
514 | break; | ||
515 | case CX231XX_VMUX_SVIDEO: | ||
516 | { | ||
517 | /* Disable the use of DIF */ | ||
518 | |||
519 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); | ||
520 | |||
521 | value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ | ||
522 | value |= 0x1000010; /* set FUNC_MODE[24:23] = 2 | ||
523 | IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ | ||
524 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); | ||
525 | |||
526 | /* Tell DIF object to go to baseband mode */ | ||
527 | status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); | ||
528 | if (status < 0) { | ||
529 | cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", | ||
530 | __func__, status); | ||
531 | return status; | ||
532 | } | ||
533 | |||
534 | /* Read the DFE_CTRL1 register */ | ||
535 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); | ||
536 | |||
537 | /* enable the VBI_GATE_EN */ | ||
538 | value |= FLD_VBI_GATE_EN; | ||
539 | |||
540 | /* Enable the auto-VGA enable */ | ||
541 | value |= FLD_VGA_AUTO_EN; | ||
542 | |||
543 | /* Write it back */ | ||
544 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); | ||
545 | |||
546 | /* Disable auto config of registers */ | ||
547 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
548 | MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); | ||
549 | |||
550 | /* Set YC input mode */ | ||
551 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
552 | MODE_CTRL, FLD_INPUT_MODE, | ||
553 | cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1)); | ||
554 | |||
555 | /* Chroma to ADC2 */ | ||
556 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); | ||
557 | value |= FLD_CHROMA_IN_SEL; /* set the chroma in select */ | ||
558 | |||
559 | /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8) This sets them to use video | ||
560 | rather than audio. Only one of the two will be in use. */ | ||
561 | value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3); | ||
562 | |||
563 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); | ||
564 | |||
565 | status = cx231xx_colibri_set_mode(dev, AFE_MODE_BASEBAND); | ||
566 | } | ||
567 | break; | ||
568 | case CX231XX_VMUX_TELEVISION: | ||
569 | case CX231XX_VMUX_CABLE: | ||
570 | default: | ||
571 | { | ||
572 | switch(dev->model) { | ||
573 | case CX231XX_BOARD_CNXT_RDE_250: | ||
574 | case CX231XX_BOARD_CNXT_RDU_250: | ||
575 | { | ||
576 | /* Disable the use of DIF */ | ||
577 | |||
578 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); | ||
579 | value |= (0<<13)|(1<<4); | ||
580 | value &= ~(1<<5); | ||
581 | |||
582 | value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ | ||
583 | value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ | ||
584 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); | ||
585 | |||
586 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4); | ||
587 | value |= (1<<7); | ||
588 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); | ||
589 | |||
590 | /* Set vip 1.1 output mode */ | ||
591 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
592 | OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); | ||
593 | |||
594 | /* Tell DIF object to go to baseband mode */ | ||
595 | status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); | ||
596 | if (status < 0) { | ||
597 | cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", | ||
598 | __func__, status); | ||
599 | return status; | ||
600 | } | ||
601 | |||
602 | /* Read the DFE_CTRL1 register */ | ||
603 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); | ||
604 | |||
605 | /* enable the VBI_GATE_EN */ | ||
606 | value |= FLD_VBI_GATE_EN; | ||
607 | |||
608 | /* Enable the auto-VGA enable */ | ||
609 | value |= FLD_VGA_AUTO_EN; | ||
610 | |||
611 | /* Write it back */ | ||
612 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); | ||
613 | |||
614 | /* Disable auto config of registers */ | ||
615 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
616 | MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); | ||
617 | |||
618 | /* Set CVBS input mode */ | ||
619 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
620 | MODE_CTRL, FLD_INPUT_MODE, | ||
621 | cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); | ||
622 | } | ||
623 | break; | ||
624 | default: | ||
625 | { | ||
626 | /* Enable the DIF for the tuner */ | ||
627 | |||
628 | /* Reinitialize the DIF */ | ||
629 | status = cx231xx_dif_set_standard(dev, dev->norm); | ||
630 | if (status < 0) { | ||
631 | cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", | ||
632 | __func__, status); | ||
633 | return status; | ||
634 | } | ||
635 | |||
636 | /* Make sure bypass is cleared */ | ||
637 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, &value, 4); | ||
638 | |||
639 | /* Clear the bypass bit */ | ||
640 | value &= ~FLD_DIF_DIF_BYPASS; | ||
641 | |||
642 | /* Enable the use of the DIF block */ | ||
643 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, value, 4); | ||
644 | |||
645 | /* Read the DFE_CTRL1 register */ | ||
646 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); | ||
647 | |||
648 | /* Disable the VBI_GATE_EN */ | ||
649 | value &= ~FLD_VBI_GATE_EN; | ||
650 | |||
651 | /* Enable the auto-VGA enable, AGC, and set the skip count to 2 */ | ||
652 | value |= FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000; | ||
653 | |||
654 | /* Write it back */ | ||
655 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); | ||
656 | |||
657 | /* Wait 15 ms */ | ||
658 | msleep(1); | ||
659 | |||
660 | /* Disable the auto-VGA enable AGC */ | ||
661 | value &= ~(FLD_VGA_AUTO_EN); | ||
662 | |||
663 | /* Write it back */ | ||
664 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); | ||
665 | |||
666 | /* Enable Polaris B0 AGC output */ | ||
667 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, &value, 4); | ||
668 | value |=(FLD_OEF_AGC_RF)|(FLD_OEF_AGC_IFVGA)|(FLD_OEF_AGC_IF); | ||
669 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, value, 4); | ||
670 | |||
671 | /* Set vip 1.1 output mode */ | ||
672 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
673 | OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); | ||
674 | |||
675 | /* Disable auto config of registers */ | ||
676 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
677 | MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); | ||
678 | |||
679 | /* Set CVBS input mode */ | ||
680 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
681 | MODE_CTRL, FLD_INPUT_MODE, | ||
682 | cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); | ||
683 | |||
684 | /* Set some bits in AFE_CTRL so that channel 2 or 3 is ready to receive audio */ | ||
685 | /* Clear clamp for channels 2 and 3 (bit 16-17) */ | ||
686 | /* Clear droop comp (bit 19-20) */ | ||
687 | /* Set VGA_SEL (for audio control) (bit 7-8) */ | ||
688 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); | ||
689 | |||
690 | value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2; | ||
691 | |||
692 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); | ||
693 | } | ||
694 | break; | ||
695 | |||
696 | } | ||
697 | } | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | /* Set raw VBI mode */ | ||
702 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
703 | OUT_CTRL1, FLD_VBIHACTRAW_EN, | ||
704 | cx231xx_set_field(FLD_VBIHACTRAW_EN, 1)); | ||
705 | |||
706 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4); | ||
707 | if(value & 0x02) { | ||
708 | value |=(1<<19); | ||
709 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); | ||
710 | } | ||
711 | |||
712 | return status; | ||
713 | } | ||
714 | |||
715 | /* | ||
716 | * Handle any video-mode specific overrides that are different on a per video standards | ||
717 | * basis after touching the MODE_CTRL register which resets many values for autodetect | ||
718 | */ | ||
719 | int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) | ||
720 | { | ||
721 | int status = 0; | ||
722 | |||
723 | cx231xx_info("do_mode_ctrl_overrides : 0x%x\n", (unsigned int)dev->norm); | ||
724 | |||
725 | /* Change the DFE_CTRL3 bp_percent to fix flagging */ | ||
726 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL3, 2, 0xCD3F0280, 4); | ||
727 | |||
728 | if( dev->norm & (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_PAL_M) ) { | ||
729 | cx231xx_info("do_mode_ctrl_overrides NTSC\n"); | ||
730 | |||
731 | /* Move the close caption lines out of active video, adjust the active video start point */ | ||
732 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
733 | VERT_TIM_CTRL, FLD_VBLANK_CNT,0x18); | ||
734 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
735 | VERT_TIM_CTRL, FLD_VACTIVE_CNT,0x1E6000); | ||
736 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
737 | VERT_TIM_CTRL, FLD_V656BLANK_CNT,0x1E000000); | ||
738 | |||
739 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
740 | HORIZ_TIM_CTRL, FLD_HBLANK_CNT, | ||
741 | cx231xx_set_field(FLD_HBLANK_CNT, 0x79)); | ||
742 | } else if ( dev->norm & ( V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_D | | ||
743 | V4L2_STD_PAL_I | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc) ) { | ||
744 | cx231xx_info("do_mode_ctrl_overrides PAL\n"); | ||
745 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
746 | VERT_TIM_CTRL, FLD_VBLANK_CNT,0x24); | ||
747 | /* Adjust the active video horizontal start point */ | ||
748 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
749 | HORIZ_TIM_CTRL, FLD_HBLANK_CNT, | ||
750 | cx231xx_set_field(FLD_HBLANK_CNT, 0x85)); | ||
751 | } else if (dev->norm & ( V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | | ||
752 | V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1 | V4L2_STD_SECAM_L | | ||
753 | V4L2_STD_SECAM_LC) ) { | ||
754 | cx231xx_info("do_mode_ctrl_overrides SECAM\n"); | ||
755 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
756 | VERT_TIM_CTRL, FLD_VBLANK_CNT,0x24); | ||
757 | /* Adjust the active video horizontal start point */ | ||
758 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
759 | HORIZ_TIM_CTRL, FLD_HBLANK_CNT, | ||
760 | cx231xx_set_field(FLD_HBLANK_CNT, 0x85)); | ||
761 | } | ||
762 | |||
763 | return status; | ||
764 | } | ||
765 | |||
766 | int cx231xx_set_audio_input(struct cx231xx *dev, u8 input) | ||
767 | { | ||
768 | int status = 0; | ||
769 | enum AUDIO_INPUT ainput = AUDIO_INPUT_LINE; | ||
770 | |||
771 | switch(INPUT(input)->amux) { | ||
772 | case CX231XX_AMUX_VIDEO: | ||
773 | ainput = AUDIO_INPUT_TUNER_TV; | ||
774 | break; | ||
775 | case CX231XX_AMUX_LINE_IN: | ||
776 | status = cx231xx_flatiron_set_audio_input(dev, input); | ||
777 | ainput = AUDIO_INPUT_LINE; | ||
778 | break; | ||
779 | default: | ||
780 | break; | ||
781 | } | ||
782 | |||
783 | status = cx231xx_set_audio_decoder_input(dev, ainput); | ||
784 | |||
785 | return status; | ||
786 | } | ||
787 | |||
788 | int cx231xx_set_audio_decoder_input(struct cx231xx *dev, enum AUDIO_INPUT audio_input) | ||
789 | { | ||
790 | u32 dwval; | ||
791 | int status; | ||
792 | u32 gen_ctrl; | ||
793 | u32 value = 0; | ||
794 | |||
795 | /* Put it in soft reset */ | ||
796 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, &gen_ctrl, 1); | ||
797 | gen_ctrl |= 1; | ||
798 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, gen_ctrl, 1); | ||
799 | |||
800 | switch(audio_input) | ||
801 | { | ||
802 | case AUDIO_INPUT_LINE: | ||
803 | |||
804 | /* setup AUD_IO control from Merlin paralle output */ | ||
805 | value = cx231xx_set_field(FLD_AUD_CHAN1_SRC, AUD_CHAN_SRC_PARALLEL); | ||
806 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AUD_IO_CTRL, 2, value, 4); | ||
807 | |||
808 | /* setup input to Merlin, SRC2 connect to AC97 | ||
809 | bypass upsample-by-2, slave mode, sony mode, left justify | ||
810 | adr 091c, dat 01000000 */ | ||
811 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, 2, &dwval, 4); | ||
812 | |||
813 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, 2, (dwval | FLD_AC97_UP2X_BYPASS), 4); | ||
814 | |||
815 | /* select the parallel1 and SRC3 */ | ||
816 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, BAND_OUT_SEL, 2, | ||
817 | cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0)| | ||
818 | cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0)| | ||
819 | cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0), 4); | ||
820 | |||
821 | /* unmute all, AC97 in, independence mode | ||
822 | adr 08d0, data 0x00063073 */ | ||
823 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063073, 4); | ||
824 | |||
825 | /* set AVC maximum threshold, adr 08d4, dat ffff0024 */ | ||
826 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2, &dwval, 4); | ||
827 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2, | ||
828 | (dwval | FLD_PATH1_AVC_THRESHOLD), 4); | ||
829 | |||
830 | /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */ | ||
831 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2, &dwval, 4); | ||
832 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2, | ||
833 | (dwval | FLD_PATH1_SC_THRESHOLD), 4); | ||
834 | break; | ||
835 | |||
836 | case AUDIO_INPUT_TUNER_TV: | ||
837 | default: | ||
838 | |||
839 | /* Setup SRC sources and clocks */ | ||
840 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, BAND_OUT_SEL, 2, | ||
841 | cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00)| | ||
842 | cx231xx_set_field(FLD_SRC6_CLK_SEL, 0x01)| | ||
843 | cx231xx_set_field(FLD_SRC5_IN_SEL, 0x00)| | ||
844 | cx231xx_set_field(FLD_SRC5_CLK_SEL, 0x02)| | ||
845 | cx231xx_set_field(FLD_SRC4_IN_SEL, 0x02)| | ||
846 | cx231xx_set_field(FLD_SRC4_CLK_SEL, 0x03)| | ||
847 | cx231xx_set_field(FLD_SRC3_IN_SEL, 0x00)| | ||
848 | cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x00)| | ||
849 | cx231xx_set_field(FLD_BASEBAND_BYPASS_CTL, 0x00)| | ||
850 | cx231xx_set_field(FLD_AC97_SRC_SEL, 0x03)| | ||
851 | cx231xx_set_field(FLD_I2S_SRC_SEL, 0x00)| | ||
852 | cx231xx_set_field(FLD_PARALLEL2_SRC_SEL, 0x02)| | ||
853 | cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01) , 4); | ||
854 | |||
855 | /* Setup the AUD_IO control */ | ||
856 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AUD_IO_CTRL, 2, | ||
857 | cx231xx_set_field(FLD_I2S_PORT_DIR, 0x00)| | ||
858 | cx231xx_set_field(FLD_I2S_OUT_SRC, 0x00)| | ||
859 | cx231xx_set_field(FLD_AUD_CHAN3_SRC,0x00)| | ||
860 | cx231xx_set_field(FLD_AUD_CHAN2_SRC, 0x00)| | ||
861 | cx231xx_set_field(FLD_AUD_CHAN1_SRC,0x03 ), 4); | ||
862 | |||
863 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F063870, 4); | ||
864 | |||
865 | /* setAudioStandard(_audio_standard); */ | ||
866 | |||
867 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063870, 4); | ||
868 | switch(dev->model) | ||
869 | { | ||
870 | case CX231XX_BOARD_CNXT_RDE_250: | ||
871 | case CX231XX_BOARD_CNXT_RDU_250: | ||
872 | status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, | ||
873 | CHIP_CTRL, FLD_SIF_EN, | ||
874 | cx231xx_set_field(FLD_SIF_EN, 1)); | ||
875 | break; | ||
876 | default: | ||
877 | break; | ||
878 | } | ||
879 | break; | ||
880 | |||
881 | case AUDIO_INPUT_TUNER_FM: | ||
882 | /* use SIF for FM radio | ||
883 | setupFM(); | ||
884 | setAudioStandard(_audio_standard); | ||
885 | */ | ||
886 | break; | ||
887 | |||
888 | case AUDIO_INPUT_MUTE: | ||
889 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F011012, 4); | ||
890 | break; | ||
891 | } | ||
892 | |||
893 | /* Take it out of soft reset */ | ||
894 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, &gen_ctrl, 1); | ||
895 | gen_ctrl &= ~1; | ||
896 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, gen_ctrl, 1); | ||
897 | |||
898 | return status; | ||
899 | } | ||
900 | |||
901 | |||
902 | |||
903 | /* Set resolution of the video */ | ||
904 | int cx231xx_resolution_set(struct cx231xx *dev) | ||
905 | { | ||
906 | int width, height; | ||
907 | u32 hscale, vscale; | ||
908 | int status = 0; | ||
909 | |||
910 | width = dev->width; | ||
911 | height = dev->height; | ||
912 | |||
913 | get_scale(dev,width, height,&hscale, &vscale); | ||
914 | |||
915 | /* set horzontal scale */ | ||
916 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, HSCALE_CTRL, 2, hscale, 4); | ||
917 | |||
918 | /* set vertical scale */ | ||
919 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, VSCALE_CTRL, 2, vscale, 4); | ||
920 | |||
921 | return status; | ||
922 | } | ||
923 | |||
924 | /************************************************************************************* | ||
925 | * C H I P Specific C O N T R O L functions * | ||
926 | *************************************************************************************/ | ||
927 | int cx231xx_init_ctrl_pin_status(struct cx231xx *dev) | ||
928 | { | ||
929 | u32 value; | ||
930 | int status = 0; | ||
931 | |||
932 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, &value, 4); | ||
933 | value |=(~dev->board.ctl_pin_status_mask); | ||
934 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, value, 4); | ||
935 | |||
936 | return status; | ||
937 | } | ||
938 | |||
939 | int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, u8 analog_or_digital) | ||
940 | { | ||
941 | int status = 0; | ||
942 | |||
943 | /* first set the direction to output */ | ||
944 | status = cx231xx_set_gpio_direction(dev, dev->board.agc_analog_digital_select_gpio, 1); | ||
945 | |||
946 | /* 0 - demod ; 1 - Analog mode */ | ||
947 | status = cx231xx_set_gpio_value(dev, dev->board.agc_analog_digital_select_gpio, | ||
948 | analog_or_digital); | ||
949 | |||
950 | return status; | ||
951 | } | ||
952 | |||
953 | int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex) | ||
954 | { | ||
955 | u8 value[4] ={0,0,0,0}; | ||
956 | int status = 0; | ||
957 | |||
958 | cx231xx_info("Changing the i2c port for tuner to %d\n",I2CIndex); | ||
959 | |||
960 | status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); | ||
961 | if(status < 0) | ||
962 | return status; | ||
963 | |||
964 | if(I2CIndex==I2C_1) { | ||
965 | if(value[0] & I2C_DEMOD_EN) { | ||
966 | value[0] &= ~I2C_DEMOD_EN; | ||
967 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
968 | } | ||
969 | } else { | ||
970 | if(!(value[0] & I2C_DEMOD_EN)) { | ||
971 | value[0] |= I2C_DEMOD_EN; | ||
972 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
973 | } | ||
974 | } | ||
975 | |||
976 | return status; | ||
977 | |||
978 | } | ||
979 | |||
980 | |||
981 | /************************************************************************************* | ||
982 | * D I F - B L O C K C O N T R O L functions * | ||
983 | *************************************************************************************/ | ||
984 | int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, | ||
985 | u32 function_mode, u32 standard) | ||
986 | { | ||
987 | int status = 0; | ||
988 | |||
989 | if(mode == V4L2_TUNER_RADIO) { | ||
990 | /* C2HH */ | ||
991 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
992 | AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ | ||
993 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
994 | AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ | ||
995 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
996 | AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); /* IF_MODE */ | ||
997 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
998 | AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ | ||
999 | } | ||
1000 | else { | ||
1001 | switch(standard) { | ||
1002 | case V4L2_STD_NTSC_M: /* 75 IRE Setup */ | ||
1003 | case V4L2_STD_NTSC_M_JP: /* Japan, 0 IRE Setup */ | ||
1004 | case V4L2_STD_PAL_M: | ||
1005 | case V4L2_STD_PAL_N: | ||
1006 | case V4L2_STD_PAL_Nc: | ||
1007 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1008 | AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ | ||
1009 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1010 | AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ | ||
1011 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1012 | AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); /* IF_MODE */ | ||
1013 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1014 | AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ | ||
1015 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1016 | AUD_IO_CTRL, 0, 31, 0x00000003); /* 0x124, AUD_CHAN1_SRC = 0x3 */ | ||
1017 | break; | ||
1018 | |||
1019 | case V4L2_STD_PAL_B: | ||
1020 | case V4L2_STD_PAL_G: | ||
1021 | /* C2HH setup */ | ||
1022 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1023 | AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ | ||
1024 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1025 | AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ | ||
1026 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1027 | AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); /* IF_MODE */ | ||
1028 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1029 | AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ | ||
1030 | break; | ||
1031 | |||
1032 | case V4L2_STD_PAL_D: | ||
1033 | case V4L2_STD_PAL_I: | ||
1034 | case V4L2_STD_SECAM_L: | ||
1035 | case V4L2_STD_SECAM_LC: | ||
1036 | case V4L2_STD_SECAM_B: | ||
1037 | case V4L2_STD_SECAM_D: | ||
1038 | case V4L2_STD_SECAM_G: | ||
1039 | case V4L2_STD_SECAM_K: | ||
1040 | case V4L2_STD_SECAM_K1: | ||
1041 | /* C2HH setup */ | ||
1042 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1043 | AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ | ||
1044 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1045 | AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ | ||
1046 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1047 | AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); /* IF_MODE */ | ||
1048 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, | ||
1049 | AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ | ||
1050 | break; | ||
1051 | |||
1052 | case DIF_USE_BASEBAND: | ||
1053 | default: | ||
1054 | /* do nothing to config C2HH for baseband */ | ||
1055 | break; | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | return status; | ||
1060 | } | ||
1061 | |||
1062 | int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) | ||
1063 | { | ||
1064 | int status = 0; | ||
1065 | u32 dif_misc_ctrl_value = 0; | ||
1066 | u32 func_mode = 0; | ||
1067 | |||
1068 | cx231xx_info("%s: setStandard to %x\n",__func__,standard); | ||
1069 | |||
1070 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1071 | DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, 4); | ||
1072 | if(standard != DIF_USE_BASEBAND ) | ||
1073 | dev->norm = standard; | ||
1074 | |||
1075 | switch (dev->model) { | ||
1076 | case CX231XX_BOARD_CNXT_RDE_250: | ||
1077 | case CX231XX_BOARD_CNXT_RDU_250: | ||
1078 | func_mode=0x03; | ||
1079 | break; | ||
1080 | default: | ||
1081 | func_mode=0x01; | ||
1082 | } | ||
1083 | |||
1084 | status = cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode, func_mode, standard); | ||
1085 | |||
1086 | |||
1087 | if(standard == DIF_USE_BASEBAND ) { /* base band */ | ||
1088 | |||
1089 | /* There is a different SRC_PHASE_INC value for baseband vs. DIF */ | ||
1090 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1091 | DIF_SRC_PHASE_INC, 2, 0xDF7DF83, 4); | ||
1092 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1093 | DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, 4); | ||
1094 | dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS; | ||
1095 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1096 | DIF_MISC_CTRL, 2, dif_misc_ctrl_value, 4); | ||
1097 | |||
1098 | } else if ( standard & (V4L2_STD_PAL_B | V4L2_STD_PAL_G) ) { | ||
1099 | |||
1100 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); | ||
1101 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); | ||
1102 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); | ||
1103 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); | ||
1104 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); | ||
1105 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); | ||
1106 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); | ||
1107 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); | ||
1108 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); | ||
1109 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); | ||
1110 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); | ||
1111 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); | ||
1112 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC); | ||
1113 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00A653A8); | ||
1114 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); | ||
1115 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); | ||
1116 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); | ||
1117 | /* Save the Spec Inversion value */ | ||
1118 | dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; | ||
1119 | dif_misc_ctrl_value |=0x3a013F11; | ||
1120 | |||
1121 | } else if( standard & V4L2_STD_PAL_D ) { | ||
1122 | |||
1123 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); | ||
1124 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); | ||
1125 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); | ||
1126 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); | ||
1127 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); | ||
1128 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); | ||
1129 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); | ||
1130 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); | ||
1131 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); | ||
1132 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); | ||
1133 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); | ||
1134 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); | ||
1135 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA); | ||
1136 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); | ||
1137 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); | ||
1138 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); | ||
1139 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); | ||
1140 | /* Save the Spec Inversion value */ | ||
1141 | dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; | ||
1142 | dif_misc_ctrl_value |=0x3a023F11; | ||
1143 | |||
1144 | } else if( standard & V4L2_STD_PAL_I ) { | ||
1145 | |||
1146 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); | ||
1147 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); | ||
1148 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); | ||
1149 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); | ||
1150 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); | ||
1151 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); | ||
1152 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); | ||
1153 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); | ||
1154 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); | ||
1155 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); | ||
1156 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); | ||
1157 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); | ||
1158 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934); | ||
1159 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); | ||
1160 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); | ||
1161 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); | ||
1162 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); | ||
1163 | /* Save the Spec Inversion value */ | ||
1164 | dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; | ||
1165 | dif_misc_ctrl_value |=0x3a033F11; | ||
1166 | |||
1167 | } else if( standard & V4L2_STD_PAL_M ) { | ||
1168 | |||
1169 | /* improved Low Frequency Phase Noise */ | ||
1170 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1171 | DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); | ||
1172 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1173 | DIF_PLL_CTRL1, 2, 0xbd038c85, 4); | ||
1174 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1175 | DIF_PLL_CTRL2, 2, 0x1db4640a, 4); | ||
1176 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1177 | DIF_PLL_CTRL3, 2, 0x00008800, 4); | ||
1178 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1179 | DIF_AGC_IF_REF, 2, 0x444C1380, 4); | ||
1180 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1181 | DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); | ||
1182 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1183 | DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); | ||
1184 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1185 | DIF_VIDEO_AGC_CTRL, 2, 0x72500800, 4); | ||
1186 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1187 | DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); | ||
1188 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1189 | DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); | ||
1190 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1191 | DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); | ||
1192 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1193 | DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); | ||
1194 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1195 | DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); | ||
1196 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1197 | DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); | ||
1198 | |||
1199 | /* Save the Spec Inversion value */ | ||
1200 | dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; | ||
1201 | dif_misc_ctrl_value |= 0x3A0A3F10; | ||
1202 | |||
1203 | } else if( standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc) ) { | ||
1204 | |||
1205 | /* improved Low Frequency Phase Noise */ | ||
1206 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); | ||
1207 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xbd038c85, 4); | ||
1208 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1db4640a, 4); | ||
1209 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4); | ||
1210 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C1380, 4); | ||
1211 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); | ||
1212 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); | ||
1213 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x72500800, 4); | ||
1214 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); | ||
1215 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); | ||
1216 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); | ||
1217 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); | ||
1218 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); | ||
1219 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); | ||
1220 | |||
1221 | /* Save the Spec Inversion value */ | ||
1222 | dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; | ||
1223 | dif_misc_ctrl_value = 0x3A093F10; | ||
1224 | |||
1225 | } else if( standard & ( V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | | ||
1226 | V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1) ) { | ||
1227 | |||
1228 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); | ||
1229 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); | ||
1230 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); | ||
1231 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); | ||
1232 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); | ||
1233 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); | ||
1234 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); | ||
1235 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); | ||
1236 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); | ||
1237 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); | ||
1238 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); | ||
1239 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); | ||
1240 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); | ||
1241 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); | ||
1242 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); | ||
1243 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); | ||
1244 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf4000000); | ||
1245 | |||
1246 | /* Save the Spec Inversion value */ | ||
1247 | dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; | ||
1248 | dif_misc_ctrl_value |=0x3a023F11; | ||
1249 | |||
1250 | } else if( standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC) ) { | ||
1251 | |||
1252 | /* Is it SECAM_L1? */ | ||
1253 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); | ||
1254 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); | ||
1255 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); | ||
1256 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); | ||
1257 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); | ||
1258 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); | ||
1259 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); | ||
1260 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); | ||
1261 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); | ||
1262 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); | ||
1263 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); | ||
1264 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); | ||
1265 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); | ||
1266 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); | ||
1267 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); | ||
1268 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); | ||
1269 | status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf2560000); | ||
1270 | |||
1271 | /* Save the Spec Inversion value */ | ||
1272 | dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; | ||
1273 | dif_misc_ctrl_value |=0x3a023F11; | ||
1274 | |||
1275 | } else { /* V4L2_STD_NTSC_M (75 IRE Setup) Or V4L2_STD_NTSC_M_JP (Japan, 0 IRE Setup) */ | ||
1276 | |||
1277 | /* For NTSC the centre frequency of video coming out of sidewinder is | ||
1278 | around 7.1MHz or 3.6MHz depending on the spectral inversion. | ||
1279 | so for a non spectrally inverted channel the pll freq word is 0x03420c49 | ||
1280 | */ | ||
1281 | |||
1282 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0x6503BC0C, 4); | ||
1283 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xBD038C85, 4); | ||
1284 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1DB4640A, 4); | ||
1285 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4); | ||
1286 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C0380, 4); | ||
1287 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); | ||
1288 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); | ||
1289 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x04000800, 4); | ||
1290 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); | ||
1291 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x01296e1f, 4); | ||
1292 | |||
1293 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); | ||
1294 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); | ||
1295 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); | ||
1296 | |||
1297 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_IF, 2, 0xC2262600, 4); | ||
1298 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_INT, 2, 0xC2262600, 4); | ||
1299 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_RF, 2, 0xC2262600, 4); | ||
1300 | |||
1301 | /* Save the Spec Inversion value */ | ||
1302 | dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; | ||
1303 | dif_misc_ctrl_value |= 0x3a003F10; | ||
1304 | |||
1305 | } | ||
1306 | |||
1307 | /* The AGC values should be the same for all standards, | ||
1308 | AUD_SRC_SEL[19] should always be disabled */ | ||
1309 | dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL; | ||
1310 | |||
1311 | /* It is still possible to get Set Standard calls even when we are in FM mode | ||
1312 | This is done to override the value for FM. */ | ||
1313 | if (dev->active_mode == V4L2_TUNER_RADIO) | ||
1314 | dif_misc_ctrl_value = 0x7a080000; | ||
1315 | |||
1316 | /* Write the calculated value for misc ontrol register */ | ||
1317 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, dif_misc_ctrl_value, 4); | ||
1318 | |||
1319 | return status; | ||
1320 | } | ||
1321 | |||
1322 | int cx231xx_tuner_pre_channel_change(struct cx231xx *dev) | ||
1323 | { | ||
1324 | int status = 0; | ||
1325 | u32 dwval; | ||
1326 | |||
1327 | /* Set the RF and IF k_agc values to 3 */ | ||
1328 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1329 | DIF_AGC_IF_REF, 2, &dwval, 4); | ||
1330 | dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); | ||
1331 | dwval |= 0x33000000; | ||
1332 | |||
1333 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1334 | DIF_AGC_IF_REF, 2, dwval, 4); | ||
1335 | |||
1336 | return status; | ||
1337 | } | ||
1338 | |||
1339 | int cx231xx_tuner_post_channel_change(struct cx231xx *dev) | ||
1340 | { | ||
1341 | int status = 0; | ||
1342 | u32 dwval; | ||
1343 | |||
1344 | /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for SECAM */ | ||
1345 | status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1346 | DIF_AGC_IF_REF, 2, &dwval, 4); | ||
1347 | dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); | ||
1348 | |||
1349 | if(dev->norm & ( V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | V4L2_STD_SECAM_D) ) { | ||
1350 | dwval |= 0x88000000; | ||
1351 | } else { | ||
1352 | dwval |= 0x44000000; | ||
1353 | } | ||
1354 | |||
1355 | status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, | ||
1356 | DIF_AGC_IF_REF, 2, dwval, 4); | ||
1357 | |||
1358 | return status; | ||
1359 | } | ||
1360 | |||
1361 | |||
1362 | |||
1363 | /************************************************************************************* | ||
1364 | * F L A T I R O N - B L O C K C O N T R O L functions * | ||
1365 | *************************************************************************************/ | ||
1366 | int cx231xx_flatiron_initialize(struct cx231xx *dev) | ||
1367 | { | ||
1368 | int status = 0; | ||
1369 | u32 value; | ||
1370 | |||
1371 | status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL1, 1, &value, 1); | ||
1372 | /* enables clock to delta-sigma and decimation filter */ | ||
1373 | value |= 0x80; | ||
1374 | status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, | ||
1375 | CH_PWR_CTRL1, 1, value, 1); | ||
1376 | /* power up all channel */ | ||
1377 | status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, | ||
1378 | CH_PWR_CTRL2, 1, 0x00, 1); | ||
1379 | |||
1380 | return status; | ||
1381 | } | ||
1382 | |||
1383 | int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode) | ||
1384 | { | ||
1385 | int status = 0; | ||
1386 | u32 value=0; | ||
1387 | |||
1388 | if(avmode!=POLARIS_AVMODE_ENXTERNAL_AV) { | ||
1389 | status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, &value, 1); | ||
1390 | value |= 0xfe; | ||
1391 | status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, | ||
1392 | CH_PWR_CTRL2, 1, value, 1); | ||
1393 | } | ||
1394 | else { | ||
1395 | status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, | ||
1396 | CH_PWR_CTRL2, 1, 0x00, 1); | ||
1397 | } | ||
1398 | |||
1399 | return status; | ||
1400 | } | ||
1401 | |||
1402 | /* set flatiron for audio input types */ | ||
1403 | int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input) | ||
1404 | { | ||
1405 | int status = 0; | ||
1406 | |||
1407 | switch(audio_input) { | ||
1408 | case CX231XX_AMUX_LINE_IN: | ||
1409 | |||
1410 | status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, | ||
1411 | CH_PWR_CTRL2, 1, 0x00, 1); | ||
1412 | status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, | ||
1413 | CH_PWR_CTRL1, 1, 0x80, 1); | ||
1414 | break; | ||
1415 | case CX231XX_AMUX_VIDEO: | ||
1416 | default: | ||
1417 | break; | ||
1418 | } | ||
1419 | |||
1420 | dev->ctl_ainput = audio_input; | ||
1421 | |||
1422 | return status; | ||
1423 | } | ||
1424 | |||
1425 | /************************************************************************************* | ||
1426 | * P O W E R C O N T R O L functions * | ||
1427 | *************************************************************************************/ | ||
1428 | int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) | ||
1429 | { | ||
1430 | u8 value[4] ={0,0,0,0}; | ||
1431 | u32 tmp = 0; | ||
1432 | int status = 0; | ||
1433 | |||
1434 | if(dev->power_mode != mode) | ||
1435 | dev->power_mode = mode; | ||
1436 | else { | ||
1437 | cx231xx_info(" setPowerMode::mode = %d, No Change req.\n",mode); | ||
1438 | return 0; | ||
1439 | } | ||
1440 | |||
1441 | cx231xx_info(" setPowerMode::mode = %d\n",mode); | ||
1442 | |||
1443 | status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); | ||
1444 | if(status < 0) | ||
1445 | return status; | ||
1446 | |||
1447 | tmp = *((u32 *)value); | ||
1448 | |||
1449 | switch(mode) { | ||
1450 | case POLARIS_AVMODE_ENXTERNAL_AV: | ||
1451 | |||
1452 | tmp &= (~PWR_MODE_MASK); | ||
1453 | |||
1454 | tmp |= PWR_AV_EN; | ||
1455 | value[0]=(u8)tmp; | ||
1456 | value[1]=(u8)(tmp>>8); | ||
1457 | value[2]=(u8)(tmp>>16); | ||
1458 | value[3]=(u8)(tmp>>24); | ||
1459 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1460 | msleep(PWR_SLEEP_INTERVAL); | ||
1461 | |||
1462 | tmp |= PWR_ISO_EN; | ||
1463 | value[0]=(u8)tmp; | ||
1464 | value[1]=(u8)(tmp>>8); | ||
1465 | value[2]=(u8)(tmp>>16); | ||
1466 | value[3]=(u8)(tmp>>24); | ||
1467 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1468 | msleep(PWR_SLEEP_INTERVAL); | ||
1469 | |||
1470 | tmp |=POLARIS_AVMODE_ENXTERNAL_AV; | ||
1471 | value[0]=(u8)tmp; | ||
1472 | value[1]=(u8)(tmp>>8); | ||
1473 | value[2]=(u8)(tmp>>16); | ||
1474 | value[3]=(u8)(tmp>>24); | ||
1475 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1476 | |||
1477 | dev->xc_fw_load_done = 0; /* reset state of xceive tuner */ | ||
1478 | break; | ||
1479 | |||
1480 | case POLARIS_AVMODE_ANALOGT_TV: | ||
1481 | |||
1482 | tmp &= (~PWR_DEMOD_EN); | ||
1483 | tmp |= (I2C_DEMOD_EN); | ||
1484 | value[0]=(u8)tmp; | ||
1485 | value[1]=(u8)(tmp>>8); | ||
1486 | value[2]=(u8)(tmp>>16); | ||
1487 | value[3]=(u8)(tmp>>24); | ||
1488 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1489 | msleep(PWR_SLEEP_INTERVAL); | ||
1490 | |||
1491 | if(!(tmp & PWR_TUNER_EN)) { | ||
1492 | tmp |= (PWR_TUNER_EN); | ||
1493 | value[0]=(u8)tmp; | ||
1494 | value[1]=(u8)(tmp>>8); | ||
1495 | value[2]=(u8)(tmp>>16); | ||
1496 | value[3]=(u8)(tmp>>24); | ||
1497 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1498 | msleep(PWR_SLEEP_INTERVAL); | ||
1499 | } | ||
1500 | |||
1501 | if(!(tmp & PWR_AV_EN)) { | ||
1502 | tmp |= PWR_AV_EN; | ||
1503 | value[0]=(u8)tmp; | ||
1504 | value[1]=(u8)(tmp>>8); | ||
1505 | value[2]=(u8)(tmp>>16); | ||
1506 | value[3]=(u8)(tmp>>24); | ||
1507 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1508 | msleep(PWR_SLEEP_INTERVAL); | ||
1509 | } | ||
1510 | if(!(tmp & PWR_ISO_EN )) { | ||
1511 | tmp |= PWR_ISO_EN; | ||
1512 | value[0]=(u8)tmp; | ||
1513 | value[1]=(u8)(tmp>>8); | ||
1514 | value[2]=(u8)(tmp>>16); | ||
1515 | value[3]=(u8)(tmp>>24); | ||
1516 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1517 | msleep(PWR_SLEEP_INTERVAL); | ||
1518 | } | ||
1519 | |||
1520 | if(!(tmp & POLARIS_AVMODE_ANALOGT_TV )) { | ||
1521 | tmp |= POLARIS_AVMODE_ANALOGT_TV; | ||
1522 | value[0]=(u8)tmp; | ||
1523 | value[1]=(u8)(tmp>>8); | ||
1524 | value[2]=(u8)(tmp>>16); | ||
1525 | value[3]=(u8)(tmp>>24); | ||
1526 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1527 | msleep(PWR_SLEEP_INTERVAL); | ||
1528 | } | ||
1529 | |||
1530 | if( (dev->model == CX231XX_BOARD_CNXT_RDE_250) || | ||
1531 | (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { | ||
1532 | |||
1533 | /* tuner path to channel 1 from port 3 */ | ||
1534 | cx231xx_enable_i2c_for_tuner(dev, I2C_3); | ||
1535 | |||
1536 | if(dev->cx231xx_reset_analog_tuner) | ||
1537 | dev->cx231xx_reset_analog_tuner(dev); | ||
1538 | } | ||
1539 | break; | ||
1540 | |||
1541 | case POLARIS_AVMODE_DIGITAL: | ||
1542 | |||
1543 | if(!(tmp & PWR_TUNER_EN)) { | ||
1544 | tmp |= (PWR_TUNER_EN); | ||
1545 | value[0]=(u8)tmp; | ||
1546 | value[1]=(u8)(tmp>>8); | ||
1547 | value[2]=(u8)(tmp>>16); | ||
1548 | value[3]=(u8)(tmp>>24); | ||
1549 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1550 | msleep(PWR_SLEEP_INTERVAL); | ||
1551 | } | ||
1552 | if(!(tmp & PWR_AV_EN)) { | ||
1553 | tmp |= PWR_AV_EN; | ||
1554 | value[0]=(u8)tmp; | ||
1555 | value[1]=(u8)(tmp>>8); | ||
1556 | value[2]=(u8)(tmp>>16); | ||
1557 | value[3]=(u8)(tmp>>24); | ||
1558 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1559 | msleep(PWR_SLEEP_INTERVAL); | ||
1560 | } | ||
1561 | if(!(tmp & PWR_ISO_EN)) { | ||
1562 | tmp |= PWR_ISO_EN; | ||
1563 | value[0]=(u8)tmp; | ||
1564 | value[1]=(u8)(tmp>>8); | ||
1565 | value[2]=(u8)(tmp>>16); | ||
1566 | value[3]=(u8)(tmp>>24); | ||
1567 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1568 | msleep(PWR_SLEEP_INTERVAL); | ||
1569 | } | ||
1570 | |||
1571 | tmp |= POLARIS_AVMODE_DIGITAL|I2C_DEMOD_EN; | ||
1572 | value[0]=(u8)tmp; | ||
1573 | value[1]=(u8)(tmp>>8); | ||
1574 | value[2]=(u8)(tmp>>16); | ||
1575 | value[3]=(u8)(tmp>>24); | ||
1576 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1577 | msleep(PWR_SLEEP_INTERVAL); | ||
1578 | |||
1579 | if(!(tmp & PWR_DEMOD_EN)) { | ||
1580 | tmp |= PWR_DEMOD_EN; | ||
1581 | value[0]=(u8)tmp; | ||
1582 | value[1]=(u8)(tmp>>8); | ||
1583 | value[2]=(u8)(tmp>>16); | ||
1584 | value[3]=(u8)(tmp>>24); | ||
1585 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1586 | msleep(PWR_SLEEP_INTERVAL); | ||
1587 | } | ||
1588 | |||
1589 | if( (dev->model == CX231XX_BOARD_CNXT_RDE_250) || | ||
1590 | (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { | ||
1591 | |||
1592 | /* tuner path to channel 1 from port 3 */ | ||
1593 | cx231xx_enable_i2c_for_tuner(dev, I2C_3); | ||
1594 | |||
1595 | if(dev->cx231xx_reset_analog_tuner) | ||
1596 | dev->cx231xx_reset_analog_tuner(dev); | ||
1597 | } | ||
1598 | break; | ||
1599 | |||
1600 | default: | ||
1601 | break; | ||
1602 | } | ||
1603 | |||
1604 | msleep(PWR_SLEEP_INTERVAL); | ||
1605 | |||
1606 | /* For power saving, only enable Pwr_resetout_n when digital TV is selected. */ | ||
1607 | if(mode == POLARIS_AVMODE_DIGITAL) { | ||
1608 | tmp |= PWR_RESETOUT_EN; | ||
1609 | value[0]=(u8)tmp; | ||
1610 | value[1]=(u8)(tmp>>8); | ||
1611 | value[2]=(u8)(tmp>>16); | ||
1612 | value[3]=(u8)(tmp>>24); | ||
1613 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1614 | msleep(PWR_SLEEP_INTERVAL); | ||
1615 | } | ||
1616 | |||
1617 | /* update power control for colibri */ | ||
1618 | status = cx231xx_colibri_update_power_control(dev, mode); | ||
1619 | |||
1620 | /* update power control for flatiron */ | ||
1621 | status = cx231xx_flatiron_update_power_control(dev, mode); | ||
1622 | |||
1623 | status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); | ||
1624 | cx231xx_info(" The data of PWR_CTL_EN register 0x74=0x%0x,0x%0x,0x%0x,0x%0x\n",value[0],value[1],value[2],value[3]); | ||
1625 | |||
1626 | return status; | ||
1627 | } | ||
1628 | |||
1629 | int cx231xx_power_suspend(struct cx231xx *dev) | ||
1630 | { | ||
1631 | u8 value[4] ={0,0,0,0}; | ||
1632 | u32 tmp = 0; | ||
1633 | int status = 0; | ||
1634 | |||
1635 | status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); | ||
1636 | if(status > 0) | ||
1637 | return status; | ||
1638 | |||
1639 | tmp = *((u32 *)value); | ||
1640 | tmp &= (~PWR_MODE_MASK); | ||
1641 | |||
1642 | value[0]=(u8)tmp; | ||
1643 | value[1]=(u8)(tmp>>8); | ||
1644 | value[2]=(u8)(tmp>>16); | ||
1645 | value[3]=(u8)(tmp>>24); | ||
1646 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); | ||
1647 | |||
1648 | return status; | ||
1649 | } | ||
1650 | |||
1651 | |||
1652 | /************************************************************************************* | ||
1653 | * S T R E A M C O N T R O L functions * | ||
1654 | *************************************************************************************/ | ||
1655 | int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask) | ||
1656 | { | ||
1657 | u8 value[4] = {0x0, 0x0, 0x0, 0x0}; | ||
1658 | u32 tmp =0; | ||
1659 | int status = 0; | ||
1660 | |||
1661 | cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask); | ||
1662 | status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, EP_MODE_SET,value,4); | ||
1663 | if(status < 0) | ||
1664 | return status; | ||
1665 | |||
1666 | tmp = *((u32 *)value); | ||
1667 | tmp |= ep_mask; | ||
1668 | value[0]=(u8) tmp; | ||
1669 | value[1]=(u8)(tmp>>8); | ||
1670 | value[2]=(u8)(tmp>>16); | ||
1671 | value[3]=(u8)(tmp>>24); | ||
1672 | |||
1673 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, EP_MODE_SET,value,4); | ||
1674 | |||
1675 | return status; | ||
1676 | } | ||
1677 | |||
1678 | int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask) | ||
1679 | { | ||
1680 | u8 value[4] = {0x0, 0x0, 0x0, 0x0}; | ||
1681 | u32 tmp =0; | ||
1682 | int status = 0; | ||
1683 | |||
1684 | cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask); | ||
1685 | status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, EP_MODE_SET,value,4); | ||
1686 | if(status < 0) | ||
1687 | return status; | ||
1688 | |||
1689 | tmp = *((u32 *)value); | ||
1690 | tmp&= (~ep_mask); | ||
1691 | value[0]=(u8) tmp; | ||
1692 | value[1]=(u8)(tmp>>8); | ||
1693 | value[2]=(u8)(tmp>>16); | ||
1694 | value[3]=(u8)(tmp>>24); | ||
1695 | |||
1696 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, EP_MODE_SET,value,4); | ||
1697 | |||
1698 | return status; | ||
1699 | } | ||
1700 | |||
1701 | int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) | ||
1702 | { | ||
1703 | int status = 0; | ||
1704 | |||
1705 | if(dev->udev->speed == USB_SPEED_HIGH) | ||
1706 | { | ||
1707 | switch(media_type) | ||
1708 | { | ||
1709 | case 81: /* audio */ | ||
1710 | cx231xx_info("%s: Audio enter HANC\n",__func__); | ||
1711 | status = cx231xx_mode_register(dev, TS_MODE_REG, 0x9300); | ||
1712 | break; | ||
1713 | |||
1714 | case 2: /* vbi */ | ||
1715 | cx231xx_info("%s: set vanc registers\n",__func__); | ||
1716 | status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300); | ||
1717 | break; | ||
1718 | |||
1719 | case 3: /* sliced cc */ | ||
1720 | cx231xx_info("%s: set hanc registers\n",__func__); | ||
1721 | status = cx231xx_mode_register(dev, TS_MODE_REG, 0x1300); | ||
1722 | break; | ||
1723 | |||
1724 | case 0: /* video */ | ||
1725 | cx231xx_info("%s: set video registers\n",__func__); | ||
1726 | status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); | ||
1727 | break; | ||
1728 | |||
1729 | case 4: /* ts1 */ | ||
1730 | cx231xx_info("%s: set ts1 registers\n",__func__); | ||
1731 | status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); | ||
1732 | status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); | ||
1733 | break; | ||
1734 | case 6: /* ts1 parallel mode */ | ||
1735 | cx231xx_info("%s: set ts1 parrallel mode registers\n",__func__); | ||
1736 | status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); | ||
1737 | status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); | ||
1738 | break; | ||
1739 | } | ||
1740 | } | ||
1741 | else | ||
1742 | { | ||
1743 | status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); | ||
1744 | } | ||
1745 | |||
1746 | return status; | ||
1747 | } | ||
1748 | |||
1749 | |||
1750 | |||
1751 | |||
1752 | int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) | ||
1753 | { | ||
1754 | int rc; | ||
1755 | u32 ep_mask = -1; | ||
1756 | PPCB_CONFIG pcb_config; | ||
1757 | |||
1758 | /* get EP for media type */ | ||
1759 | pcb_config = &dev->current_pcb_config; | ||
1760 | |||
1761 | if(pcb_config->config_num==1) | ||
1762 | { | ||
1763 | switch (media_type) | ||
1764 | { | ||
1765 | case 0: /* Video */ | ||
1766 | ep_mask =ENABLE_EP4; /* ep4 [00:1000] */ | ||
1767 | break; | ||
1768 | case 1: /* Audio */ | ||
1769 | ep_mask =ENABLE_EP3; /* ep3 [00:0100] */ | ||
1770 | break; | ||
1771 | case 2: /* Vbi */ | ||
1772 | ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ | ||
1773 | break; | ||
1774 | case 3: /* Sliced_cc */ | ||
1775 | ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ | ||
1776 | break; | ||
1777 | case 4: /* ts1 */ | ||
1778 | case 6: /* ts1 parallel mode */ | ||
1779 | ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ | ||
1780 | break; | ||
1781 | case 5: /* ts2 */ | ||
1782 | ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ | ||
1783 | break; | ||
1784 | } | ||
1785 | |||
1786 | } | ||
1787 | else if(pcb_config->config_num>1) | ||
1788 | { | ||
1789 | switch (media_type) | ||
1790 | { | ||
1791 | case 0: /* Video */ | ||
1792 | ep_mask = ENABLE_EP4; /* ep4 [00:1000] */ | ||
1793 | break; | ||
1794 | case 1: /* Audio */ | ||
1795 | ep_mask = ENABLE_EP3; /* ep3 [00:0100] */ | ||
1796 | break; | ||
1797 | case 2: /* Vbi */ | ||
1798 | ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ | ||
1799 | break; | ||
1800 | case 3: /* Sliced_cc */ | ||
1801 | ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ | ||
1802 | break; | ||
1803 | case 4: /* ts1 */ | ||
1804 | case 6: /* ts1 parallel mode */ | ||
1805 | ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ | ||
1806 | break; | ||
1807 | case 5: /* ts2 */ | ||
1808 | ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ | ||
1809 | break; | ||
1810 | } | ||
1811 | |||
1812 | } | ||
1813 | |||
1814 | if(start) { | ||
1815 | rc = cx231xx_initialize_stream_xfer(dev, media_type); | ||
1816 | |||
1817 | if(rc < 0) { | ||
1818 | return rc; | ||
1819 | } | ||
1820 | |||
1821 | /* enable video capture */ | ||
1822 | if(ep_mask > 0 ) | ||
1823 | rc = cx231xx_start_stream(dev, ep_mask); | ||
1824 | } | ||
1825 | else { | ||
1826 | /* disable video capture */ | ||
1827 | if(ep_mask > 0 ) | ||
1828 | rc = cx231xx_stop_stream(dev, ep_mask); | ||
1829 | } | ||
1830 | |||
1831 | if (dev->mode == CX231XX_ANALOG_MODE){ | ||
1832 | /* do any in Analog mode */ | ||
1833 | } | ||
1834 | else { | ||
1835 | /* do any in digital mode */ | ||
1836 | } | ||
1837 | |||
1838 | return rc; | ||
1839 | } | ||
1840 | EXPORT_SYMBOL_GPL(cx231xx_capture_start); | ||
1841 | |||
1842 | |||
1843 | /************************************************************************************ | ||
1844 | * G P I O B I T control functions * | ||
1845 | *************************************************************************************/ | ||
1846 | int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val) | ||
1847 | { | ||
1848 | int status = 0; | ||
1849 | |||
1850 | status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 0); | ||
1851 | |||
1852 | return status; | ||
1853 | } | ||
1854 | |||
1855 | int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val) | ||
1856 | { | ||
1857 | int status = 0; | ||
1858 | |||
1859 | status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 1); | ||
1860 | |||
1861 | return status; | ||
1862 | } | ||
1863 | |||
1864 | /* | ||
1865 | * cx231xx_set_gpio_direction | ||
1866 | * Sets the direction of the GPIO pin to input or output | ||
1867 | * | ||
1868 | * Parameters : | ||
1869 | * pin_number : The GPIO Pin number to program the direction for | ||
1870 | * from 0 to 31 | ||
1871 | * pin_value : The Direction of the GPIO Pin under reference. | ||
1872 | * 0 = Input direction | ||
1873 | * 1 = Output direction | ||
1874 | */ | ||
1875 | int cx231xx_set_gpio_direction(struct cx231xx *dev, | ||
1876 | int pin_number, | ||
1877 | int pin_value) | ||
1878 | { | ||
1879 | int status = 0; | ||
1880 | u32 value = 0; | ||
1881 | |||
1882 | /* Check for valid pin_number - if 32 , bail out */ | ||
1883 | if (pin_number >= 32) { | ||
1884 | return -EINVAL; | ||
1885 | } | ||
1886 | |||
1887 | if (pin_value == 0) { /* input */ | ||
1888 | value = dev->gpio_dir &(~(1<<pin_number)) ; /* clear */ | ||
1889 | } else { | ||
1890 | value = dev->gpio_dir | (1<<pin_number) ; | ||
1891 | } | ||
1892 | |||
1893 | status = cx231xx_set_gpio_bit(dev, value, (u8*) & dev->gpio_val); | ||
1894 | |||
1895 | /* cache the value for future */ | ||
1896 | dev->gpio_dir = value; | ||
1897 | |||
1898 | return status; | ||
1899 | } | ||
1900 | |||
1901 | |||
1902 | /* | ||
1903 | * SetGpioPinLogicValue | ||
1904 | * Sets the value of the GPIO pin to Logic high or low. The Pin under | ||
1905 | * reference should ALREADY BE SET IN OUTPUT MODE !!!!!!!!! | ||
1906 | * | ||
1907 | * Parameters : | ||
1908 | * pin_number : The GPIO Pin number to program the direction for | ||
1909 | * pin_value : The value of the GPIO Pin under reference. | ||
1910 | * 0 = set it to 0 | ||
1911 | * 1 = set it to 1 | ||
1912 | */ | ||
1913 | int cx231xx_set_gpio_value(struct cx231xx *dev, | ||
1914 | int pin_number, | ||
1915 | int pin_value) | ||
1916 | { | ||
1917 | int status = 0; | ||
1918 | u32 value = 0; | ||
1919 | |||
1920 | /* Check for valid pin_number - if 0xFF , bail out */ | ||
1921 | if (pin_number >= 32) | ||
1922 | return -EINVAL; | ||
1923 | |||
1924 | /* first do a sanity check - if the Pin is not output, make it output */ | ||
1925 | if ((dev->gpio_dir & (1<<pin_number)) == 0x00) | ||
1926 | { | ||
1927 | /* It was in input mode */ | ||
1928 | value = dev->gpio_dir | (1<<pin_number) ; | ||
1929 | dev->gpio_dir = value; | ||
1930 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
1931 | value = 0; | ||
1932 | } | ||
1933 | |||
1934 | if (pin_value == 0) { | ||
1935 | value = dev->gpio_val & (~(1<<pin_number)); | ||
1936 | } else { | ||
1937 | value = dev->gpio_val | (1<<pin_number); | ||
1938 | } | ||
1939 | |||
1940 | /* store the value */ | ||
1941 | dev->gpio_val=value; | ||
1942 | |||
1943 | /* toggle bit0 of GP_IO */ | ||
1944 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
1945 | |||
1946 | return status; | ||
1947 | } | ||
1948 | |||
1949 | |||
1950 | /************************************************************************************ | ||
1951 | * G P I O I2C related functions * | ||
1952 | *************************************************************************************/ | ||
1953 | int cx231xx_gpio_i2c_start(struct cx231xx *dev) | ||
1954 | { | ||
1955 | int status = 0; | ||
1956 | |||
1957 | /* set SCL to output 1 ; set SDA to output 1 */ | ||
1958 | dev->gpio_dir |= 1<< dev->board.tuner_scl_gpio; | ||
1959 | dev->gpio_dir |= 1<<dev->board.tuner_sda_gpio; | ||
1960 | dev->gpio_val |= 1<<dev->board.tuner_scl_gpio; | ||
1961 | dev->gpio_val |= 1<<dev->board.tuner_sda_gpio; | ||
1962 | |||
1963 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
1964 | if(status < 0){ | ||
1965 | return -EINVAL; | ||
1966 | } | ||
1967 | |||
1968 | /* set SCL to output 1; set SDA to output 0 */ | ||
1969 | dev->gpio_val |= 1<<dev->board.tuner_scl_gpio; | ||
1970 | dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio); | ||
1971 | |||
1972 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
1973 | if(status < 0){ | ||
1974 | return -EINVAL; | ||
1975 | } | ||
1976 | |||
1977 | /* set SCL to output 0; set SDA to output 0 */ | ||
1978 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
1979 | dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio); | ||
1980 | |||
1981 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
1982 | if(status < 0){ | ||
1983 | return -EINVAL; | ||
1984 | } | ||
1985 | |||
1986 | return status; | ||
1987 | } | ||
1988 | |||
1989 | |||
1990 | int cx231xx_gpio_i2c_end(struct cx231xx *dev) | ||
1991 | { | ||
1992 | int status = 0; | ||
1993 | |||
1994 | /* set SCL to output 0; set SDA to output 0 */ | ||
1995 | dev->gpio_dir |= 1<<dev->board.tuner_scl_gpio; | ||
1996 | dev->gpio_dir |= 1<<dev->board.tuner_sda_gpio; | ||
1997 | |||
1998 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
1999 | dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio); | ||
2000 | |||
2001 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2002 | if(status < 0){ | ||
2003 | return -EINVAL; | ||
2004 | } | ||
2005 | |||
2006 | /* set SCL to output 1; set SDA to output 0 */ | ||
2007 | dev->gpio_val |= 1<<dev->board.tuner_scl_gpio; | ||
2008 | dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio); | ||
2009 | |||
2010 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2011 | if(status < 0){ | ||
2012 | return -EINVAL; | ||
2013 | } | ||
2014 | |||
2015 | /* set SCL to input ,release SCL cable control | ||
2016 | set SDA to input ,release SDA cable control */ | ||
2017 | dev->gpio_dir &= ~(1<<dev->board.tuner_scl_gpio); | ||
2018 | dev->gpio_dir &= ~(1<<dev->board.tuner_sda_gpio); | ||
2019 | |||
2020 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2021 | if(status < 0){ | ||
2022 | return -EINVAL; | ||
2023 | } | ||
2024 | return status; | ||
2025 | } | ||
2026 | |||
2027 | |||
2028 | int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data) | ||
2029 | { | ||
2030 | int status = 0; | ||
2031 | u8 i; | ||
2032 | |||
2033 | /* set SCL to output ; set SDA to output */ | ||
2034 | dev->gpio_dir |= 1<<dev->board.tuner_scl_gpio; | ||
2035 | dev->gpio_dir |= 1<<dev->board.tuner_sda_gpio; | ||
2036 | |||
2037 | for(i = 0;i<8;i++) { | ||
2038 | if(((data<<i) & 0x80) == 0) { | ||
2039 | /* set SCL to output 0; set SDA to output 0 */ | ||
2040 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2041 | dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio); | ||
2042 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2043 | |||
2044 | /* set SCL to output 1; set SDA to output 0 */ | ||
2045 | dev->gpio_val |= 1<<dev->board.tuner_scl_gpio; | ||
2046 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2047 | |||
2048 | /* set SCL to output 0; set SDA to output 0 */ | ||
2049 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2050 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2051 | } else { | ||
2052 | /* set SCL to output 0; set SDA to output 1 */ | ||
2053 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2054 | dev->gpio_val |= 1<<dev->board.tuner_sda_gpio; | ||
2055 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2056 | |||
2057 | /* set SCL to output 1; set SDA to output 1 */ | ||
2058 | dev->gpio_val |= 1<<dev->board.tuner_scl_gpio; | ||
2059 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2060 | |||
2061 | /* set SCL to output 0; set SDA to output 1 */ | ||
2062 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2063 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2064 | } | ||
2065 | } | ||
2066 | return status; | ||
2067 | } | ||
2068 | |||
2069 | int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf) | ||
2070 | { | ||
2071 | u8 value = 0; | ||
2072 | int status = 0; | ||
2073 | u32 gpio_logic_value =0; | ||
2074 | u8 i; | ||
2075 | |||
2076 | /* read byte */ | ||
2077 | for(i=0;i<8;i++) { /* send write I2c addr */ | ||
2078 | |||
2079 | /* set SCL to output 0; set SDA to input */ | ||
2080 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2081 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2082 | |||
2083 | /* set SCL to output 1; set SDA to input */ | ||
2084 | dev->gpio_val |= 1<<dev->board.tuner_scl_gpio; | ||
2085 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2086 | |||
2087 | /* get SDA data bit */ | ||
2088 | gpio_logic_value = dev->gpio_val; | ||
2089 | status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2090 | if((dev->gpio_val & (1<<dev->board.tuner_sda_gpio)) != 0) { | ||
2091 | value |= (1<<(8-i-1)); | ||
2092 | } | ||
2093 | |||
2094 | dev->gpio_val = gpio_logic_value; | ||
2095 | } | ||
2096 | |||
2097 | /* set SCL to output 0,finish the read latest SCL signal. | ||
2098 | !!!set SDA to input,never to modify SDA direction at the same times */ | ||
2099 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2100 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2101 | |||
2102 | /* store the value */ | ||
2103 | *buf = value & 0xff; | ||
2104 | |||
2105 | return status; | ||
2106 | } | ||
2107 | |||
2108 | int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev) | ||
2109 | { | ||
2110 | int status = 0; | ||
2111 | u32 gpio_logic_value = 0; | ||
2112 | int nCnt=10; | ||
2113 | int nInit=nCnt; | ||
2114 | |||
2115 | /* clock stretch; set SCL to input; set SDA to input; get SCL value till SCL = 1 */ | ||
2116 | dev->gpio_dir &= ~(1<<dev->board.tuner_sda_gpio); | ||
2117 | dev->gpio_dir &= ~(1<<dev->board.tuner_scl_gpio); | ||
2118 | |||
2119 | gpio_logic_value = dev->gpio_val; | ||
2120 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2121 | |||
2122 | do{ | ||
2123 | msleep(2); | ||
2124 | status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2125 | nCnt--; | ||
2126 | }while(((dev->gpio_val & (1<<dev->board.tuner_scl_gpio)) == 0) && (nCnt>0)); | ||
2127 | |||
2128 | if(nCnt==0) { | ||
2129 | cx231xx_info("No ACK after %d msec for clock stretch. GPIO I2C operation failed!",nInit*10); | ||
2130 | } | ||
2131 | |||
2132 | /* readAck | ||
2133 | throuth clock stretch ,slave has given a SCL signal,so the SDA data can be directly read. */ | ||
2134 | status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2135 | |||
2136 | if((dev->gpio_val & 1<< dev->board.tuner_sda_gpio) == 0){ | ||
2137 | dev->gpio_val = gpio_logic_value; | ||
2138 | dev->gpio_val &= ~(1<< dev->board.tuner_sda_gpio); | ||
2139 | status = 0; | ||
2140 | } else { | ||
2141 | dev->gpio_val = gpio_logic_value; | ||
2142 | dev->gpio_val |= (1<< dev->board.tuner_sda_gpio); | ||
2143 | } | ||
2144 | |||
2145 | /* read SDA end, set the SCL to output 0, after this operation, SDA direction can be changed. */ | ||
2146 | dev->gpio_val = gpio_logic_value; | ||
2147 | dev->gpio_dir |= (1<<dev->board.tuner_scl_gpio); | ||
2148 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2149 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2150 | |||
2151 | return status; | ||
2152 | } | ||
2153 | |||
2154 | |||
2155 | int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev) | ||
2156 | { | ||
2157 | int status = 0; | ||
2158 | |||
2159 | /* set SDA to ouput */ | ||
2160 | dev->gpio_dir |= 1<<dev->board.tuner_sda_gpio; | ||
2161 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2162 | |||
2163 | /* set SCL = 0 (output); set SDA = 0 (output) */ | ||
2164 | dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio); | ||
2165 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2166 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2167 | |||
2168 | /* set SCL = 1 (output); set SDA = 0 (output) */ | ||
2169 | dev->gpio_val |= 1<<dev->board.tuner_scl_gpio; | ||
2170 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2171 | |||
2172 | /* set SCL = 0 (output); set SDA = 0 (output) */ | ||
2173 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2174 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2175 | |||
2176 | /* set SDA to input,and then the slave will read data from SDA. */ | ||
2177 | dev->gpio_dir &= ~(1<<dev->board.tuner_sda_gpio); | ||
2178 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2179 | |||
2180 | return status; | ||
2181 | } | ||
2182 | |||
2183 | int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev) | ||
2184 | { | ||
2185 | int status = 0; | ||
2186 | |||
2187 | /* set scl to output ; set sda to input */ | ||
2188 | dev->gpio_dir |= 1<<dev->board.tuner_scl_gpio; | ||
2189 | dev->gpio_dir &= ~(1<<dev->board.tuner_sda_gpio); | ||
2190 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2191 | |||
2192 | /* set scl to output 0; set sda to input */ | ||
2193 | dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio); | ||
2194 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2195 | |||
2196 | /* set scl to output 1; set sda to input */ | ||
2197 | dev->gpio_val |= 1<<dev->board.tuner_scl_gpio; | ||
2198 | status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); | ||
2199 | |||
2200 | return status; | ||
2201 | } | ||
2202 | |||
2203 | |||
2204 | |||
2205 | /************************************************************************************ | ||
2206 | * G P I O I2C related functions * | ||
2207 | *************************************************************************************/ | ||
2208 | /* cx231xx_gpio_i2c_read | ||
2209 | * Function to read data from gpio based I2C interface | ||
2210 | */ | ||
2211 | int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len) | ||
2212 | { | ||
2213 | int status = 0; | ||
2214 | int i = 0; | ||
2215 | |||
2216 | /* get the lock */ | ||
2217 | mutex_lock(&dev->gpio_i2c_lock); | ||
2218 | |||
2219 | /* start */ | ||
2220 | status = cx231xx_gpio_i2c_start(dev); | ||
2221 | |||
2222 | /* write dev_addr */ | ||
2223 | status = cx231xx_gpio_i2c_write_byte(dev, (dev_addr << 1) +1); | ||
2224 | |||
2225 | /* readAck */ | ||
2226 | status = cx231xx_gpio_i2c_read_ack(dev); | ||
2227 | |||
2228 | /* read data */ | ||
2229 | for(i = 0; i < len; i++ ) { | ||
2230 | /* read data */ | ||
2231 | buf[i] = 0; | ||
2232 | status = cx231xx_gpio_i2c_read_byte(dev, & buf[i]); | ||
2233 | |||
2234 | if( (i+1) != len) { | ||
2235 | /* only do write ack if we more length */ | ||
2236 | status = cx231xx_gpio_i2c_write_ack(dev); | ||
2237 | } | ||
2238 | } | ||
2239 | |||
2240 | /* write NAK - inform reads are complete */ | ||
2241 | status = cx231xx_gpio_i2c_write_nak(dev); | ||
2242 | |||
2243 | /* write end */ | ||
2244 | status = cx231xx_gpio_i2c_end(dev); | ||
2245 | |||
2246 | /* release the lock */ | ||
2247 | mutex_unlock(&dev->gpio_i2c_lock); | ||
2248 | |||
2249 | return status; | ||
2250 | } | ||
2251 | |||
2252 | |||
2253 | /* cx231xx_gpio_i2c_write | ||
2254 | * Function to write data to gpio based I2C interface | ||
2255 | */ | ||
2256 | int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len) | ||
2257 | { | ||
2258 | int status = 0; | ||
2259 | int i=0; | ||
2260 | |||
2261 | /* get the lock */ | ||
2262 | mutex_lock(&dev->gpio_i2c_lock); | ||
2263 | |||
2264 | /* start */ | ||
2265 | status = cx231xx_gpio_i2c_start(dev); | ||
2266 | |||
2267 | /* write dev_addr */ | ||
2268 | status = cx231xx_gpio_i2c_write_byte(dev, dev_addr << 1); | ||
2269 | |||
2270 | /* read Ack */ | ||
2271 | status = cx231xx_gpio_i2c_read_ack(dev); | ||
2272 | |||
2273 | for(i = 0; i < len; i++ ) { | ||
2274 | /* Write data */ | ||
2275 | status = cx231xx_gpio_i2c_write_byte(dev, buf[i]); | ||
2276 | |||
2277 | /* read Ack */ | ||
2278 | status = cx231xx_gpio_i2c_read_ack(dev); | ||
2279 | } | ||
2280 | |||
2281 | /* write End */ | ||
2282 | status = cx231xx_gpio_i2c_end(dev); | ||
2283 | |||
2284 | /* release the lock */ | ||
2285 | mutex_unlock(&dev->gpio_i2c_lock); | ||
2286 | |||
2287 | return 0; | ||
2288 | } | ||
2289 | |||
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c new file mode 100644 index 000000000000..c567e5a9eec8 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-cards.c | |||
@@ -0,0 +1,935 @@ | |||
1 | /* | ||
2 | cx231xx-cards.c - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on em28xx driver | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <linux/usb.h> | ||
27 | #include <media/tuner.h> | ||
28 | #include <media/tveeprom.h> | ||
29 | #include <media/v4l2-common.h> | ||
30 | #include <media/v4l2-chip-ident.h> | ||
31 | |||
32 | #include <media/cx25840.h> | ||
33 | #include "xc5000.h" | ||
34 | |||
35 | #include "cx231xx.h" | ||
36 | |||
37 | static int tuner = -1; | ||
38 | module_param(tuner, int, 0444); | ||
39 | MODULE_PARM_DESC(tuner, "tuner type"); | ||
40 | |||
41 | static unsigned int disable_ir; | ||
42 | module_param(disable_ir, int, 0444); | ||
43 | MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); | ||
44 | |||
45 | /* Bitmask marking allocated devices from 0 to CX231XX_MAXBOARDS */ | ||
46 | static unsigned long cx231xx_devused; | ||
47 | |||
48 | /* | ||
49 | * Reset sequences for analog/digital modes | ||
50 | */ | ||
51 | |||
52 | static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = { | ||
53 | { 0x03, 0x01, 10 }, | ||
54 | { 0x03, 0x00, 30 }, | ||
55 | { 0x03, 0x01, 10 }, | ||
56 | { -1, -1, -1 }, | ||
57 | }; | ||
58 | |||
59 | |||
60 | |||
61 | /* | ||
62 | * Board definitions | ||
63 | */ | ||
64 | struct cx231xx_board cx231xx_boards[] = { | ||
65 | |||
66 | [CX231XX_BOARD_UNKNOWN] = { | ||
67 | .name = "Unknown CX231xx video grabber", | ||
68 | .tuner_type = TUNER_ABSENT, | ||
69 | .input = { { | ||
70 | .type = CX231XX_VMUX_TELEVISION, | ||
71 | .vmux = CX231XX_VIN_3_1, | ||
72 | .amux = CX231XX_AMUX_VIDEO, | ||
73 | .gpio = 0, | ||
74 | }, { | ||
75 | .type = CX231XX_VMUX_COMPOSITE1, | ||
76 | .vmux = CX231XX_VIN_2_1, | ||
77 | .amux = CX231XX_AMUX_LINE_IN, | ||
78 | .gpio = 0, | ||
79 | }, { | ||
80 | .type = CX231XX_VMUX_SVIDEO, | ||
81 | .vmux = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) | | ||
82 | CX25840_SVIDEO_ON, | ||
83 | .amux = CX231XX_AMUX_LINE_IN, | ||
84 | .gpio = 0, | ||
85 | } }, | ||
86 | }, | ||
87 | |||
88 | [CX231XX_BOARD_CNXT_RDE_250] = { | ||
89 | .name = "Conexant Hybrid TV - RDE250", | ||
90 | .valid = CX231XX_BOARD_VALIDATED, | ||
91 | .tuner_type = TUNER_XC5000, | ||
92 | .tuner_addr = 0x61, | ||
93 | .tuner_gpio = RDE250_XCV_TUNER, | ||
94 | .tuner_sif_gpio = 0x05, | ||
95 | .tuner_scl_gpio = 0x1a, | ||
96 | .tuner_sda_gpio = 0x1b, | ||
97 | .decoder = CX231XX_AVDECODER, | ||
98 | .demod_xfer_mode = 0, | ||
99 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
100 | .agc_analog_digital_select_gpio = 0x0c, | ||
101 | .gpio_pin_status_mask = 0x4001000, | ||
102 | .tuner_i2c_master = 1, | ||
103 | .demod_i2c_master = 2, | ||
104 | .has_dvb = 1, | ||
105 | .demod_addr = 0x02, | ||
106 | .norm = V4L2_STD_PAL, | ||
107 | |||
108 | .input = { { | ||
109 | .type = CX231XX_VMUX_TELEVISION, | ||
110 | .vmux = CX231XX_VIN_3_1, | ||
111 | .amux = CX231XX_AMUX_VIDEO, | ||
112 | .gpio = 0, | ||
113 | }, { | ||
114 | .type = CX231XX_VMUX_COMPOSITE1, | ||
115 | .vmux = CX231XX_VIN_2_1, | ||
116 | .amux = CX231XX_AMUX_LINE_IN, | ||
117 | .gpio = 0, | ||
118 | }, { | ||
119 | .type = CX231XX_VMUX_SVIDEO, | ||
120 | .vmux = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) | | ||
121 | CX25840_SVIDEO_ON, | ||
122 | .amux = CX231XX_AMUX_LINE_IN, | ||
123 | .gpio = 0, | ||
124 | } }, | ||
125 | }, | ||
126 | |||
127 | [CX231XX_BOARD_CNXT_RDU_250] = { | ||
128 | .name = "Conexant Hybrid TV - RDU250", | ||
129 | .valid = CX231XX_BOARD_VALIDATED, | ||
130 | .tuner_type = TUNER_XC5000, | ||
131 | .tuner_addr = 0x61, | ||
132 | .tuner_gpio = RDE250_XCV_TUNER, | ||
133 | .tuner_sif_gpio = 0x05, | ||
134 | .tuner_scl_gpio = 0x1a, | ||
135 | .tuner_sda_gpio = 0x1b, | ||
136 | .decoder = CX231XX_AVDECODER, | ||
137 | .demod_xfer_mode = 0, | ||
138 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
139 | .agc_analog_digital_select_gpio = 0x0c, | ||
140 | .gpio_pin_status_mask = 0x4001000, | ||
141 | .tuner_i2c_master = 1, | ||
142 | .demod_i2c_master = 2, | ||
143 | .has_dvb = 1, | ||
144 | .demod_addr = 0x32, | ||
145 | .norm = V4L2_STD_NTSC, | ||
146 | |||
147 | .input = { { | ||
148 | .type = CX231XX_VMUX_TELEVISION, | ||
149 | .vmux = CX231XX_VIN_3_1, | ||
150 | .amux = CX231XX_AMUX_VIDEO, | ||
151 | .gpio = 0, | ||
152 | }, { | ||
153 | .type = CX231XX_VMUX_COMPOSITE1, | ||
154 | .vmux = CX231XX_VIN_2_1, | ||
155 | .amux = CX231XX_AMUX_LINE_IN, | ||
156 | .gpio = 0, | ||
157 | }, { | ||
158 | .type = CX231XX_VMUX_SVIDEO, | ||
159 | .vmux = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) | | ||
160 | CX25840_SVIDEO_ON, | ||
161 | .amux = CX231XX_AMUX_LINE_IN, | ||
162 | .gpio = 0, | ||
163 | } }, | ||
164 | }, | ||
165 | }; | ||
166 | const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); | ||
167 | |||
168 | /* table of devices that work with this driver */ | ||
169 | struct usb_device_id cx231xx_id_table [] = { | ||
170 | { USB_DEVICE(0x0572, 0x58A0), | ||
171 | .driver_info = CX231XX_BOARD_UNKNOWN }, | ||
172 | { USB_DEVICE(0x0572, 0x58A2), | ||
173 | .driver_info = CX231XX_BOARD_CNXT_RDE_250 }, | ||
174 | { USB_DEVICE(0x0572, 0x5A3C), | ||
175 | .driver_info = CX231XX_BOARD_CNXT_RDU_250 }, | ||
176 | { }, | ||
177 | }; | ||
178 | MODULE_DEVICE_TABLE(usb, cx231xx_id_table); | ||
179 | |||
180 | /* cx231xx_tuner_callback | ||
181 | * will be used to reset XC5000 tuner using GPIO pin | ||
182 | */ | ||
183 | |||
184 | int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) | ||
185 | { | ||
186 | int rc = 0; | ||
187 | struct cx231xx *dev = ptr; | ||
188 | |||
189 | if (dev->tuner_type == TUNER_XC5000) { | ||
190 | if (command == XC5000_TUNER_RESET) { | ||
191 | cx231xx_info("Tuner Call back : RESET : command %d : tuner type %d \n", | ||
192 | command, dev->tuner_type); | ||
193 | |||
194 | cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); | ||
195 | msleep(10); | ||
196 | cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,0); | ||
197 | msleep(330); | ||
198 | cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); | ||
199 | msleep(10); | ||
200 | } | ||
201 | } | ||
202 | return rc; | ||
203 | } | ||
204 | EXPORT_SYMBOL_GPL(cx231xx_tuner_callback); | ||
205 | |||
206 | static void inline cx231xx_set_model(struct cx231xx *dev) | ||
207 | { | ||
208 | memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board)); | ||
209 | } | ||
210 | |||
211 | /* Since cx231xx_pre_card_setup() requires a proper dev->model, | ||
212 | * this won't work for boards with generic PCI IDs | ||
213 | */ | ||
214 | void cx231xx_pre_card_setup(struct cx231xx *dev) | ||
215 | { | ||
216 | |||
217 | cx231xx_set_model(dev); | ||
218 | |||
219 | cx231xx_info("Identified as %s (card=%d)\n", | ||
220 | dev->board.name, dev->model); | ||
221 | |||
222 | /* Do card specific if any */ | ||
223 | switch (dev->model) { | ||
224 | case CX231XX_BOARD_CNXT_RDE_250: | ||
225 | /* do card specific GPIO settings if required */ | ||
226 | cx231xx_info("Precard: Board is Conexnat RDE 250\n"); | ||
227 | /* set the direction for GPIO pins */ | ||
228 | cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit,1); | ||
229 | cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); | ||
230 | cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio,1); | ||
231 | break; | ||
232 | case CX231XX_BOARD_CNXT_RDU_250: | ||
233 | /* do card specific GPIO settings if required */ | ||
234 | cx231xx_info("Precard: Board is Conexnat RDU 250\n"); | ||
235 | /* set the direction for GPIO pins */ | ||
236 | cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit,1); | ||
237 | cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); | ||
238 | cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio,1); | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | /* request some modules if any required */ | ||
243 | |||
244 | /* reset the Tuner */ | ||
245 | cx231xx_gpio_set(dev, dev->board.tuner_gpio); | ||
246 | |||
247 | /* set the mode to Analog mode initially */ | ||
248 | cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); | ||
249 | |||
250 | /* Unlock device */ | ||
251 | /* cx231xx_set_mode(dev, CX231XX_SUSPEND); */ | ||
252 | |||
253 | } | ||
254 | |||
255 | #if 0 | ||
256 | |||
257 | static void cx231xx_config_tuner(struct cx231xx *dev) | ||
258 | { | ||
259 | struct tuner_setup tun_setup; | ||
260 | struct v4l2_frequency f; | ||
261 | |||
262 | if (dev->tuner_type == TUNER_ABSENT) | ||
263 | return; | ||
264 | |||
265 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
266 | tun_setup.type = dev->tuner_type; | ||
267 | tun_setup.addr = dev->tuner_addr; | ||
268 | tun_setup.tuner_callback = cx231xx_tuner_callback; | ||
269 | |||
270 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_TYPE_ADDR, &tun_setup); | ||
271 | #if 0 | ||
272 | if (tun_setup.type == TUNER_XC5000) { | ||
273 | static struct xc2028_ctrl ctrl = { | ||
274 | .fname = XC5000_DEFAULT_FIRMWARE, | ||
275 | .max_len = 64, | ||
276 | .demod = 0; | ||
277 | }; | ||
278 | struct v4l2_priv_tun_config cfg = { | ||
279 | .tuner = dev->tuner_type, | ||
280 | .priv = &ctrl, | ||
281 | }; | ||
282 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_CONFIG, &cfg); | ||
283 | } | ||
284 | #endif | ||
285 | |||
286 | /* configure tuner */ | ||
287 | f.tuner = 0; | ||
288 | f.type = V4L2_TUNER_ANALOG_TV; | ||
289 | f.frequency = 9076; /* just a magic number */ | ||
290 | dev->ctl_freq = f.frequency; | ||
291 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); | ||
292 | } | ||
293 | |||
294 | #endif | ||
295 | |||
296 | /* ----------------------------------------------------------------------- */ | ||
297 | void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) | ||
298 | { | ||
299 | if (disable_ir) { | ||
300 | ir->get_key = NULL; | ||
301 | return ; | ||
302 | } | ||
303 | |||
304 | /* detect & configure */ | ||
305 | switch (dev->model) { | ||
306 | |||
307 | case CX231XX_BOARD_CNXT_RDE_250: | ||
308 | break; | ||
309 | case CX231XX_BOARD_CNXT_RDU_250: | ||
310 | break; | ||
311 | default: | ||
312 | break; | ||
313 | } | ||
314 | } | ||
315 | |||
316 | void cx231xx_card_setup(struct cx231xx *dev) | ||
317 | { | ||
318 | cx231xx_set_model(dev); | ||
319 | |||
320 | dev->tuner_type = cx231xx_boards[dev->model].tuner_type; | ||
321 | if (cx231xx_boards[dev->model].tuner_addr) | ||
322 | dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr; | ||
323 | |||
324 | cx231xx_info(": tuner type %d, tuner address %d \n", | ||
325 | dev->tuner_type, dev->tuner_addr); | ||
326 | |||
327 | /* Do card specific if any */ | ||
328 | switch (dev->model) { | ||
329 | case CX231XX_BOARD_CNXT_RDE_250: | ||
330 | /* do card specific GPIO settings if required */ | ||
331 | cx231xx_info("Board is Conexnat RDE 250\n"); | ||
332 | break; | ||
333 | case CX231XX_BOARD_CNXT_RDU_250: | ||
334 | /* do card specific GPIO settings if required */ | ||
335 | cx231xx_info("Board is Conexnat RDU 250\n"); | ||
336 | break; | ||
337 | } | ||
338 | |||
339 | if (dev->board.valid == CX231XX_BOARD_NOT_VALIDATED) { | ||
340 | cx231xx_errdev("\n\n"); | ||
341 | cx231xx_errdev("The support for this board weren't " | ||
342 | "valid yet.\n"); | ||
343 | cx231xx_errdev("Please send a report of having this working\n"); | ||
344 | cx231xx_errdev("not to V4L mailing list (and/or to other " | ||
345 | "addresses)\n\n"); | ||
346 | } | ||
347 | |||
348 | |||
349 | /* request some modules */ | ||
350 | if (dev->board.decoder == CX231XX_AVDECODER) { | ||
351 | cx231xx_info(": Requesting cx25840 module\n"); | ||
352 | request_module("cx25840"); | ||
353 | } | ||
354 | #if 0 | ||
355 | if (dev->board.tuner_type != TUNER_ABSENT) { | ||
356 | cx231xx_info(": Requesting Tuner module\n"); | ||
357 | request_module("tuner"); | ||
358 | } | ||
359 | |||
360 | cx231xx_config_tuner(dev); | ||
361 | |||
362 | /* TBD IR will be added later */ | ||
363 | cx231xx_ir_init(dev); | ||
364 | #endif | ||
365 | } | ||
366 | |||
367 | |||
368 | |||
369 | /* | ||
370 | * cx231xx_config() | ||
371 | * inits registers with sane defaults | ||
372 | */ | ||
373 | int cx231xx_config(struct cx231xx *dev) | ||
374 | { | ||
375 | /* TBD need to add cx231xx specific code */ | ||
376 | dev->mute = 1; /* maybe not the right place... */ | ||
377 | dev->volume = 0x1f; | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | /* | ||
383 | * cx231xx_config_i2c() | ||
384 | * configure i2c attached devices | ||
385 | */ | ||
386 | void cx231xx_config_i2c(struct cx231xx *dev) | ||
387 | { | ||
388 | struct v4l2_routing route; | ||
389 | |||
390 | route.input = INPUT(dev->video_input)->vmux; | ||
391 | route.output = 0; | ||
392 | |||
393 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_STREAMON, NULL); | ||
394 | } | ||
395 | |||
396 | /* | ||
397 | * cx231xx_realease_resources() | ||
398 | * unregisters the v4l2,i2c and usb devices | ||
399 | * called when the device gets disconected or at module unload | ||
400 | */ | ||
401 | void cx231xx_release_resources(struct cx231xx *dev) | ||
402 | { | ||
403 | |||
404 | #if 0 /* TBD IR related */ | ||
405 | if (dev->ir) | ||
406 | cx231xx_ir_fini(dev); | ||
407 | #endif | ||
408 | |||
409 | cx231xx_release_analog_resources(dev); | ||
410 | |||
411 | cx231xx_remove_from_devlist(dev); | ||
412 | |||
413 | cx231xx_dev_uninit(dev); | ||
414 | |||
415 | usb_put_dev(dev->udev); | ||
416 | |||
417 | /* Mark device as unused */ | ||
418 | cx231xx_devused &= ~(1<<dev->devno); | ||
419 | } | ||
420 | |||
421 | |||
422 | /* | ||
423 | * cx231xx_init_dev() | ||
424 | * allocates and inits the device structs, registers i2c bus and v4l device | ||
425 | */ | ||
426 | static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, | ||
427 | int minor) | ||
428 | { | ||
429 | struct cx231xx *dev = *devhandle; | ||
430 | int retval = -ENOMEM; | ||
431 | int errCode; | ||
432 | unsigned int maxh, maxw; | ||
433 | |||
434 | dev->udev = udev; | ||
435 | mutex_init(&dev->lock); | ||
436 | mutex_init(&dev->ctrl_urb_lock); | ||
437 | mutex_init(&dev->gpio_i2c_lock); | ||
438 | |||
439 | spin_lock_init(&dev->video_mode.slock); | ||
440 | spin_lock_init(&dev->vbi_mode.slock); | ||
441 | spin_lock_init(&dev->sliced_cc_mode.slock); | ||
442 | |||
443 | init_waitqueue_head(&dev->open); | ||
444 | init_waitqueue_head(&dev->wait_frame); | ||
445 | init_waitqueue_head(&dev->wait_stream); | ||
446 | |||
447 | dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg; | ||
448 | dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg; | ||
449 | dev->cx231xx_send_usb_command = cx231xx_send_usb_command; | ||
450 | dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read; | ||
451 | dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write; | ||
452 | |||
453 | /* Query cx231xx to find what pcb config it is related to */ | ||
454 | initialize_cx231xx(dev); | ||
455 | |||
456 | /* Cx231xx pre card setup */ | ||
457 | cx231xx_pre_card_setup(dev); | ||
458 | |||
459 | errCode = cx231xx_config(dev); | ||
460 | if (errCode) { | ||
461 | cx231xx_errdev("error configuring device\n"); | ||
462 | return -ENOMEM; | ||
463 | } | ||
464 | |||
465 | /* set default norm */ | ||
466 | dev->norm = dev->board.norm; | ||
467 | |||
468 | /* register i2c bus */ | ||
469 | errCode = cx231xx_dev_init(dev); | ||
470 | if (errCode < 0) { | ||
471 | cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n", | ||
472 | __func__, errCode); | ||
473 | return errCode; | ||
474 | } | ||
475 | |||
476 | /* Do board specific init */ | ||
477 | cx231xx_card_setup(dev); | ||
478 | |||
479 | /* configure the device */ | ||
480 | cx231xx_config_i2c(dev); | ||
481 | |||
482 | maxw = norm_maxw(dev); | ||
483 | maxh = norm_maxh(dev); | ||
484 | |||
485 | /* set default image size */ | ||
486 | dev->width = maxw; | ||
487 | dev->height = maxh; | ||
488 | dev->interlaced = 0; | ||
489 | dev->hscale = 0; | ||
490 | dev->vscale = 0; | ||
491 | dev->video_input = 0; | ||
492 | |||
493 | errCode = cx231xx_config(dev); | ||
494 | if (errCode < 0) { | ||
495 | cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n", | ||
496 | __func__, errCode); | ||
497 | return errCode; | ||
498 | } | ||
499 | |||
500 | /* init video dma queues */ | ||
501 | INIT_LIST_HEAD(&dev->video_mode.vidq.active); | ||
502 | INIT_LIST_HEAD(&dev->video_mode.vidq.queued); | ||
503 | |||
504 | /* init vbi dma queues */ | ||
505 | INIT_LIST_HEAD(&dev->vbi_mode.vidq.active); | ||
506 | INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued); | ||
507 | |||
508 | /* Reset other chips required if they are tied up with GPIO pins */ | ||
509 | |||
510 | cx231xx_add_into_devlist(dev); | ||
511 | |||
512 | retval = cx231xx_register_analog_devices(dev); | ||
513 | if (retval < 0) { | ||
514 | cx231xx_release_resources(dev); | ||
515 | goto fail_reg_devices; | ||
516 | } | ||
517 | |||
518 | cx231xx_init_extension(dev); | ||
519 | |||
520 | return 0; | ||
521 | |||
522 | fail_reg_devices: | ||
523 | mutex_unlock(&dev->lock); | ||
524 | return retval; | ||
525 | } | ||
526 | |||
527 | #if defined(CONFIG_MODULES) && defined(MODULE) | ||
528 | static void request_module_async(struct work_struct *work) | ||
529 | { | ||
530 | struct cx231xx *dev = container_of(work, | ||
531 | struct cx231xx, request_module_wk); | ||
532 | |||
533 | |||
534 | if (dev->has_alsa_audio) | ||
535 | request_module("cx231xx-alsa"); | ||
536 | |||
537 | if (dev->board.has_dvb) | ||
538 | request_module("cx231xx-dvb"); | ||
539 | |||
540 | } | ||
541 | |||
542 | static void request_modules(struct cx231xx *dev) | ||
543 | { | ||
544 | INIT_WORK(&dev->request_module_wk, request_module_async); | ||
545 | schedule_work(&dev->request_module_wk); | ||
546 | } | ||
547 | #else | ||
548 | #define request_modules(dev) | ||
549 | #endif /* CONFIG_MODULES */ | ||
550 | |||
551 | |||
552 | |||
553 | /* | ||
554 | * cx231xx_usb_probe() | ||
555 | * checks for supported devices | ||
556 | */ | ||
557 | static int cx231xx_usb_probe(struct usb_interface *interface, | ||
558 | const struct usb_device_id *id) | ||
559 | { | ||
560 | struct usb_device *udev; | ||
561 | struct usb_interface *uif; | ||
562 | struct cx231xx *dev = NULL; | ||
563 | int retval = -ENODEV; | ||
564 | int nr, ifnum; | ||
565 | int i, isoc_pipe = 0; | ||
566 | char *speed; | ||
567 | char descr[255] = ""; | ||
568 | struct usb_interface *lif = NULL; | ||
569 | int skip_interface = 0; | ||
570 | struct usb_interface_assoc_descriptor *assoc_desc; | ||
571 | |||
572 | udev = usb_get_dev(interface_to_usbdev(interface)); | ||
573 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; | ||
574 | |||
575 | cx231xx_info(": Interface Number %d\n", ifnum); | ||
576 | |||
577 | /* Interface number 0 - IR interface */ | ||
578 | if(ifnum == 0 ){ | ||
579 | /* Check to see next free device and mark as used */ | ||
580 | nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); | ||
581 | cx231xx_devused |= 1<<nr; | ||
582 | |||
583 | if (nr >= CX231XX_MAXBOARDS) { | ||
584 | cx231xx_info(": Supports only %i cx231xx boards.\n", | ||
585 | CX231XX_MAXBOARDS); | ||
586 | cx231xx_devused &= ~(1<<nr); | ||
587 | return -ENOMEM; | ||
588 | } | ||
589 | |||
590 | /* allocate memory for our device state and initialize it */ | ||
591 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
592 | if (dev == NULL) { | ||
593 | cx231xx_err(DRIVER_NAME ": out of memory!\n"); | ||
594 | cx231xx_devused &= ~(1<<nr); | ||
595 | return -ENOMEM; | ||
596 | } | ||
597 | |||
598 | snprintf(dev->name, 29, "cx231xx #%d", nr); | ||
599 | dev->devno = nr; | ||
600 | dev->model = id->driver_info; | ||
601 | dev->video_mode.alt = -1; | ||
602 | dev->interface_count++; | ||
603 | |||
604 | /* reset gpio dir and value */ | ||
605 | dev->gpio_dir = 0; | ||
606 | dev->gpio_val = 0; | ||
607 | dev->xc_fw_load_done = 0; | ||
608 | dev->has_alsa_audio = 1; | ||
609 | dev->power_mode = -1; | ||
610 | |||
611 | dev->vbi_or_sliced_cc_mode = 0; /* 0 - vbi ; 1 -sliced cc mode */ | ||
612 | |||
613 | /* get maximum no.of IAD interfaces */ | ||
614 | assoc_desc = udev->actconfig->intf_assoc[0]; | ||
615 | dev->max_iad_interface_count = assoc_desc->bInterfaceCount; | ||
616 | cx231xx_info(": Found IAD interface count %d\n", dev->max_iad_interface_count); | ||
617 | |||
618 | /* init CIR module TBD */ | ||
619 | |||
620 | /* store the current interface */ | ||
621 | lif = interface; | ||
622 | |||
623 | } | ||
624 | else if(ifnum == 1 ){ | ||
625 | |||
626 | /* Get dev structure first */ | ||
627 | dev = usb_get_intfdata(udev->actconfig->interface[0]); | ||
628 | if(dev == NULL){ | ||
629 | cx231xx_err(DRIVER_NAME ": out of first interface!\n"); | ||
630 | return -ENODEV; | ||
631 | } | ||
632 | |||
633 | /* store the interface 0 back */ | ||
634 | lif = udev->actconfig->interface[0]; | ||
635 | |||
636 | /* increment interface count */ | ||
637 | dev->interface_count++; | ||
638 | |||
639 | /* get device number */ | ||
640 | nr = dev->devno; | ||
641 | |||
642 | assoc_desc = udev->actconfig->intf_assoc[0]; | ||
643 | if(assoc_desc->bFirstInterface == ifnum){ | ||
644 | cx231xx_info(": Found IAD interface match: AV Descriptor Start!! \n"); | ||
645 | } else { | ||
646 | cx231xx_err(DRIVER_NAME " Not found matching interface\n"); | ||
647 | return -ENODEV; | ||
648 | } | ||
649 | |||
650 | } | ||
651 | else if(ifnum >= 2) { | ||
652 | /* Get dev structure first */ | ||
653 | dev = usb_get_intfdata(udev->actconfig->interface[0]); | ||
654 | if(dev == NULL){ | ||
655 | cx231xx_err(DRIVER_NAME ": out of first interface!\n"); | ||
656 | return -ENODEV; | ||
657 | } | ||
658 | |||
659 | /* store the interface 0 back */ | ||
660 | lif = udev->actconfig->interface[0]; | ||
661 | |||
662 | /* increment interface count */ | ||
663 | dev->interface_count++; | ||
664 | |||
665 | /* get device number */ | ||
666 | nr = dev->devno; | ||
667 | |||
668 | /* set skip interface */ | ||
669 | if((dev->interface_count -1) != dev->max_iad_interface_count ) | ||
670 | skip_interface = 1; /* set skipping */ | ||
671 | else{ | ||
672 | cx231xx_info(": Found IAD interface number match with AV Device number!! \n"); | ||
673 | } | ||
674 | } | ||
675 | |||
676 | switch (udev->speed) { | ||
677 | case USB_SPEED_LOW: | ||
678 | speed = "1.5"; | ||
679 | break; | ||
680 | case USB_SPEED_UNKNOWN: | ||
681 | case USB_SPEED_FULL: | ||
682 | speed = "12"; | ||
683 | break; | ||
684 | case USB_SPEED_HIGH: | ||
685 | speed = "480"; | ||
686 | break; | ||
687 | default: | ||
688 | speed = "unknown"; | ||
689 | } | ||
690 | |||
691 | if (udev->manufacturer) | ||
692 | strlcpy(descr, udev->manufacturer, sizeof(descr)); | ||
693 | |||
694 | if (udev->product) { | ||
695 | if (*descr) | ||
696 | strlcat(descr, " ", sizeof(descr)); | ||
697 | strlcat(descr, udev->product, sizeof(descr)); | ||
698 | } | ||
699 | if (*descr) | ||
700 | strlcat(descr, " ", sizeof(descr)); | ||
701 | |||
702 | cx231xx_info("New device %s@ %s Mbps " | ||
703 | "(%04x:%04x, interface %d, class %d)\n", | ||
704 | descr, | ||
705 | speed, | ||
706 | le16_to_cpu(udev->descriptor.idVendor), | ||
707 | le16_to_cpu(udev->descriptor.idProduct), | ||
708 | ifnum, | ||
709 | interface->altsetting->desc.bInterfaceNumber); | ||
710 | |||
711 | /* AV device initialization */ | ||
712 | if((dev->interface_count -1) == dev->max_iad_interface_count ) { | ||
713 | cx231xx_info(" Calling init_dev\n"); | ||
714 | /* allocate device struct */ | ||
715 | retval = cx231xx_init_dev(&dev, udev, nr); | ||
716 | if (retval) { | ||
717 | cx231xx_devused &= ~(1<<dev->devno); | ||
718 | kfree(dev); | ||
719 | |||
720 | return retval; | ||
721 | } | ||
722 | |||
723 | /* compute alternate max packet sizes for video */ | ||
724 | uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1]; | ||
725 | |||
726 | dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); | ||
727 | |||
728 | dev->video_mode.num_alt = uif->num_altsetting; | ||
729 | cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->video_mode.end_point_addr, | ||
730 | dev->video_mode.num_alt); | ||
731 | dev->video_mode.alt_max_pkt_size = kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL); | ||
732 | |||
733 | if (dev->video_mode.alt_max_pkt_size == NULL) { | ||
734 | cx231xx_errdev("out of memory!\n"); | ||
735 | cx231xx_devused &= ~(1<<nr); | ||
736 | kfree(dev); | ||
737 | return -ENOMEM; | ||
738 | } | ||
739 | |||
740 | for (i = 0; i < dev->video_mode.num_alt ; i++) { | ||
741 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. | ||
742 | wMaxPacketSize); | ||
743 | dev->video_mode.alt_max_pkt_size[i] = | ||
744 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
745 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
746 | dev->video_mode.alt_max_pkt_size[i]); | ||
747 | } | ||
748 | |||
749 | |||
750 | /* compute alternate max packet sizes for vbi */ | ||
751 | uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index+1]; | ||
752 | |||
753 | dev->vbi_mode.end_point_addr = | ||
754 | le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); | ||
755 | |||
756 | dev->vbi_mode.num_alt = uif->num_altsetting; | ||
757 | cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->vbi_mode.end_point_addr, | ||
758 | dev->vbi_mode.num_alt); | ||
759 | dev->vbi_mode.alt_max_pkt_size = kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL); | ||
760 | |||
761 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { | ||
762 | cx231xx_errdev("out of memory!\n"); | ||
763 | cx231xx_devused &= ~(1<<nr); | ||
764 | kfree(dev); | ||
765 | return -ENOMEM; | ||
766 | } | ||
767 | |||
768 | for (i = 0; i < dev->vbi_mode.num_alt ; i++) { | ||
769 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. | ||
770 | wMaxPacketSize); | ||
771 | dev->vbi_mode.alt_max_pkt_size[i] = | ||
772 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
773 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
774 | dev->vbi_mode.alt_max_pkt_size[i]); | ||
775 | } | ||
776 | |||
777 | /* compute alternate max packet sizes for sliced CC */ | ||
778 | uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index+1]; | ||
779 | |||
780 | dev->sliced_cc_mode.end_point_addr = | ||
781 | le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); | ||
782 | |||
783 | dev->sliced_cc_mode.num_alt = uif->num_altsetting; | ||
784 | cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->sliced_cc_mode.end_point_addr, | ||
785 | dev->sliced_cc_mode.num_alt); | ||
786 | dev->sliced_cc_mode.alt_max_pkt_size = kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL); | ||
787 | |||
788 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { | ||
789 | cx231xx_errdev("out of memory!\n"); | ||
790 | cx231xx_devused &= ~(1<<nr); | ||
791 | kfree(dev); | ||
792 | return -ENOMEM; | ||
793 | } | ||
794 | |||
795 | for (i = 0; i < dev->sliced_cc_mode.num_alt ; i++) { | ||
796 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. | ||
797 | wMaxPacketSize); | ||
798 | dev->sliced_cc_mode.alt_max_pkt_size[i] = | ||
799 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
800 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
801 | dev->sliced_cc_mode.alt_max_pkt_size[i]); | ||
802 | } | ||
803 | |||
804 | if(dev->current_pcb_config.ts1_source != 0xff ) { | ||
805 | |||
806 | /* compute alternate max packet sizes for TS1 */ | ||
807 | uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index+1]; | ||
808 | |||
809 | dev->ts1_mode.end_point_addr = | ||
810 | le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); | ||
811 | |||
812 | dev->ts1_mode.num_alt = uif->num_altsetting; | ||
813 | cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->ts1_mode.end_point_addr, | ||
814 | dev->ts1_mode.num_alt); | ||
815 | dev->ts1_mode.alt_max_pkt_size = kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL); | ||
816 | |||
817 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { | ||
818 | cx231xx_errdev("out of memory!\n"); | ||
819 | cx231xx_devused &= ~(1<<nr); | ||
820 | kfree(dev); | ||
821 | return -ENOMEM; | ||
822 | } | ||
823 | |||
824 | for (i = 0; i < dev->ts1_mode.num_alt ; i++) { | ||
825 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. | ||
826 | wMaxPacketSize); | ||
827 | dev->ts1_mode.alt_max_pkt_size[i] = | ||
828 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
829 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
830 | dev->ts1_mode.alt_max_pkt_size[i]); | ||
831 | } | ||
832 | } | ||
833 | |||
834 | } | ||
835 | |||
836 | /* save our data pointer in this interface device */ | ||
837 | usb_set_intfdata(lif, dev); | ||
838 | |||
839 | /* load other modules required */ | ||
840 | if((dev->interface_count -1) == dev->max_iad_interface_count ) | ||
841 | { | ||
842 | cx231xx_info("Calling request modules\n"); | ||
843 | request_modules(dev); | ||
844 | } | ||
845 | |||
846 | if(skip_interface ) { | ||
847 | cx231xx_info("Skipping the interface\n"); | ||
848 | return -ENODEV; | ||
849 | } | ||
850 | |||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | * cx231xx_usb_disconnect() | ||
856 | * called when the device gets diconencted | ||
857 | * video device will be unregistered on v4l2_close in case it is still open | ||
858 | */ | ||
859 | static void cx231xx_usb_disconnect(struct usb_interface *interface) | ||
860 | { | ||
861 | struct cx231xx *dev; | ||
862 | |||
863 | dev = usb_get_intfdata(interface); | ||
864 | usb_set_intfdata(interface, NULL); | ||
865 | |||
866 | if (!dev) | ||
867 | return; | ||
868 | |||
869 | /* wait until all current v4l2 io is finished then deallocate | ||
870 | resources */ | ||
871 | mutex_lock(&dev->lock); | ||
872 | |||
873 | wake_up_interruptible_all(&dev->open); | ||
874 | |||
875 | if (dev->users) { | ||
876 | cx231xx_warn | ||
877 | ("device /dev/video%d is open! Deregistration and memory " | ||
878 | "deallocation are deferred on close.\n", | ||
879 | dev->vdev->num); | ||
880 | |||
881 | dev->state |= DEV_MISCONFIGURED; | ||
882 | cx231xx_uninit_isoc(dev); | ||
883 | dev->state |= DEV_DISCONNECTED; | ||
884 | wake_up_interruptible(&dev->wait_frame); | ||
885 | wake_up_interruptible(&dev->wait_stream); | ||
886 | } else { | ||
887 | dev->state |= DEV_DISCONNECTED; | ||
888 | cx231xx_release_resources(dev); | ||
889 | } | ||
890 | |||
891 | cx231xx_close_extension(dev); | ||
892 | |||
893 | mutex_unlock(&dev->lock); | ||
894 | |||
895 | if (!dev->users) { | ||
896 | kfree(dev->video_mode.alt_max_pkt_size); | ||
897 | kfree(dev->vbi_mode.alt_max_pkt_size); | ||
898 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | ||
899 | kfree(dev->ts1_mode.alt_max_pkt_size); | ||
900 | kfree(dev); | ||
901 | } | ||
902 | } | ||
903 | |||
904 | static struct usb_driver cx231xx_usb_driver = { | ||
905 | .name = "cx231xx", | ||
906 | .probe = cx231xx_usb_probe, | ||
907 | .disconnect = cx231xx_usb_disconnect, | ||
908 | .id_table = cx231xx_id_table, | ||
909 | }; | ||
910 | |||
911 | static int __init cx231xx_module_init(void) | ||
912 | { | ||
913 | int result; | ||
914 | |||
915 | printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n", | ||
916 | (CX231XX_VERSION_CODE >> 16) & 0xff, | ||
917 | (CX231XX_VERSION_CODE >> 8) & 0xff, CX231XX_VERSION_CODE & 0xff); | ||
918 | |||
919 | /* register this driver with the USB subsystem */ | ||
920 | result = usb_register(&cx231xx_usb_driver); | ||
921 | if (result) | ||
922 | cx231xx_err(DRIVER_NAME | ||
923 | " usb_register failed. Error number %d.\n", result); | ||
924 | |||
925 | return result; | ||
926 | } | ||
927 | |||
928 | static void __exit cx231xx_module_exit(void) | ||
929 | { | ||
930 | /* deregister this driver with the USB subsystem */ | ||
931 | usb_deregister(&cx231xx_usb_driver); | ||
932 | } | ||
933 | |||
934 | module_init(cx231xx_module_init); | ||
935 | module_exit(cx231xx_module_exit); | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/drivers/media/video/cx231xx/cx231xx-conf-reg.h new file mode 100644 index 000000000000..5ccf6bdfe579 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-conf-reg.h | |||
@@ -0,0 +1,491 @@ | |||
1 | /* | ||
2 | cx231xx_conf-reg.h - driver for Conexant Cx23100/101/102 USB | ||
3 | video capture devices | ||
4 | |||
5 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | |||
23 | #ifndef _POLARIS_REG_H_ | ||
24 | #define _POLARIS_REG_H_ | ||
25 | |||
26 | #define BOARD_CFG_STAT 0x0 | ||
27 | #define TS_MODE_REG 0x4 | ||
28 | #define TS1_CFG_REG 0x8 | ||
29 | #define TS1_LENGTH_REG 0xc | ||
30 | #define TS2_CFG_REG 0x10 | ||
31 | #define TS2_LENGTH_REG 0x14 | ||
32 | #define EP_MODE_SET 0x18 | ||
33 | #define CIR_PWR_PTN1 0x1c | ||
34 | #define CIR_PWR_PTN2 0x20 | ||
35 | #define CIR_PWR_PTN3 0x24 | ||
36 | #define CIR_PWR_MASK0 0x28 | ||
37 | #define CIR_PWR_MASK1 0x2c | ||
38 | #define CIR_PWR_MASK2 0x30 | ||
39 | #define CIR_GAIN 0x34 | ||
40 | #define CIR_CAR_REG 0x38 | ||
41 | #define CIR_OT_CFG1 0x40 | ||
42 | #define CIR_OT_CFG2 0x44 | ||
43 | #define PWR_CTL_EN 0x74 | ||
44 | |||
45 | /* Polaris Endpoints capture mask for register EP_MODE_SET */ | ||
46 | #define ENABLE_EP1 0x01 /* Bit[0]=1 */ | ||
47 | #define ENABLE_EP2 0x02 /* Bit[1]=1 */ | ||
48 | #define ENABLE_EP3 0x04 /* Bit[2]=1 */ | ||
49 | #define ENABLE_EP4 0x08 /* Bit[3]=1 */ | ||
50 | #define ENABLE_EP5 0x10 /* Bit[4]=1 */ | ||
51 | #define ENABLE_EP6 0x20 /* Bit[5]=1 */ | ||
52 | |||
53 | /* Bit definition for register PWR_CTL_EN */ | ||
54 | #define PWR_MODE_MASK 0x17f | ||
55 | #define PWR_AV_EN 0x08 /* bit3 */ | ||
56 | #define PWR_ISO_EN 0x40 /* bit6 */ | ||
57 | #define PWR_AV_MODE 0x30 /* bit4,5 */ | ||
58 | #define PWR_TUNER_EN 0x04 /* bit2 */ | ||
59 | #define PWR_DEMOD_EN 0x02 /* bit1 */ | ||
60 | #define I2C_DEMOD_EN 0x01 /* bit0 */ | ||
61 | #define PWR_RESETOUT_EN 0x100 /* bit8 */ | ||
62 | |||
63 | typedef enum{ | ||
64 | POLARIS_AVMODE_DEFAULT = 0, | ||
65 | POLARIS_AVMODE_DIGITAL = 0x10, | ||
66 | POLARIS_AVMODE_ANALOGT_TV = 0x20, | ||
67 | POLARIS_AVMODE_ENXTERNAL_AV = 0x30, | ||
68 | |||
69 | }AV_MODE; | ||
70 | |||
71 | /* Colibri Registers */ | ||
72 | |||
73 | #define SINGLE_ENDED 0x0 | ||
74 | #define LOW_IF 0x4 | ||
75 | #define EU_IF 0x9 | ||
76 | #define US_IF 0xa | ||
77 | |||
78 | |||
79 | |||
80 | #define SUP_BLK_TUNE1 0x00 | ||
81 | #define SUP_BLK_TUNE2 0x01 | ||
82 | #define SUP_BLK_TUNE3 0x02 | ||
83 | #define SUP_BLK_XTAL 0x03 | ||
84 | #define SUP_BLK_PLL1 0x04 | ||
85 | #define SUP_BLK_PLL2 0x05 | ||
86 | #define SUP_BLK_PLL3 0x06 | ||
87 | #define SUP_BLK_REF 0x07 | ||
88 | #define SUP_BLK_PWRDN 0x08 | ||
89 | #define SUP_BLK_TESTPAD 0x09 | ||
90 | #define ADC_COM_INT5_STAB_REF 0x0a | ||
91 | #define ADC_COM_QUANT 0x0b | ||
92 | #define ADC_COM_BIAS1 0x0c | ||
93 | #define ADC_COM_BIAS2 0x0d | ||
94 | #define ADC_COM_BIAS3 0x0e | ||
95 | #define TESTBUS_CTRL 0x12 | ||
96 | |||
97 | #define ADC_STATUS_CH1 0x20 | ||
98 | #define ADC_STATUS_CH2 0x40 | ||
99 | #define ADC_STATUS_CH3 0x60 | ||
100 | |||
101 | #define ADC_STATUS2_CH1 0x21 | ||
102 | #define ADC_STATUS2_CH2 0x41 | ||
103 | #define ADC_STATUS2_CH3 0x61 | ||
104 | |||
105 | #define ADC_CAL_ATEST_CH1 0x22 | ||
106 | #define ADC_CAL_ATEST_CH2 0x42 | ||
107 | #define ADC_CAL_ATEST_CH3 0x62 | ||
108 | |||
109 | #define ADC_PWRDN_CLAMP_CH1 0x23 | ||
110 | #define ADC_PWRDN_CLAMP_CH2 0x43 | ||
111 | #define ADC_PWRDN_CLAMP_CH3 0x63 | ||
112 | |||
113 | #define ADC_CTRL_DAC23_CH1 0x24 | ||
114 | #define ADC_CTRL_DAC23_CH2 0x44 | ||
115 | #define ADC_CTRL_DAC23_CH3 0x64 | ||
116 | |||
117 | #define ADC_CTRL_DAC1_CH1 0x25 | ||
118 | #define ADC_CTRL_DAC1_CH2 0x45 | ||
119 | #define ADC_CTRL_DAC1_CH3 0x65 | ||
120 | |||
121 | #define ADC_DCSERVO_DEM_CH1 0x26 | ||
122 | #define ADC_DCSERVO_DEM_CH2 0x46 | ||
123 | #define ADC_DCSERVO_DEM_CH3 0x66 | ||
124 | |||
125 | #define ADC_FB_FRCRST_CH1 0x27 | ||
126 | #define ADC_FB_FRCRST_CH2 0x47 | ||
127 | #define ADC_FB_FRCRST_CH3 0x67 | ||
128 | |||
129 | #define ADC_INPUT_CH1 0x28 | ||
130 | #define ADC_INPUT_CH2 0x48 | ||
131 | #define ADC_INPUT_CH3 0x68 | ||
132 | #define INPUT_SEL_MASK 0x30 /* [5:4] in_sel */ | ||
133 | |||
134 | #define ADC_NTF_PRECLMP_EN_CH1 0x29 | ||
135 | #define ADC_NTF_PRECLMP_EN_CH2 0x49 | ||
136 | #define ADC_NTF_PRECLMP_EN_CH3 0x69 | ||
137 | |||
138 | #define ADC_QGAIN_RES_TRM_CH1 0x2a | ||
139 | #define ADC_QGAIN_RES_TRM_CH2 0x4a | ||
140 | #define ADC_QGAIN_RES_TRM_CH3 0x6a | ||
141 | |||
142 | #define ADC_SOC_PRECLMP_TERM_CH1 0x2b | ||
143 | #define ADC_SOC_PRECLMP_TERM_CH2 0x4b | ||
144 | #define ADC_SOC_PRECLMP_TERM_CH3 0x6b | ||
145 | |||
146 | #define TESTBUS_CTRL_CH1 0x32 | ||
147 | #define TESTBUS_CTRL_CH2 0x52 | ||
148 | #define TESTBUS_CTRL_CH3 0x72 | ||
149 | |||
150 | /****************************************************************************** | ||
151 | * DIF registers * | ||
152 | ******************************************************************************/ | ||
153 | #define DIRECT_IF_REVB_BASE 0x00300 | ||
154 | |||
155 | /*****************************************************************************/ | ||
156 | #define DIF_PLL_FREQ_WORD (DIRECT_IF_REVB_BASE + 0x00000000) /* Reg Size 32 */ | ||
157 | /*****************************************************************************/ | ||
158 | #define FLD_DIF_PLL_LOCK 0x80000000 | ||
159 | /* Reserved [30:29] */ | ||
160 | #define FLD_DIF_PLL_FREE_RUN 0x10000000 | ||
161 | #define FLD_DIF_PLL_FREQ 0x0FFFFFFF | ||
162 | |||
163 | /*****************************************************************************/ | ||
164 | #define DIF_PLL_CTRL (DIRECT_IF_REVB_BASE + 0x00000004) /* Reg Size 32 */ | ||
165 | /*****************************************************************************/ | ||
166 | #define FLD_DIF_KD_PD 0xFF000000 | ||
167 | /* Reserved [23:20] */ | ||
168 | #define FLD_DIF_KDS_PD 0x000F0000 | ||
169 | #define FLD_DIF_KI_PD 0x0000FF00 | ||
170 | /* Reserved [7:4] */ | ||
171 | #define FLD_DIF_KIS_PD 0x0000000F | ||
172 | |||
173 | /*****************************************************************************/ | ||
174 | #define DIF_PLL_CTRL1 (DIRECT_IF_REVB_BASE + 0x00000008) /* Reg Size 32 */ | ||
175 | /*****************************************************************************/ | ||
176 | #define FLD_DIF_KD_FD 0xFF000000 | ||
177 | /* Reserved [23:20] */ | ||
178 | #define FLD_DIF_KDS_FD 0x000F0000 | ||
179 | #define FLD_DIF_KI_FD 0x0000FF00 | ||
180 | #define FLD_DIF_SIG_PROP_SZ 0x000000F0 | ||
181 | #define FLD_DIF_KIS_FD 0x0000000F | ||
182 | |||
183 | /*****************************************************************************/ | ||
184 | #define DIF_PLL_CTRL2 (DIRECT_IF_REVB_BASE + 0x0000000C) /* Reg Size 32 */ | ||
185 | /*****************************************************************************/ | ||
186 | #define FLD_DIF_PLL_AGC_REF 0xFFF00000 | ||
187 | #define FLD_DIF_PLL_AGC_KI 0x000F0000 | ||
188 | /* Reserved [15] */ | ||
189 | #define FLD_DIF_FREQ_LIMIT 0x00007000 | ||
190 | #define FLD_DIF_K_FD 0x00000F00 | ||
191 | #define FLD_DIF_DOWNSMPL_FD 0x000000FF | ||
192 | |||
193 | /*****************************************************************************/ | ||
194 | #define DIF_PLL_CTRL3 (DIRECT_IF_REVB_BASE + 0x00000010) /* Reg Size 32 */ | ||
195 | /*****************************************************************************/ | ||
196 | /* Reserved [31:16] */ | ||
197 | #define FLD_DIF_PLL_AGC_EN 0x00008000 | ||
198 | /* Reserved [14:12] */ | ||
199 | #define FLD_DIF_PLL_MAN_GAIN 0x00000FFF | ||
200 | |||
201 | /*****************************************************************************/ | ||
202 | #define DIF_AGC_IF_REF (DIRECT_IF_REVB_BASE + 0x00000014) /* Reg Size 32 */ | ||
203 | /*****************************************************************************/ | ||
204 | #define FLD_DIF_K_AGC_RF 0xF0000000 | ||
205 | #define FLD_DIF_K_AGC_IF 0x0F000000 | ||
206 | #define FLD_DIF_K_AGC_INT 0x00F00000 | ||
207 | /* Reserved [19:12] */ | ||
208 | #define FLD_DIF_IF_REF 0x00000FFF | ||
209 | |||
210 | /*****************************************************************************/ | ||
211 | #define DIF_AGC_CTRL_IF (DIRECT_IF_REVB_BASE + 0x00000018) /* Reg Size 32 */ | ||
212 | /*****************************************************************************/ | ||
213 | #define FLD_DIF_IF_MAX 0xFF000000 | ||
214 | #define FLD_DIF_IF_MIN 0x00FF0000 | ||
215 | #define FLD_DIF_IF_AGC 0x0000FFFF | ||
216 | |||
217 | /*****************************************************************************/ | ||
218 | #define DIF_AGC_CTRL_INT (DIRECT_IF_REVB_BASE + 0x0000001C) /* Reg Size 32 */ | ||
219 | /*****************************************************************************/ | ||
220 | #define FLD_DIF_INT_MAX 0xFF000000 | ||
221 | #define FLD_DIF_INT_MIN 0x00FF0000 | ||
222 | #define FLD_DIF_INT_AGC 0x0000FFFF | ||
223 | |||
224 | /*****************************************************************************/ | ||
225 | #define DIF_AGC_CTRL_RF (DIRECT_IF_REVB_BASE + 0x00000020) /* Reg Size 32 */ | ||
226 | /*****************************************************************************/ | ||
227 | #define FLD_DIF_RF_MAX 0xFF000000 | ||
228 | #define FLD_DIF_RF_MIN 0x00FF0000 | ||
229 | #define FLD_DIF_RF_AGC 0x0000FFFF | ||
230 | |||
231 | /*****************************************************************************/ | ||
232 | #define DIF_AGC_IF_INT_CURRENT (DIRECT_IF_REVB_BASE + 0x00000024) /* Reg Size 32 */ | ||
233 | /*****************************************************************************/ | ||
234 | #define FLD_DIF_IF_AGC_IN 0xFFFF0000 | ||
235 | #define FLD_DIF_INT_AGC_IN 0x0000FFFF | ||
236 | |||
237 | /*****************************************************************************/ | ||
238 | #define DIF_AGC_RF_CURRENT (DIRECT_IF_REVB_BASE + 0x00000028) /* Reg Size 32 */ | ||
239 | /*****************************************************************************/ | ||
240 | /* Reserved [31:16] */ | ||
241 | #define FLD_DIF_RF_AGC_IN 0x0000FFFF | ||
242 | |||
243 | /*****************************************************************************/ | ||
244 | #define DIF_VIDEO_AGC_CTRL (DIRECT_IF_REVB_BASE + 0x0000002C) /* Reg Size 32 */ | ||
245 | /*****************************************************************************/ | ||
246 | #define FLD_DIF_AFD 0xC0000000 | ||
247 | #define FLD_DIF_K_VID_AGC 0x30000000 | ||
248 | #define FLD_DIF_LINE_LENGTH 0x0FFF0000 | ||
249 | #define FLD_DIF_AGC_GAIN 0x0000FFFF | ||
250 | |||
251 | /*****************************************************************************/ | ||
252 | #define DIF_VID_AUD_OVERRIDE (DIRECT_IF_REVB_BASE + 0x00000030) /* Reg Size 32 */ | ||
253 | /*****************************************************************************/ | ||
254 | #define FLD_DIF_AUDIO_AGC_OVERRIDE 0x80000000 | ||
255 | /* Reserved [30:30] */ | ||
256 | #define FLD_DIF_AUDIO_MAN_GAIN 0x3F000000 | ||
257 | /* Reserved [23:17] */ | ||
258 | #define FLD_DIF_VID_AGC_OVERRIDE 0x00010000 | ||
259 | #define FLD_DIF_VID_MAN_GAIN 0x0000FFFF | ||
260 | |||
261 | /*****************************************************************************/ | ||
262 | #define DIF_AV_SEP_CTRL (DIRECT_IF_REVB_BASE + 0x00000034) /* Reg Size 32 */ | ||
263 | /*****************************************************************************/ | ||
264 | #define FLD_DIF_LPF_FREQ 0xC0000000 | ||
265 | #define FLD_DIF_AV_PHASE_INC 0x3F000000 | ||
266 | #define FLD_DIF_AUDIO_FREQ 0x00FFFFFF | ||
267 | |||
268 | /*****************************************************************************/ | ||
269 | #define DIF_COMP_FLT_CTRL (DIRECT_IF_REVB_BASE + 0x00000038) /* Reg Size 32 */ | ||
270 | /*****************************************************************************/ | ||
271 | /* Reserved [31:24] */ | ||
272 | #define FLD_DIF_IIR23_R2 0x00FF0000 | ||
273 | #define FLD_DIF_IIR23_R1 0x0000FF00 | ||
274 | #define FLD_DIF_IIR1_R1 0x000000FF | ||
275 | |||
276 | /*****************************************************************************/ | ||
277 | #define DIF_MISC_CTRL (DIRECT_IF_REVB_BASE + 0x0000003C) /* Reg Size 32 */ | ||
278 | /*****************************************************************************/ | ||
279 | #define FLD_DIF_DIF_BYPASS 0x80000000 | ||
280 | #define FLD_DIF_FM_NYQ_GAIN 0x40000000 | ||
281 | #define FLD_DIF_RF_AGC_ENA 0x20000000 | ||
282 | #define FLD_DIF_INT_AGC_ENA 0x10000000 | ||
283 | #define FLD_DIF_IF_AGC_ENA 0x08000000 | ||
284 | #define FLD_DIF_FORCE_RF_IF_LOCK 0x04000000 | ||
285 | #define FLD_DIF_VIDEO_AGC_ENA 0x02000000 | ||
286 | #define FLD_DIF_RF_AGC_INV 0x01000000 | ||
287 | #define FLD_DIF_INT_AGC_INV 0x00800000 | ||
288 | #define FLD_DIF_IF_AGC_INV 0x00400000 | ||
289 | #define FLD_DIF_SPEC_INV 0x00200000 | ||
290 | #define FLD_DIF_AUD_FULL_BW 0x00100000 | ||
291 | #define FLD_DIF_AUD_SRC_SEL 0x00080000 | ||
292 | /* Reserved [18] */ | ||
293 | #define FLD_DIF_IF_FREQ 0x00030000 | ||
294 | /* Reserved [15:14] */ | ||
295 | #define FLD_DIF_TIP_OFFSET 0x00003F00 | ||
296 | /* Reserved [7:5] */ | ||
297 | #define FLD_DIF_DITHER_ENA 0x00000010 | ||
298 | /* Reserved [3:1] */ | ||
299 | #define FLD_DIF_RF_IF_LOCK 0x00000001 | ||
300 | |||
301 | /*****************************************************************************/ | ||
302 | #define DIF_SRC_PHASE_INC (DIRECT_IF_REVB_BASE + 0x00000040) /* Reg Size 32 */ | ||
303 | /*****************************************************************************/ | ||
304 | /* Reserved [31:29] */ | ||
305 | #define FLD_DIF_PHASE_INC 0x1FFFFFFF | ||
306 | |||
307 | /*****************************************************************************/ | ||
308 | #define DIF_SRC_GAIN_CONTROL (DIRECT_IF_REVB_BASE + 0x00000044) /* Reg Size 32 */ | ||
309 | /*****************************************************************************/ | ||
310 | /* Reserved [31:16] */ | ||
311 | #define FLD_DIF_SRC_KI 0x0000FF00 | ||
312 | #define FLD_DIF_SRC_KD 0x000000FF | ||
313 | |||
314 | /*****************************************************************************/ | ||
315 | #define DIF_BPF_COEFF01 (DIRECT_IF_REVB_BASE + 0x00000048) /* Reg Size 32 */ | ||
316 | /*****************************************************************************/ | ||
317 | /* Reserved [31:19] */ | ||
318 | #define FLD_DIF_BPF_COEFF_0 0x00070000 | ||
319 | /* Reserved [15:4] */ | ||
320 | #define FLD_DIF_BPF_COEFF_1 0x0000000F | ||
321 | |||
322 | /*****************************************************************************/ | ||
323 | #define DIF_BPF_COEFF23 (DIRECT_IF_REVB_BASE + 0x0000004c) /* Reg Size 32 */ | ||
324 | /*****************************************************************************/ | ||
325 | /* Reserved [31:22] */ | ||
326 | #define FLD_DIF_BPF_COEFF_2 0x003F0000 | ||
327 | /* Reserved [15:7] */ | ||
328 | #define FLD_DIF_BPF_COEFF_3 0x0000007F | ||
329 | |||
330 | /*****************************************************************************/ | ||
331 | #define DIF_BPF_COEFF45 (DIRECT_IF_REVB_BASE + 0x00000050) /* Reg Size 32 */ | ||
332 | /*****************************************************************************/ | ||
333 | /* Reserved [31:24] */ | ||
334 | #define FLD_DIF_BPF_COEFF_4 0x00FF0000 | ||
335 | /* Reserved [15:8] */ | ||
336 | #define FLD_DIF_BPF_COEFF_5 0x000000FF | ||
337 | |||
338 | /*****************************************************************************/ | ||
339 | #define DIF_BPF_COEFF67 (DIRECT_IF_REVB_BASE + 0x00000054) /* Reg Size 32 */ | ||
340 | /*****************************************************************************/ | ||
341 | /* Reserved [31:25] */ | ||
342 | #define FLD_DIF_BPF_COEFF_6 0x01FF0000 | ||
343 | /* Reserved [15:9] */ | ||
344 | #define FLD_DIF_BPF_COEFF_7 0x000001FF | ||
345 | |||
346 | /*****************************************************************************/ | ||
347 | #define DIF_BPF_COEFF89 (DIRECT_IF_REVB_BASE + 0x00000058) /* Reg Size 32 */ | ||
348 | /*****************************************************************************/ | ||
349 | /* Reserved [31:26] */ | ||
350 | #define FLD_DIF_BPF_COEFF_8 0x03FF0000 | ||
351 | /* Reserved [15:10] */ | ||
352 | #define FLD_DIF_BPF_COEFF_9 0x000003FF | ||
353 | |||
354 | /*****************************************************************************/ | ||
355 | #define DIF_BPF_COEFF1011 (DIRECT_IF_REVB_BASE + 0x0000005C) /* Reg Size 32 */ | ||
356 | /*****************************************************************************/ | ||
357 | /* Reserved [31:27] */ | ||
358 | #define FLD_DIF_BPF_COEFF_10 0x07FF0000 | ||
359 | /* Reserved [15:11] */ | ||
360 | #define FLD_DIF_BPF_COEFF_11 0x000007FF | ||
361 | |||
362 | /*****************************************************************************/ | ||
363 | #define DIF_BPF_COEFF1213 (DIRECT_IF_REVB_BASE + 0x00000060) /* Reg Size 32 */ | ||
364 | /*****************************************************************************/ | ||
365 | /* Reserved [31:27] */ | ||
366 | #define FLD_DIF_BPF_COEFF_12 0x07FF0000 | ||
367 | /* Reserved [15:12] */ | ||
368 | #define FLD_DIF_BPF_COEFF_13 0x00000FFF | ||
369 | |||
370 | /*****************************************************************************/ | ||
371 | #define DIF_BPF_COEFF1415 (DIRECT_IF_REVB_BASE + 0x00000064) /* Reg Size 32 */ | ||
372 | /*****************************************************************************/ | ||
373 | /* Reserved [31:28] */ | ||
374 | #define FLD_DIF_BPF_COEFF_14 0x0FFF0000 | ||
375 | /* Reserved [15:12] */ | ||
376 | #define FLD_DIF_BPF_COEFF_15 0x00000FFF | ||
377 | |||
378 | /*****************************************************************************/ | ||
379 | #define DIF_BPF_COEFF1617 (DIRECT_IF_REVB_BASE + 0x00000068) /* Reg Size 32 */ | ||
380 | /*****************************************************************************/ | ||
381 | /* Reserved [31:29] */ | ||
382 | #define FLD_DIF_BPF_COEFF_16 0x1FFF0000 | ||
383 | /* Reserved [15:13] */ | ||
384 | #define FLD_DIF_BPF_COEFF_17 0x00001FFF | ||
385 | |||
386 | /*****************************************************************************/ | ||
387 | #define DIF_BPF_COEFF1819 (DIRECT_IF_REVB_BASE + 0x0000006C) /* Reg Size 32 */ | ||
388 | /*****************************************************************************/ | ||
389 | /* Reserved [31:29] */ | ||
390 | #define FLD_DIF_BPF_COEFF_18 0x1FFF0000 | ||
391 | /* Reserved [15:13] */ | ||
392 | #define FLD_DIF_BPF_COEFF_19 0x00001FFF | ||
393 | |||
394 | /*****************************************************************************/ | ||
395 | #define DIF_BPF_COEFF2021 (DIRECT_IF_REVB_BASE + 0x00000070) /* Reg Size 32 */ | ||
396 | /*****************************************************************************/ | ||
397 | /* Reserved [31:29] */ | ||
398 | #define FLD_DIF_BPF_COEFF_20 0x1FFF0000 | ||
399 | /* Reserved [15:14] */ | ||
400 | #define FLD_DIF_BPF_COEFF_21 0x00003FFF | ||
401 | |||
402 | /*****************************************************************************/ | ||
403 | #define DIF_BPF_COEFF2223 (DIRECT_IF_REVB_BASE + 0x00000074) /* Reg Size 32 */ | ||
404 | /*****************************************************************************/ | ||
405 | /* Reserved [31:30] */ | ||
406 | #define FLD_DIF_BPF_COEFF_22 0x3FFF0000 | ||
407 | /* Reserved [15:14] */ | ||
408 | #define FLD_DIF_BPF_COEFF_23 0x00003FFF | ||
409 | |||
410 | /*****************************************************************************/ | ||
411 | #define DIF_BPF_COEFF2425 (DIRECT_IF_REVB_BASE + 0x00000078) /* Reg Size 32 */ | ||
412 | /*****************************************************************************/ | ||
413 | /* Reserved [31:30] */ | ||
414 | #define FLD_DIF_BPF_COEFF_24 0x3FFF0000 | ||
415 | /* Reserved [15:14] */ | ||
416 | #define FLD_DIF_BPF_COEFF_25 0x00003FFF | ||
417 | |||
418 | /*****************************************************************************/ | ||
419 | #define DIF_BPF_COEFF2627 (DIRECT_IF_REVB_BASE + 0x0000007C) /* Reg Size 32 */ | ||
420 | /*****************************************************************************/ | ||
421 | /* Reserved [31:30] */ | ||
422 | #define FLD_DIF_BPF_COEFF_26 0x3FFF0000 | ||
423 | /* Reserved [15:14] */ | ||
424 | #define FLD_DIF_BPF_COEFF_27 0x00003FFF | ||
425 | |||
426 | /*****************************************************************************/ | ||
427 | #define DIF_BPF_COEFF2829 (DIRECT_IF_REVB_BASE + 0x00000080) /* Reg Size 32 */ | ||
428 | /*****************************************************************************/ | ||
429 | /* Reserved [31:30] */ | ||
430 | #define FLD_DIF_BPF_COEFF_28 0x3FFF0000 | ||
431 | /* Reserved [15:14] */ | ||
432 | #define FLD_DIF_BPF_COEFF_29 0x00003FFF | ||
433 | |||
434 | /*****************************************************************************/ | ||
435 | #define DIF_BPF_COEFF3031 (DIRECT_IF_REVB_BASE + 0x00000084) /* Reg Size 32 */ | ||
436 | /*****************************************************************************/ | ||
437 | /* Reserved [31:30] */ | ||
438 | #define FLD_DIF_BPF_COEFF_30 0x3FFF0000 | ||
439 | /* Reserved [15:14] */ | ||
440 | #define FLD_DIF_BPF_COEFF_31 0x00003FFF | ||
441 | |||
442 | /*****************************************************************************/ | ||
443 | #define DIF_BPF_COEFF3233 (DIRECT_IF_REVB_BASE + 0x00000088) /* Reg Size 32 */ | ||
444 | /*****************************************************************************/ | ||
445 | /* Reserved [31:30] */ | ||
446 | #define FLD_DIF_BPF_COEFF_32 0x3FFF0000 | ||
447 | /* Reserved [15:14] */ | ||
448 | #define FLD_DIF_BPF_COEFF_33 0x00003FFF | ||
449 | |||
450 | /*****************************************************************************/ | ||
451 | #define DIF_BPF_COEFF3435 (DIRECT_IF_REVB_BASE + 0x0000008C) /* Reg Size 32 */ | ||
452 | /*****************************************************************************/ | ||
453 | /* Reserved [31:30] */ | ||
454 | #define FLD_DIF_BPF_COEFF_34 0x3FFF0000 | ||
455 | /* Reserved [15:14] */ | ||
456 | #define FLD_DIF_BPF_COEFF_35 0x00003FFF | ||
457 | |||
458 | /*****************************************************************************/ | ||
459 | #define DIF_BPF_COEFF36 (DIRECT_IF_REVB_BASE + 0x00000090) /* Reg Size 32 */ | ||
460 | /*****************************************************************************/ | ||
461 | /* Reserved [31:30] */ | ||
462 | #define FLD_DIF_BPF_COEFF_36 0x3FFF0000 | ||
463 | /* Reserved [15:0] */ | ||
464 | |||
465 | /*****************************************************************************/ | ||
466 | #define DIF_RPT_VARIANCE (DIRECT_IF_REVB_BASE + 0x00000094) /* Reg Size 32 */ | ||
467 | /*****************************************************************************/ | ||
468 | /* Reserved [31:20] */ | ||
469 | #define FLD_DIF_RPT_VARIANCE 0x000FFFFF | ||
470 | |||
471 | /*****************************************************************************/ | ||
472 | #define DIF_SOFT_RST_CTRL_REVB (DIRECT_IF_REVB_BASE + 0x00000098) /* Reg Size 32 */ | ||
473 | /*****************************************************************************/ | ||
474 | /* Reserved [31:8] */ | ||
475 | #define FLD_DIF_DIF_SOFT_RST 0x00000080 | ||
476 | #define FLD_DIF_DIF_REG_RST_MSK 0x00000040 | ||
477 | #define FLD_DIF_AGC_RST_MSK 0x00000020 | ||
478 | #define FLD_DIF_CMP_RST_MSK 0x00000010 | ||
479 | #define FLD_DIF_AVS_RST_MSK 0x00000008 | ||
480 | #define FLD_DIF_NYQ_RST_MSK 0x00000004 | ||
481 | #define FLD_DIF_DIF_SRC_RST_MSK 0x00000002 | ||
482 | #define FLD_DIF_PLL_RST_MSK 0x00000001 | ||
483 | |||
484 | /*****************************************************************************/ | ||
485 | #define DIF_PLL_FREQ_ERR (DIRECT_IF_REVB_BASE + 0x0000009C) /* Reg Size 32 */ | ||
486 | /*****************************************************************************/ | ||
487 | /* Reserved [31:25] */ | ||
488 | #define FLD_DIF_CTL_IP 0x01FFFFFF | ||
489 | |||
490 | |||
491 | #endif | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c new file mode 100644 index 000000000000..efe0c666043a --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-core.c | |||
@@ -0,0 +1,1167 @@ | |||
1 | /* | ||
2 | cx231xx-core.c - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on em28xx driver | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/vmalloc.h> | ||
27 | #include <media/v4l2-common.h> | ||
28 | |||
29 | #include "cx231xx.h" | ||
30 | #include "cx231xx-reg.h" | ||
31 | |||
32 | /* #define ENABLE_DEBUG_ISOC_FRAMES */ | ||
33 | |||
34 | static unsigned int core_debug; | ||
35 | module_param(core_debug,int,0644); | ||
36 | MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); | ||
37 | |||
38 | #define cx231xx_coredbg(fmt, arg...) do {\ | ||
39 | if (core_debug) \ | ||
40 | printk(KERN_INFO "%s %s :"fmt, \ | ||
41 | dev->name, __func__ , ##arg); } while (0) | ||
42 | |||
43 | static unsigned int reg_debug; | ||
44 | module_param(reg_debug,int,0644); | ||
45 | MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); | ||
46 | |||
47 | #define cx231xx_regdbg(fmt, arg...) do {\ | ||
48 | if (reg_debug) \ | ||
49 | printk(KERN_INFO "%s %s :"fmt, \ | ||
50 | dev->name, __func__ , ##arg); } while (0) | ||
51 | |||
52 | static int alt = CX231XX_PINOUT; | ||
53 | module_param(alt, int, 0644); | ||
54 | MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); | ||
55 | |||
56 | /* FIXME */ | ||
57 | #define cx231xx_isocdbg(fmt, arg...) do {\ | ||
58 | if (core_debug) \ | ||
59 | printk(KERN_INFO "%s %s :"fmt, \ | ||
60 | dev->name, __func__ , ##arg); } while (0) | ||
61 | |||
62 | |||
63 | |||
64 | /************************************************************************************ | ||
65 | * Device control list functions * | ||
66 | *************************************************************************************/ | ||
67 | |||
68 | static LIST_HEAD(cx231xx_devlist); | ||
69 | static DEFINE_MUTEX(cx231xx_devlist_mutex); | ||
70 | |||
71 | struct cx231xx *cx231xx_get_device(int minor, | ||
72 | enum v4l2_buf_type *fh_type, | ||
73 | int *has_radio) | ||
74 | { | ||
75 | struct cx231xx *h, *dev = NULL; | ||
76 | |||
77 | *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
78 | *has_radio = 0; | ||
79 | |||
80 | mutex_lock(&cx231xx_devlist_mutex); | ||
81 | list_for_each_entry(h, &cx231xx_devlist, devlist) { | ||
82 | if (h->vdev->minor == minor) | ||
83 | dev = h; | ||
84 | if (h->vbi_dev->minor == minor) { | ||
85 | dev = h; | ||
86 | *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
87 | } | ||
88 | if (h->radio_dev && | ||
89 | h->radio_dev->minor == minor) { | ||
90 | dev = h; | ||
91 | *has_radio = 1; | ||
92 | } | ||
93 | } | ||
94 | mutex_unlock(&cx231xx_devlist_mutex); | ||
95 | |||
96 | return dev; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * cx231xx_realease_resources() | ||
101 | * unregisters the v4l2,i2c and usb devices | ||
102 | * called when the device gets disconected or at module unload | ||
103 | */ | ||
104 | void cx231xx_remove_from_devlist(struct cx231xx *dev) | ||
105 | { | ||
106 | mutex_lock(&cx231xx_devlist_mutex); | ||
107 | list_del(&dev->devlist); | ||
108 | mutex_unlock(&cx231xx_devlist_mutex); | ||
109 | }; | ||
110 | |||
111 | void cx231xx_add_into_devlist(struct cx231xx *dev) | ||
112 | { | ||
113 | mutex_lock(&cx231xx_devlist_mutex); | ||
114 | list_add_tail(&dev->devlist, &cx231xx_devlist); | ||
115 | mutex_unlock(&cx231xx_devlist_mutex); | ||
116 | }; | ||
117 | |||
118 | |||
119 | |||
120 | |||
121 | static LIST_HEAD(cx231xx_extension_devlist); | ||
122 | static DEFINE_MUTEX(cx231xx_extension_devlist_lock); | ||
123 | |||
124 | int cx231xx_register_extension(struct cx231xx_ops *ops) | ||
125 | { | ||
126 | struct cx231xx *dev = NULL; | ||
127 | |||
128 | mutex_lock(&cx231xx_devlist_mutex); | ||
129 | mutex_lock(&cx231xx_extension_devlist_lock); | ||
130 | list_add_tail(&ops->next, &cx231xx_extension_devlist); | ||
131 | list_for_each_entry(dev, &cx231xx_devlist, devlist) { | ||
132 | if (dev) | ||
133 | ops->init(dev); | ||
134 | } | ||
135 | cx231xx_info("Cx231xx: Initialized (%s) extension\n", ops->name); | ||
136 | mutex_unlock(&cx231xx_extension_devlist_lock); | ||
137 | mutex_unlock(&cx231xx_devlist_mutex); | ||
138 | return 0; | ||
139 | } | ||
140 | EXPORT_SYMBOL(cx231xx_register_extension); | ||
141 | |||
142 | void cx231xx_unregister_extension(struct cx231xx_ops *ops) | ||
143 | { | ||
144 | struct cx231xx *dev = NULL; | ||
145 | |||
146 | mutex_lock(&cx231xx_devlist_mutex); | ||
147 | list_for_each_entry(dev, &cx231xx_devlist, devlist) { | ||
148 | if (dev) | ||
149 | ops->fini(dev); | ||
150 | } | ||
151 | |||
152 | mutex_lock(&cx231xx_extension_devlist_lock); | ||
153 | cx231xx_info("Cx231xx: Removed (%s) extension\n", ops->name); | ||
154 | list_del(&ops->next); | ||
155 | mutex_unlock(&cx231xx_extension_devlist_lock); | ||
156 | mutex_unlock(&cx231xx_devlist_mutex); | ||
157 | } | ||
158 | EXPORT_SYMBOL(cx231xx_unregister_extension); | ||
159 | |||
160 | |||
161 | void cx231xx_init_extension(struct cx231xx *dev) | ||
162 | { | ||
163 | struct cx231xx_ops *ops = NULL; | ||
164 | |||
165 | mutex_lock(&cx231xx_extension_devlist_lock); | ||
166 | if (!list_empty(&cx231xx_extension_devlist)) { | ||
167 | list_for_each_entry(ops, &cx231xx_extension_devlist, next) { | ||
168 | if (ops->init) | ||
169 | ops->init(dev); | ||
170 | } | ||
171 | } | ||
172 | mutex_unlock(&cx231xx_extension_devlist_lock); | ||
173 | } | ||
174 | |||
175 | void cx231xx_close_extension(struct cx231xx *dev) | ||
176 | { | ||
177 | struct cx231xx_ops *ops = NULL; | ||
178 | |||
179 | mutex_lock(&cx231xx_extension_devlist_lock); | ||
180 | if (!list_empty(&cx231xx_extension_devlist)) { | ||
181 | list_for_each_entry(ops, &cx231xx_extension_devlist, next) { | ||
182 | if (ops->fini) | ||
183 | ops->fini(dev); | ||
184 | } | ||
185 | } | ||
186 | mutex_unlock(&cx231xx_extension_devlist_lock); | ||
187 | } | ||
188 | |||
189 | /************************************************************************************ | ||
190 | * U S B related functions * | ||
191 | *************************************************************************************/ | ||
192 | int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, | ||
193 | struct cx231xx_i2c_xfer_data *req_data) | ||
194 | { | ||
195 | int status = 0; | ||
196 | struct cx231xx *dev = i2c_bus->dev; | ||
197 | VENDOR_REQUEST_IN ven_req; | ||
198 | |||
199 | u8 saddr_len = 0; | ||
200 | u8 _i2c_period = 0; | ||
201 | u8 _i2c_nostop = 0; | ||
202 | u8 _i2c_reserve = 0; | ||
203 | |||
204 | /* Get the I2C period, nostop and reserve parameters */ | ||
205 | _i2c_period = i2c_bus->i2c_period; | ||
206 | _i2c_nostop = i2c_bus->i2c_nostop; | ||
207 | _i2c_reserve = i2c_bus->i2c_reserve; | ||
208 | |||
209 | saddr_len = req_data->saddr_len; | ||
210 | |||
211 | /* Set wValue */ | ||
212 | if(saddr_len == 1) /* need check saddr_len == 0 */ | ||
213 | ven_req.wValue = req_data->dev_addr<<9|_i2c_period<<4|saddr_len<<2| | ||
214 | _i2c_nostop<<1|I2C_SYNC|_i2c_reserve<<6; | ||
215 | else | ||
216 | ven_req.wValue = req_data->dev_addr<<9|_i2c_period<<4|saddr_len<<2| | ||
217 | _i2c_nostop<<1|I2C_SYNC|_i2c_reserve<<6; | ||
218 | |||
219 | /* set channel number */ | ||
220 | if(req_data->direction & I2C_M_RD) | ||
221 | ven_req.bRequest = i2c_bus->nr + 4; /* channel number, for read, | ||
222 | spec required channel_num +4 */ | ||
223 | else | ||
224 | ven_req.bRequest = i2c_bus->nr; /* channel number, */ | ||
225 | |||
226 | /* set index value */ | ||
227 | switch(saddr_len){ | ||
228 | case 0: | ||
229 | ven_req.wIndex = 0; /* need check */ | ||
230 | break; | ||
231 | case 1: | ||
232 | ven_req.wIndex = (req_data->saddr_dat & 0xff); | ||
233 | break; | ||
234 | case 2: | ||
235 | ven_req.wIndex = req_data->saddr_dat; | ||
236 | break; | ||
237 | } | ||
238 | |||
239 | /* set wLength value */ | ||
240 | ven_req.wLength = req_data->buf_size; | ||
241 | |||
242 | /* set bData value */ | ||
243 | ven_req.bData = 0; | ||
244 | |||
245 | /* set the direction */ | ||
246 | if(req_data->direction){ | ||
247 | ven_req.direction = USB_DIR_IN; | ||
248 | memset(req_data->p_buffer, 0x00, ven_req.wLength); | ||
249 | } | ||
250 | else | ||
251 | ven_req.direction = USB_DIR_OUT; | ||
252 | |||
253 | /* set the buffer for read / write */ | ||
254 | ven_req.pBuff = req_data->p_buffer; | ||
255 | |||
256 | |||
257 | |||
258 | /* call common vendor command request */ | ||
259 | status = cx231xx_send_vendor_cmd(dev, &ven_req); | ||
260 | if (status < 0) { | ||
261 | cx231xx_info("UsbInterface::sendCommand, output buffer failed with status -%d\n", status); | ||
262 | } | ||
263 | |||
264 | return status; | ||
265 | } | ||
266 | |||
267 | EXPORT_SYMBOL_GPL(cx231xx_send_usb_command); | ||
268 | /* | ||
269 | * cx231xx_read_ctrl_reg() | ||
270 | * reads data from the usb device specifying bRequest and wValue | ||
271 | */ | ||
272 | int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, | ||
273 | char *buf, int len) | ||
274 | { | ||
275 | u8 val = 0; | ||
276 | int ret; | ||
277 | int pipe = usb_rcvctrlpipe(dev->udev, 0); | ||
278 | |||
279 | if (dev->state & DEV_DISCONNECTED) | ||
280 | return -ENODEV; | ||
281 | |||
282 | if (len > URB_MAX_CTRL_SIZE) | ||
283 | return -EINVAL; | ||
284 | |||
285 | switch(len) | ||
286 | { | ||
287 | case 1: | ||
288 | val = ENABLE_ONE_BYTE; | ||
289 | break; | ||
290 | case 2: | ||
291 | val = ENABLE_TWE_BYTE; | ||
292 | break; | ||
293 | case 3: | ||
294 | val = ENABLE_THREE_BYTE; | ||
295 | break; | ||
296 | case 4: | ||
297 | val = ENABLE_FOUR_BYTE; | ||
298 | break; | ||
299 | default: | ||
300 | val = 0xFF; /* invalid option */ | ||
301 | } | ||
302 | |||
303 | if(val == 0xFF) | ||
304 | return -EINVAL; | ||
305 | |||
306 | if (reg_debug) { | ||
307 | cx231xx_isocdbg("(pipe 0x%08x): " | ||
308 | "IN: %02x %02x %02x %02x %02x %02x %02x %02x ", | ||
309 | pipe, | ||
310 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
311 | req, 0, val, | ||
312 | reg & 0xff, reg >> 8, | ||
313 | len & 0xff, len >> 8); | ||
314 | } | ||
315 | |||
316 | /* mutex_lock(&dev->ctrl_urb_lock); */ | ||
317 | ret = usb_control_msg(dev->udev, pipe, req, | ||
318 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
319 | val, reg, dev->urb_buf, len, HZ); | ||
320 | if (ret < 0) { | ||
321 | cx231xx_isocdbg(" failed!\n"); | ||
322 | /* mutex_unlock(&dev->ctrl_urb_lock); */ | ||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | if (len) | ||
327 | memcpy(buf, dev->urb_buf, len); | ||
328 | |||
329 | /* mutex_unlock(&dev->ctrl_urb_lock); */ | ||
330 | |||
331 | if (reg_debug) { | ||
332 | int byte; | ||
333 | |||
334 | cx231xx_isocdbg("<<<"); | ||
335 | for (byte = 0; byte < len; byte++) | ||
336 | cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]); | ||
337 | cx231xx_isocdbg("\n"); | ||
338 | } | ||
339 | |||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | |||
344 | int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req) | ||
345 | { | ||
346 | int ret; | ||
347 | int pipe = 0; | ||
348 | |||
349 | if (dev->state & DEV_DISCONNECTED) | ||
350 | return -ENODEV; | ||
351 | |||
352 | if ((ven_req->wLength > URB_MAX_CTRL_SIZE)) | ||
353 | return -EINVAL; | ||
354 | |||
355 | if(ven_req->direction) | ||
356 | pipe = usb_rcvctrlpipe(dev->udev, 0); | ||
357 | else | ||
358 | pipe = usb_sndctrlpipe(dev->udev, 0); | ||
359 | |||
360 | |||
361 | if (reg_debug) { | ||
362 | int byte; | ||
363 | |||
364 | cx231xx_isocdbg("(pipe 0x%08x): " | ||
365 | "OUT: %02x %02x %02x %04x %04x %04x >>>", | ||
366 | pipe, | ||
367 | ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
368 | ven_req->bRequest, 0, ven_req->wValue, | ||
369 | ven_req->wIndex, | ||
370 | ven_req->wLength); | ||
371 | |||
372 | for (byte = 0; byte < ven_req->wLength; byte++) | ||
373 | cx231xx_isocdbg(" %02x", (unsigned char)ven_req->pBuff[byte]); | ||
374 | cx231xx_isocdbg("\n"); | ||
375 | } | ||
376 | |||
377 | /* mutex_lock(&dev->ctrl_urb_lock); */ | ||
378 | ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest, | ||
379 | ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
380 | ven_req->wValue, ven_req->wIndex, ven_req->pBuff, ven_req->wLength, HZ); | ||
381 | /* mutex_unlock(&dev->ctrl_urb_lock); */ | ||
382 | |||
383 | return ret; | ||
384 | } | ||
385 | |||
386 | /* | ||
387 | * cx231xx_write_ctrl_reg() | ||
388 | * sends data to the usb device, specifying bRequest | ||
389 | */ | ||
390 | int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, | ||
391 | int len) | ||
392 | { | ||
393 | u8 val = 0; | ||
394 | int ret; | ||
395 | int pipe = usb_sndctrlpipe(dev->udev, 0); | ||
396 | |||
397 | if (dev->state & DEV_DISCONNECTED) | ||
398 | return -ENODEV; | ||
399 | |||
400 | if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) | ||
401 | return -EINVAL; | ||
402 | |||
403 | switch(len) | ||
404 | { | ||
405 | case 1: | ||
406 | val = ENABLE_ONE_BYTE; | ||
407 | break; | ||
408 | case 2: | ||
409 | val = ENABLE_TWE_BYTE; | ||
410 | break; | ||
411 | case 3: | ||
412 | val = ENABLE_THREE_BYTE; | ||
413 | break; | ||
414 | case 4: | ||
415 | val = ENABLE_FOUR_BYTE; | ||
416 | break; | ||
417 | default: | ||
418 | val = 0xFF; /* invalid option */ | ||
419 | } | ||
420 | |||
421 | if(val == 0xFF) | ||
422 | return -EINVAL; | ||
423 | |||
424 | if (reg_debug) { | ||
425 | int byte; | ||
426 | |||
427 | cx231xx_isocdbg("(pipe 0x%08x): " | ||
428 | "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", | ||
429 | pipe, | ||
430 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
431 | req, 0, val, | ||
432 | reg & 0xff, reg >> 8, | ||
433 | len & 0xff, len >> 8); | ||
434 | |||
435 | for (byte = 0; byte < len; byte++) | ||
436 | cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]); | ||
437 | cx231xx_isocdbg("\n"); | ||
438 | } | ||
439 | |||
440 | /* mutex_lock(&dev->ctrl_urb_lock); */ | ||
441 | memcpy(dev->urb_buf, buf, len); | ||
442 | ret = usb_control_msg(dev->udev, pipe, req, | ||
443 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
444 | val, reg, dev->urb_buf, len, HZ); | ||
445 | /* mutex_unlock(&dev->ctrl_urb_lock); */ | ||
446 | |||
447 | return ret; | ||
448 | } | ||
449 | |||
450 | |||
451 | /************************************************************************************ | ||
452 | * USB Alternate Setting functions * | ||
453 | *************************************************************************************/ | ||
454 | |||
455 | int cx231xx_set_video_alternate(struct cx231xx *dev) | ||
456 | { | ||
457 | int errCode, prev_alt = dev->video_mode.alt; | ||
458 | unsigned int min_pkt_size = dev->width * 2 + 4; | ||
459 | u32 usb_interface_index = 0; | ||
460 | |||
461 | /* When image size is bigger than a certain value, | ||
462 | the frame size should be increased, otherwise, only | ||
463 | green screen will be received. | ||
464 | */ | ||
465 | if (dev->width * 2 * dev->height > 720 * 240 * 2) | ||
466 | min_pkt_size *= 2; | ||
467 | |||
468 | if(dev->width > 360) { | ||
469 | /* resolutions: 720,704,640 */ | ||
470 | dev->video_mode.alt = 3; | ||
471 | } else if(dev->width > 180) { | ||
472 | /* resolutions: 360,352,320,240 */ | ||
473 | dev->video_mode.alt = 2; | ||
474 | } else if(dev->width > 0) { | ||
475 | /* resolutions: 180,176,160,128,88 */ | ||
476 | dev->video_mode.alt = 1; | ||
477 | } else { | ||
478 | /* Change to alt0 BULK to release USB bandwidth */ | ||
479 | dev->video_mode.alt = 0; | ||
480 | } | ||
481 | |||
482 | /* Get the correct video interface Index */ | ||
483 | usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1; | ||
484 | |||
485 | if (dev->video_mode.alt != prev_alt) { | ||
486 | cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", | ||
487 | min_pkt_size, dev->video_mode.alt); | ||
488 | dev->video_mode.max_pkt_size = dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; | ||
489 | cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", | ||
490 | dev->video_mode.alt, dev->video_mode.max_pkt_size); | ||
491 | cx231xx_info(" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n", | ||
492 | dev->video_mode.alt, dev->video_mode.max_pkt_size, usb_interface_index); | ||
493 | errCode = usb_set_interface(dev->udev, usb_interface_index, dev->video_mode.alt); | ||
494 | if (errCode < 0) { | ||
495 | cx231xx_errdev("cannot change alternate number to %d (error=%i)\n", | ||
496 | dev->video_mode.alt, errCode); | ||
497 | return errCode; | ||
498 | } | ||
499 | } | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt) | ||
504 | { | ||
505 | int status = 0; | ||
506 | u32 usb_interface_index = 0; | ||
507 | u32 max_pkt_size = 0; | ||
508 | |||
509 | switch(index) { | ||
510 | case INDEX_TS1: | ||
511 | usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index+1; | ||
512 | dev->video_mode.alt = alt; | ||
513 | if(dev->ts1_mode.alt_max_pkt_size != NULL) | ||
514 | max_pkt_size = dev->ts1_mode.max_pkt_size = dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt]; | ||
515 | break; | ||
516 | case INDEX_TS2: | ||
517 | usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.ts2_index+1; | ||
518 | break; | ||
519 | case INDEX_AUDIO: | ||
520 | usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.audio_index+1; | ||
521 | dev->adev.alt = alt; | ||
522 | if( dev->adev.alt_max_pkt_size != NULL) | ||
523 | max_pkt_size = dev->adev.max_pkt_size = dev->adev.alt_max_pkt_size[dev->adev.alt]; | ||
524 | break; | ||
525 | case INDEX_VIDEO: | ||
526 | usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1; | ||
527 | dev->video_mode.alt = alt; | ||
528 | if(dev->video_mode.alt_max_pkt_size != NULL) | ||
529 | max_pkt_size = dev->video_mode.max_pkt_size = dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; | ||
530 | break; | ||
531 | case INDEX_VANC: | ||
532 | usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index+1; | ||
533 | dev->vbi_mode.alt = alt; | ||
534 | if(dev->vbi_mode.alt_max_pkt_size != NULL) | ||
535 | max_pkt_size = dev->vbi_mode.max_pkt_size = dev->vbi_mode.alt_max_pkt_size[dev->vbi_mode.alt]; | ||
536 | break; | ||
537 | case INDEX_HANC: | ||
538 | usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index+1; | ||
539 | dev->sliced_cc_mode.alt = alt; | ||
540 | if(dev->sliced_cc_mode.alt_max_pkt_size != NULL) | ||
541 | max_pkt_size = dev->sliced_cc_mode.max_pkt_size = dev->sliced_cc_mode.alt_max_pkt_size[dev->sliced_cc_mode.alt]; | ||
542 | break; | ||
543 | default: | ||
544 | break; | ||
545 | } | ||
546 | |||
547 | if(alt > 0 && max_pkt_size == 0 ) { | ||
548 | cx231xx_errdev("cannot change interface %d alternate number to %d : Max. Pkt size is ZERO\n", | ||
549 | usb_interface_index, alt); | ||
550 | return -1; | ||
551 | } | ||
552 | |||
553 | cx231xx_info(" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n", | ||
554 | alt, max_pkt_size, usb_interface_index); | ||
555 | |||
556 | if(usb_interface_index > 0 ) { | ||
557 | status = usb_set_interface(dev->udev, usb_interface_index, alt); | ||
558 | if (status < 0) { | ||
559 | cx231xx_errdev("cannot change interface %d alternate number to %d (error=%i)\n", | ||
560 | usb_interface_index, alt, status); | ||
561 | return status; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | return status; | ||
566 | } | ||
567 | EXPORT_SYMBOL_GPL(cx231xx_set_alt_setting); | ||
568 | |||
569 | int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio) | ||
570 | { | ||
571 | int rc = 0; | ||
572 | |||
573 | if (!gpio) | ||
574 | return rc; | ||
575 | |||
576 | /* Send GPIO reset sequences specified at board entry */ | ||
577 | while (gpio->sleep >= 0) { | ||
578 | rc = cx231xx_set_gpio_value(dev, gpio->bit, | ||
579 | gpio->val); | ||
580 | if (rc < 0) | ||
581 | return rc; | ||
582 | |||
583 | if (gpio->sleep > 0) | ||
584 | msleep(gpio->sleep); | ||
585 | |||
586 | gpio++; | ||
587 | } | ||
588 | return rc; | ||
589 | } | ||
590 | |||
591 | int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) | ||
592 | { | ||
593 | if (dev->mode == set_mode) | ||
594 | return 0; | ||
595 | |||
596 | if (set_mode == CX231XX_SUSPEND) { | ||
597 | /* Set the chip in power saving mode */ | ||
598 | dev->mode = set_mode; | ||
599 | } | ||
600 | |||
601 | /* Resource is locked */ | ||
602 | if (dev->mode != CX231XX_SUSPEND) | ||
603 | return -EINVAL; | ||
604 | |||
605 | dev->mode = set_mode; | ||
606 | |||
607 | if (dev->mode == CX231XX_DIGITAL_MODE) { | ||
608 | /* Set Digital power mode */ | ||
609 | } else { | ||
610 | /* Set Analog Power mode*/ | ||
611 | } | ||
612 | return 0; | ||
613 | } | ||
614 | EXPORT_SYMBOL_GPL(cx231xx_set_mode); | ||
615 | |||
616 | /************************************************************************************ | ||
617 | * URB Streaming functions * | ||
618 | *************************************************************************************/ | ||
619 | |||
620 | /* | ||
621 | * IRQ callback, called by URB callback | ||
622 | */ | ||
623 | static void cx231xx_irq_callback(struct urb *urb) | ||
624 | { | ||
625 | struct cx231xx_dmaqueue *dma_q = urb->context; | ||
626 | struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); | ||
627 | struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); | ||
628 | int rc, i; | ||
629 | |||
630 | |||
631 | switch (urb->status) { | ||
632 | case 0: /* success */ | ||
633 | case -ETIMEDOUT: /* NAK */ | ||
634 | break; | ||
635 | case -ECONNRESET: /* kill */ | ||
636 | case -ENOENT: | ||
637 | case -ESHUTDOWN: | ||
638 | return; | ||
639 | default: /* error */ | ||
640 | cx231xx_isocdbg("urb completition error %d.\n", urb->status); | ||
641 | break; | ||
642 | } | ||
643 | |||
644 | /* Copy data from URB */ | ||
645 | spin_lock(&dev->video_mode.slock); | ||
646 | rc = dev->video_mode.isoc_ctl.isoc_copy(dev, urb); | ||
647 | spin_unlock(&dev->video_mode.slock); | ||
648 | |||
649 | /* Reset urb buffers */ | ||
650 | for (i = 0; i < urb->number_of_packets; i++) { | ||
651 | urb->iso_frame_desc[i].status = 0; | ||
652 | urb->iso_frame_desc[i].actual_length = 0; | ||
653 | } | ||
654 | urb->status = 0; | ||
655 | |||
656 | urb->status = usb_submit_urb(urb, GFP_ATOMIC); | ||
657 | if (urb->status) { | ||
658 | cx231xx_isocdbg("urb resubmit failed (error=%i)\n", | ||
659 | urb->status); | ||
660 | } | ||
661 | } | ||
662 | |||
663 | /* | ||
664 | * Stop and Deallocate URBs | ||
665 | */ | ||
666 | void cx231xx_uninit_isoc(struct cx231xx *dev) | ||
667 | { | ||
668 | struct urb *urb; | ||
669 | int i; | ||
670 | |||
671 | cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n"); | ||
672 | |||
673 | dev->video_mode.isoc_ctl.nfields = -1; | ||
674 | for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { | ||
675 | urb = dev->video_mode.isoc_ctl.urb[i]; | ||
676 | if (urb) { | ||
677 | if (!irqs_disabled()) | ||
678 | usb_kill_urb(urb); | ||
679 | else | ||
680 | usb_unlink_urb(urb); | ||
681 | |||
682 | if (dev->video_mode.isoc_ctl.transfer_buffer[i]) { | ||
683 | usb_buffer_free(dev->udev, | ||
684 | urb->transfer_buffer_length, | ||
685 | dev->video_mode.isoc_ctl.transfer_buffer[i], | ||
686 | urb->transfer_dma); | ||
687 | } | ||
688 | usb_free_urb(urb); | ||
689 | dev->video_mode.isoc_ctl.urb[i] = NULL; | ||
690 | } | ||
691 | dev->video_mode.isoc_ctl.transfer_buffer[i] = NULL; | ||
692 | } | ||
693 | |||
694 | kfree(dev->video_mode.isoc_ctl.urb); | ||
695 | kfree(dev->video_mode.isoc_ctl.transfer_buffer); | ||
696 | |||
697 | dev->video_mode.isoc_ctl.urb = NULL; | ||
698 | dev->video_mode.isoc_ctl.transfer_buffer = NULL; | ||
699 | dev->video_mode.isoc_ctl.num_bufs = 0; | ||
700 | |||
701 | cx231xx_capture_start(dev, 0, Raw_Video); | ||
702 | } | ||
703 | EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc); | ||
704 | |||
705 | /* | ||
706 | * Allocate URBs and start IRQ | ||
707 | */ | ||
708 | int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, | ||
709 | int num_bufs, int max_pkt_size, | ||
710 | int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)) | ||
711 | { | ||
712 | struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; | ||
713 | int i; | ||
714 | int sb_size, pipe; | ||
715 | struct urb *urb; | ||
716 | int j, k; | ||
717 | int rc; | ||
718 | |||
719 | cx231xx_isocdbg("cx231xx: called cx231xx_prepare_isoc\n"); | ||
720 | |||
721 | dev->video_input = dev->video_input > 2?2:dev->video_input; | ||
722 | |||
723 | cx231xx_info("Setting Video mux to %d\n",dev->video_input); | ||
724 | video_mux(dev, dev->video_input); | ||
725 | |||
726 | |||
727 | /* De-allocates all pending stuff */ | ||
728 | cx231xx_uninit_isoc(dev); | ||
729 | |||
730 | dev->video_mode.isoc_ctl.isoc_copy = isoc_copy; | ||
731 | dev->video_mode.isoc_ctl.num_bufs = num_bufs; | ||
732 | dma_q->pos = 0; | ||
733 | dma_q->is_partial_line = 0; | ||
734 | dma_q->last_sav = 0; | ||
735 | dma_q->current_field = -1; | ||
736 | dma_q->field1_done = 0; | ||
737 | dma_q->lines_per_field = dev->height/2; | ||
738 | dma_q->bytes_left_in_line = dev->width << 1; | ||
739 | dma_q->lines_completed = 0; | ||
740 | for(i = 0; i < 8 ; i++) | ||
741 | dma_q->partial_buf[i] = 0; | ||
742 | |||
743 | dev->video_mode.isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); | ||
744 | if (!dev->video_mode.isoc_ctl.urb) { | ||
745 | cx231xx_errdev("cannot alloc memory for usb buffers\n"); | ||
746 | return -ENOMEM; | ||
747 | } | ||
748 | |||
749 | dev->video_mode.isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, | ||
750 | GFP_KERNEL); | ||
751 | if (!dev->video_mode.isoc_ctl.transfer_buffer) { | ||
752 | cx231xx_errdev("cannot allocate memory for usbtransfer\n"); | ||
753 | kfree(dev->video_mode.isoc_ctl.urb); | ||
754 | return -ENOMEM; | ||
755 | } | ||
756 | |||
757 | dev->video_mode.isoc_ctl.max_pkt_size = max_pkt_size; | ||
758 | dev->video_mode.isoc_ctl.buf = NULL; | ||
759 | |||
760 | sb_size = max_packets * dev->video_mode.isoc_ctl.max_pkt_size; | ||
761 | |||
762 | /* allocate urbs and transfer buffers */ | ||
763 | for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { | ||
764 | urb = usb_alloc_urb(max_packets, GFP_KERNEL); | ||
765 | if (!urb) { | ||
766 | cx231xx_err("cannot alloc isoc_ctl.urb %i\n", i); | ||
767 | cx231xx_uninit_isoc(dev); | ||
768 | return -ENOMEM; | ||
769 | } | ||
770 | dev->video_mode.isoc_ctl.urb[i] = urb; | ||
771 | |||
772 | dev->video_mode.isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev, | ||
773 | sb_size, GFP_KERNEL, &urb->transfer_dma); | ||
774 | if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) { | ||
775 | cx231xx_err("unable to allocate %i bytes for transfer" | ||
776 | " buffer %i%s\n", | ||
777 | sb_size, i, | ||
778 | in_interrupt()?" while in int":""); | ||
779 | cx231xx_uninit_isoc(dev); | ||
780 | return -ENOMEM; | ||
781 | } | ||
782 | memset(dev->video_mode.isoc_ctl.transfer_buffer[i], 0, sb_size); | ||
783 | |||
784 | pipe = usb_rcvisocpipe(dev->udev, dev->video_mode.end_point_addr); | ||
785 | |||
786 | usb_fill_int_urb(urb, dev->udev, pipe, | ||
787 | dev->video_mode.isoc_ctl.transfer_buffer[i], sb_size, | ||
788 | cx231xx_irq_callback, dma_q, 1); | ||
789 | |||
790 | urb->number_of_packets = max_packets; | ||
791 | urb->transfer_flags = URB_ISO_ASAP; | ||
792 | |||
793 | k = 0; | ||
794 | for (j = 0; j < max_packets; j++) { | ||
795 | urb->iso_frame_desc[j].offset = k; | ||
796 | urb->iso_frame_desc[j].length = | ||
797 | dev->video_mode.isoc_ctl.max_pkt_size; | ||
798 | k += dev->video_mode.isoc_ctl.max_pkt_size; | ||
799 | } | ||
800 | } | ||
801 | |||
802 | init_waitqueue_head(&dma_q->wq); | ||
803 | |||
804 | |||
805 | /* submit urbs and enables IRQ */ | ||
806 | for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { | ||
807 | rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i], GFP_ATOMIC); | ||
808 | if (rc) { | ||
809 | cx231xx_err("submit of urb %i failed (error=%i)\n", i, | ||
810 | rc); | ||
811 | cx231xx_uninit_isoc(dev); | ||
812 | return rc; | ||
813 | } | ||
814 | } | ||
815 | |||
816 | cx231xx_capture_start(dev, 1, Raw_Video); | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | EXPORT_SYMBOL_GPL(cx231xx_init_isoc); | ||
821 | |||
822 | /************************************************************************************ | ||
823 | * Device Init/UnInit functions * | ||
824 | *************************************************************************************/ | ||
825 | int cx231xx_dev_init(struct cx231xx *dev) | ||
826 | { | ||
827 | int errCode = 0; | ||
828 | |||
829 | /* Initialize I2C bus */ | ||
830 | |||
831 | /* External Master 1 Bus */ | ||
832 | dev->i2c_bus[0].nr = 0; | ||
833 | dev->i2c_bus[0].dev = dev; | ||
834 | dev->i2c_bus[0].i2c_period = I2C_SPEED_1M; /* 1MHz */ | ||
835 | dev->i2c_bus[0].i2c_nostop = 0; | ||
836 | dev->i2c_bus[0].i2c_reserve = 0; | ||
837 | |||
838 | /* External Master 2 Bus */ | ||
839 | dev->i2c_bus[1].nr = 1; | ||
840 | dev->i2c_bus[1].dev = dev; | ||
841 | dev->i2c_bus[1].i2c_period = I2C_SPEED_1M; /* 1MHz */ | ||
842 | dev->i2c_bus[1].i2c_nostop = 0; | ||
843 | dev->i2c_bus[1].i2c_reserve = 0; | ||
844 | |||
845 | /* Internal Master 3 Bus */ | ||
846 | dev->i2c_bus[2].nr = 2; | ||
847 | dev->i2c_bus[2].dev = dev; | ||
848 | dev->i2c_bus[2].i2c_period = I2C_SPEED_400K; /* 400kHz */ | ||
849 | dev->i2c_bus[2].i2c_nostop = 0; | ||
850 | dev->i2c_bus[2].i2c_reserve = 0; | ||
851 | |||
852 | /* register I2C buses */ | ||
853 | cx231xx_i2c_register(&dev->i2c_bus[0]); | ||
854 | cx231xx_i2c_register(&dev->i2c_bus[1]); | ||
855 | cx231xx_i2c_register(&dev->i2c_bus[2]); | ||
856 | |||
857 | /* init hardware */ | ||
858 | /* Note : with out calling set power mode function, colibri can not be set up correctly */ | ||
859 | errCode = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); | ||
860 | if (errCode < 0) { | ||
861 | cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", | ||
862 | __func__, errCode); | ||
863 | return errCode; | ||
864 | } | ||
865 | |||
866 | /* initialize Colibri block */ | ||
867 | errCode = cx231xx_colibri_init_super_block(dev, 0x23c); | ||
868 | if (errCode < 0) { | ||
869 | cx231xx_errdev("%s: cx231xx_colibri init super block - errCode [%d]!\n", | ||
870 | __func__, errCode); | ||
871 | return errCode; | ||
872 | } | ||
873 | errCode = cx231xx_colibri_init_channels(dev); | ||
874 | if (errCode < 0) { | ||
875 | cx231xx_errdev("%s: cx231xx_colibri init channels - errCode [%d]!\n", | ||
876 | __func__, errCode); | ||
877 | return errCode; | ||
878 | } | ||
879 | |||
880 | /* Set DIF in By pass mode */ | ||
881 | errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); | ||
882 | if (errCode < 0) { | ||
883 | cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", | ||
884 | __func__, errCode); | ||
885 | return errCode; | ||
886 | } | ||
887 | |||
888 | /* flatiron related functions */ | ||
889 | errCode = cx231xx_flatiron_initialize(dev); | ||
890 | if (errCode < 0) { | ||
891 | cx231xx_errdev("%s: cx231xx_flatiron initialize - errCode [%d]!\n", | ||
892 | __func__, errCode); | ||
893 | return errCode; | ||
894 | } | ||
895 | |||
896 | /* init control pins */ | ||
897 | errCode = cx231xx_init_ctrl_pin_status(dev); | ||
898 | if (errCode < 0) { | ||
899 | cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n", | ||
900 | __func__, errCode); | ||
901 | return errCode; | ||
902 | } | ||
903 | |||
904 | /* set AGC mode to Analog */ | ||
905 | errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); | ||
906 | if (errCode < 0) { | ||
907 | cx231xx_errdev("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n", | ||
908 | __func__, errCode); | ||
909 | return errCode; | ||
910 | } | ||
911 | |||
912 | /* set all alternate settings to zero initially */ | ||
913 | cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); | ||
914 | cx231xx_set_alt_setting(dev, INDEX_VANC, 0); | ||
915 | cx231xx_set_alt_setting(dev, INDEX_HANC, 0); | ||
916 | if(dev->board.has_dvb) | ||
917 | cx231xx_set_alt_setting(dev, INDEX_TS1, 0); | ||
918 | |||
919 | /* set the I2C master port to 3 on channel 1 */ | ||
920 | errCode = cx231xx_enable_i2c_for_tuner(dev, I2C_3); | ||
921 | |||
922 | return errCode; | ||
923 | } | ||
924 | EXPORT_SYMBOL_GPL(cx231xx_dev_init); | ||
925 | |||
926 | void cx231xx_dev_uninit(struct cx231xx *dev) | ||
927 | { | ||
928 | /* Un Initialize I2C bus */ | ||
929 | cx231xx_i2c_unregister(&dev->i2c_bus[2]); | ||
930 | cx231xx_i2c_unregister(&dev->i2c_bus[1]); | ||
931 | cx231xx_i2c_unregister(&dev->i2c_bus[0]); | ||
932 | } | ||
933 | EXPORT_SYMBOL_GPL(cx231xx_dev_uninit); | ||
934 | |||
935 | |||
936 | /************************************************************************************ | ||
937 | * G P I O related functions * | ||
938 | *************************************************************************************/ | ||
939 | int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val, | ||
940 | u8 len, u8 request, u8 direction) | ||
941 | { | ||
942 | int status = 0; | ||
943 | VENDOR_REQUEST_IN ven_req; | ||
944 | |||
945 | /* Set wValue */ | ||
946 | ven_req.wValue = (u16)(gpio_bit>>16 & 0xffff); | ||
947 | |||
948 | /* set request */ | ||
949 | if(!request){ | ||
950 | if(direction) | ||
951 | ven_req.bRequest = VRT_GET_GPIO; /* 0x8 gpio */ | ||
952 | else | ||
953 | ven_req.bRequest = VRT_SET_GPIO; /* 0x9 gpio */ | ||
954 | } | ||
955 | else { | ||
956 | if(direction) | ||
957 | ven_req.bRequest = VRT_GET_GPIE; /* 0xa gpie */ | ||
958 | else | ||
959 | ven_req.bRequest = VRT_SET_GPIE; /* 0xb gpie */ | ||
960 | } | ||
961 | |||
962 | /* set index value */ | ||
963 | ven_req.wIndex = (u16)(gpio_bit & 0xffff); | ||
964 | |||
965 | /* set wLength value */ | ||
966 | ven_req.wLength = len; | ||
967 | |||
968 | /* set bData value */ | ||
969 | ven_req.bData = 0; | ||
970 | |||
971 | /* set the buffer for read / write */ | ||
972 | ven_req.pBuff = gpio_val; | ||
973 | |||
974 | /* set the direction */ | ||
975 | if(direction){ | ||
976 | ven_req.direction = USB_DIR_IN; | ||
977 | memset(ven_req.pBuff, 0x00, ven_req.wLength); | ||
978 | } | ||
979 | else | ||
980 | ven_req.direction = USB_DIR_OUT; | ||
981 | |||
982 | |||
983 | |||
984 | /* call common vendor command request */ | ||
985 | status = cx231xx_send_vendor_cmd(dev, &ven_req); | ||
986 | if (status < 0) | ||
987 | { | ||
988 | cx231xx_info("UsbInterface::sendCommand, output buffer failed with status -%d\n", status); | ||
989 | } | ||
990 | |||
991 | return status; | ||
992 | } | ||
993 | |||
994 | EXPORT_SYMBOL_GPL(cx231xx_send_gpio_cmd); | ||
995 | |||
996 | /************************************************************************************* | ||
997 | * C O N T R O L - Register R E A D / W R I T E functions * | ||
998 | *************************************************************************************/ | ||
999 | int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode) | ||
1000 | { | ||
1001 | u8 value[4] = {0x0, 0x0, 0x0, 0x0}; | ||
1002 | u32 tmp =0; | ||
1003 | int status = 0; | ||
1004 | |||
1005 | status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, address,value,4); | ||
1006 | if(status < 0) | ||
1007 | return status; | ||
1008 | |||
1009 | tmp = *((u32 *)value); | ||
1010 | tmp |= mode; | ||
1011 | |||
1012 | value[0]=(u8) tmp; | ||
1013 | value[1]=(u8)(tmp>>8); | ||
1014 | value[2]=(u8)(tmp>>16); | ||
1015 | value[3]=(u8)(tmp>>24); | ||
1016 | |||
1017 | status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, address,value,4); | ||
1018 | |||
1019 | return status; | ||
1020 | } | ||
1021 | |||
1022 | /************************************************************************************* | ||
1023 | * I 2 C Internal C O N T R O L functions * | ||
1024 | *************************************************************************************/ | ||
1025 | int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, | ||
1026 | u8 saddr_len, u32 *data, u8 data_len) | ||
1027 | { | ||
1028 | int status = 0; | ||
1029 | struct cx231xx_i2c_xfer_data req_data; | ||
1030 | u8 value[4] ={0,0,0,0}; | ||
1031 | |||
1032 | if(saddr_len == 0) | ||
1033 | saddr = 0; | ||
1034 | else if(saddr_len == 0) | ||
1035 | saddr &= 0xff; | ||
1036 | |||
1037 | /* prepare xfer_data struct */ | ||
1038 | req_data.dev_addr = dev_addr >> 1; | ||
1039 | req_data.direction = I2C_M_RD; | ||
1040 | req_data.saddr_len = saddr_len; | ||
1041 | req_data.saddr_dat = saddr; | ||
1042 | req_data.buf_size = data_len; | ||
1043 | req_data.p_buffer = (u8*)value; | ||
1044 | |||
1045 | /* usb send command */ | ||
1046 | status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); | ||
1047 | |||
1048 | if(status >= 0) | ||
1049 | { | ||
1050 | /* Copy the data read back to main buffer */ | ||
1051 | if(data_len == 1) | ||
1052 | *data = value[0]; | ||
1053 | else | ||
1054 | *data = value[0] | value[1] << 8 | value[2] << 16 | value[3] << 24; | ||
1055 | } | ||
1056 | |||
1057 | return status; | ||
1058 | } | ||
1059 | |||
1060 | int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, | ||
1061 | u8 saddr_len, u32 data, u8 data_len) | ||
1062 | { | ||
1063 | int status = 0; | ||
1064 | u8 value[4] ={0,0,0,0}; | ||
1065 | struct cx231xx_i2c_xfer_data req_data; | ||
1066 | |||
1067 | value[0]=(u8)data; | ||
1068 | value[1]=(u8)(data>>8); | ||
1069 | value[2]=(u8)(data>>16); | ||
1070 | value[3]=(u8)(data>>24); | ||
1071 | |||
1072 | if(saddr_len == 0) | ||
1073 | saddr = 0; | ||
1074 | else if(saddr_len == 0) | ||
1075 | saddr &= 0xff; | ||
1076 | |||
1077 | /* prepare xfer_data struct */ | ||
1078 | req_data.dev_addr = dev_addr >> 1; | ||
1079 | req_data.direction = 0; | ||
1080 | req_data.saddr_len = saddr_len; | ||
1081 | req_data.saddr_dat = saddr; | ||
1082 | req_data.buf_size = data_len; | ||
1083 | req_data.p_buffer = value; | ||
1084 | |||
1085 | /* usb send command */ | ||
1086 | status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); | ||
1087 | |||
1088 | return status; | ||
1089 | } | ||
1090 | |||
1091 | int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, u16 register_address, | ||
1092 | u8 bit_start,u8 bit_end, u32 value) | ||
1093 | { | ||
1094 | int status = 0; | ||
1095 | u32 tmp; | ||
1096 | u32 mask = 0; | ||
1097 | int i; | ||
1098 | |||
1099 | if (bit_start>(size-1) || bit_end>(size-1)) { | ||
1100 | return -1; | ||
1101 | } | ||
1102 | |||
1103 | if (size==8){ | ||
1104 | status = cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, &tmp, 1); | ||
1105 | } else { | ||
1106 | status = cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, &tmp, 4); | ||
1107 | } | ||
1108 | |||
1109 | if (status < 0) { | ||
1110 | return status; | ||
1111 | } | ||
1112 | |||
1113 | mask = 1<<bit_end; | ||
1114 | for (i=bit_end; i>bit_start&&i>0; i--) { | ||
1115 | mask = mask + (1<<(i-1)); | ||
1116 | } | ||
1117 | |||
1118 | value <<= bit_start; | ||
1119 | |||
1120 | if (size==8) | ||
1121 | { | ||
1122 | tmp &= ~mask; | ||
1123 | tmp |= value; | ||
1124 | tmp &= 0xff; | ||
1125 | status = cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, tmp, 1); | ||
1126 | } | ||
1127 | else | ||
1128 | { | ||
1129 | tmp &= ~mask; | ||
1130 | tmp |= value; | ||
1131 | status = cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, tmp, 4); | ||
1132 | } | ||
1133 | |||
1134 | return status; | ||
1135 | } | ||
1136 | |||
1137 | |||
1138 | |||
1139 | int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, | ||
1140 | u16 saddr, u32 mask, u32 value) | ||
1141 | { | ||
1142 | u32 temp; | ||
1143 | int status = 0; | ||
1144 | |||
1145 | status = cx231xx_read_i2c_data(dev, dev_addr, saddr, 2, &temp, 4); | ||
1146 | |||
1147 | if(status < 0) | ||
1148 | return status; | ||
1149 | |||
1150 | temp &= ~mask; | ||
1151 | temp |= value; | ||
1152 | |||
1153 | status = cx231xx_write_i2c_data(dev, dev_addr, saddr, 2, temp, 4); | ||
1154 | |||
1155 | return status; | ||
1156 | } | ||
1157 | |||
1158 | u32 cx231xx_set_field(u32 field_mask, u32 data) | ||
1159 | { | ||
1160 | u32 temp; | ||
1161 | |||
1162 | for (temp = field_mask; (temp & 1) == 0; temp >>= 1) { | ||
1163 | data <<= 1; | ||
1164 | } | ||
1165 | |||
1166 | return data; | ||
1167 | } | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c new file mode 100644 index 000000000000..46bdcecb4055 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c | |||
@@ -0,0 +1,565 @@ | |||
1 | /* | ||
2 | DVB device driver for cx231xx | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on em28xx driver | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/usb.h> | ||
24 | |||
25 | #include "cx231xx.h" | ||
26 | #include <media/v4l2-common.h> | ||
27 | #include <media/videobuf-vmalloc.h> | ||
28 | |||
29 | #include "xc5000.h" | ||
30 | #include "dvb_dummy_fe.h" | ||
31 | |||
32 | |||
33 | MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); | ||
34 | MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | |||
37 | static unsigned int debug; | ||
38 | module_param(debug, int, 0644); | ||
39 | MODULE_PARM_DESC(debug, "enable debug messages [dvb]"); | ||
40 | |||
41 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
42 | |||
43 | #define dprintk(level, fmt, arg...) do { \ | ||
44 | if (debug >= level) \ | ||
45 | printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ | ||
46 | } while (0) | ||
47 | |||
48 | #define CX231XX_DVB_NUM_BUFS 5 | ||
49 | #define CX231XX_DVB_MAX_PACKETSIZE 564 | ||
50 | #define CX231XX_DVB_MAX_PACKETS 64 | ||
51 | |||
52 | struct cx231xx_dvb { | ||
53 | struct dvb_frontend *frontend; | ||
54 | |||
55 | /* feed count management */ | ||
56 | struct mutex lock; | ||
57 | int nfeeds; | ||
58 | |||
59 | /* general boilerplate stuff */ | ||
60 | struct dvb_adapter adapter; | ||
61 | struct dvb_demux demux; | ||
62 | struct dmxdev dmxdev; | ||
63 | struct dmx_frontend fe_hw; | ||
64 | struct dmx_frontend fe_mem; | ||
65 | struct dvb_net net; | ||
66 | }; | ||
67 | |||
68 | |||
69 | static inline void print_err_status(struct cx231xx *dev, | ||
70 | int packet, int status) | ||
71 | { | ||
72 | char *errmsg = "Unknown"; | ||
73 | |||
74 | switch (status) { | ||
75 | case -ENOENT: | ||
76 | errmsg = "unlinked synchronuously"; | ||
77 | break; | ||
78 | case -ECONNRESET: | ||
79 | errmsg = "unlinked asynchronuously"; | ||
80 | break; | ||
81 | case -ENOSR: | ||
82 | errmsg = "Buffer error (overrun)"; | ||
83 | break; | ||
84 | case -EPIPE: | ||
85 | errmsg = "Stalled (device not responding)"; | ||
86 | break; | ||
87 | case -EOVERFLOW: | ||
88 | errmsg = "Babble (bad cable?)"; | ||
89 | break; | ||
90 | case -EPROTO: | ||
91 | errmsg = "Bit-stuff error (bad cable?)"; | ||
92 | break; | ||
93 | case -EILSEQ: | ||
94 | errmsg = "CRC/Timeout (could be anything)"; | ||
95 | break; | ||
96 | case -ETIME: | ||
97 | errmsg = "Device does not respond"; | ||
98 | break; | ||
99 | } | ||
100 | if (packet < 0) { | ||
101 | dprintk(1, "URB status %d [%s].\n", status, errmsg); | ||
102 | } else { | ||
103 | dprintk(1, "URB packet %d, status %d [%s].\n", | ||
104 | packet, status, errmsg); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb) | ||
109 | { | ||
110 | int i; | ||
111 | |||
112 | if (!dev) | ||
113 | return 0; | ||
114 | |||
115 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | ||
116 | return 0; | ||
117 | |||
118 | if (urb->status < 0) { | ||
119 | print_err_status(dev, -1, urb->status); | ||
120 | if (urb->status == -ENOENT) | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | for (i = 0; i < urb->number_of_packets; i++) { | ||
125 | int status = urb->iso_frame_desc[i].status; | ||
126 | |||
127 | if (status < 0) { | ||
128 | print_err_status(dev, i, status); | ||
129 | if (urb->iso_frame_desc[i].status != -EPROTO) | ||
130 | continue; | ||
131 | } | ||
132 | |||
133 | dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + | ||
134 | urb->iso_frame_desc[i].offset, | ||
135 | urb->iso_frame_desc[i].actual_length); | ||
136 | } | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int start_streaming(struct cx231xx_dvb *dvb) | ||
142 | { | ||
143 | int rc; | ||
144 | struct cx231xx *dev = dvb->adapter.priv; | ||
145 | |||
146 | usb_set_interface(dev->udev, 0, 1); | ||
147 | rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); | ||
148 | if (rc < 0) | ||
149 | return rc; | ||
150 | |||
151 | return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS, | ||
152 | CX231XX_DVB_NUM_BUFS, CX231XX_DVB_MAX_PACKETSIZE, | ||
153 | dvb_isoc_copy); | ||
154 | } | ||
155 | |||
156 | static int stop_streaming(struct cx231xx_dvb *dvb) | ||
157 | { | ||
158 | struct cx231xx *dev = dvb->adapter.priv; | ||
159 | |||
160 | cx231xx_uninit_isoc(dev); | ||
161 | |||
162 | cx231xx_set_mode(dev, CX231XX_SUSPEND); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int start_feed(struct dvb_demux_feed *feed) | ||
168 | { | ||
169 | struct dvb_demux *demux = feed->demux; | ||
170 | struct cx231xx_dvb *dvb = demux->priv; | ||
171 | int rc, ret; | ||
172 | |||
173 | if (!demux->dmx.frontend) | ||
174 | return -EINVAL; | ||
175 | |||
176 | mutex_lock(&dvb->lock); | ||
177 | dvb->nfeeds++; | ||
178 | rc = dvb->nfeeds; | ||
179 | |||
180 | if (dvb->nfeeds == 1) { | ||
181 | ret = start_streaming(dvb); | ||
182 | if (ret < 0) | ||
183 | rc = ret; | ||
184 | } | ||
185 | |||
186 | mutex_unlock(&dvb->lock); | ||
187 | return rc; | ||
188 | } | ||
189 | |||
190 | static int stop_feed(struct dvb_demux_feed *feed) | ||
191 | { | ||
192 | struct dvb_demux *demux = feed->demux; | ||
193 | struct cx231xx_dvb *dvb = demux->priv; | ||
194 | int err = 0; | ||
195 | |||
196 | mutex_lock(&dvb->lock); | ||
197 | dvb->nfeeds--; | ||
198 | |||
199 | if (0 == dvb->nfeeds) | ||
200 | err = stop_streaming(dvb); | ||
201 | |||
202 | mutex_unlock(&dvb->lock); | ||
203 | return err; | ||
204 | } | ||
205 | |||
206 | |||
207 | |||
208 | /* ------------------------------------------------------------------ */ | ||
209 | static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) | ||
210 | { | ||
211 | struct cx231xx *dev = fe->dvb->priv; | ||
212 | |||
213 | if (acquire) | ||
214 | return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); | ||
215 | else | ||
216 | return cx231xx_set_mode(dev, CX231XX_SUSPEND); | ||
217 | } | ||
218 | |||
219 | /* ------------------------------------------------------------------ */ | ||
220 | |||
221 | |||
222 | static struct xc5000_config cnxt_rde250_tunerconfig = { | ||
223 | .i2c_address = 0x61, | ||
224 | .if_khz = 5380, | ||
225 | }; | ||
226 | |||
227 | |||
228 | /* ------------------------------------------------------------------ */ | ||
229 | #if 0 | ||
230 | static int attach_xc5000(u8 addr, struct cx231xx *dev) | ||
231 | { | ||
232 | |||
233 | struct dvb_frontend *fe; | ||
234 | struct xc5000_config cfg; | ||
235 | |||
236 | memset(&cfg, 0, sizeof(cfg)); | ||
237 | cfg.i2c_adap = &dev->i2c_bus[1].i2c_adap; | ||
238 | cfg.i2c_addr = addr; | ||
239 | |||
240 | if (!dev->dvb->frontend) { | ||
241 | printk(KERN_ERR "%s/2: dvb frontend not attached. " | ||
242 | "Can't attach xc5000\n", | ||
243 | dev->name); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | |||
247 | fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg); | ||
248 | if (!fe) { | ||
249 | printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name); | ||
250 | dvb_frontend_detach(dev->dvb->frontend); | ||
251 | dev->dvb->frontend = NULL; | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name); | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | #endif | ||
260 | |||
261 | int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq ) | ||
262 | { | ||
263 | int status = 0; | ||
264 | |||
265 | if( (dev->dvb != NULL) && (dev->dvb->frontend != NULL) ){ | ||
266 | |||
267 | struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; | ||
268 | |||
269 | if(dops->set_analog_params != NULL) { | ||
270 | struct analog_parameters params; | ||
271 | |||
272 | params.frequency = freq; | ||
273 | params.std = dev->norm; | ||
274 | params.mode = 0 ; /* 0- Air; 1 - cable */ | ||
275 | /*params.audmode = ; */ | ||
276 | |||
277 | /* Set the analog parameters to set the frequency */ | ||
278 | cx231xx_info("Setting Frequency for XC5000\n"); | ||
279 | dops->set_analog_params(dev->dvb->frontend, ¶ms); | ||
280 | } | ||
281 | |||
282 | } | ||
283 | |||
284 | return status; | ||
285 | } | ||
286 | |||
287 | int cx231xx_reset_analog_tuner(struct cx231xx *dev) | ||
288 | { | ||
289 | int status = 0; | ||
290 | |||
291 | if( (dev->dvb != NULL) && (dev->dvb->frontend != NULL) ){ | ||
292 | |||
293 | struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; | ||
294 | |||
295 | if(dops->init != NULL && !dev->xc_fw_load_done) { | ||
296 | |||
297 | cx231xx_info("Reloading firmware for XC5000\n"); | ||
298 | status = dops->init(dev->dvb->frontend); | ||
299 | if(status == 0 ) { | ||
300 | dev->xc_fw_load_done = 1; | ||
301 | cx231xx_info("XC5000 firmware download completed\n"); | ||
302 | } else { | ||
303 | dev->xc_fw_load_done = 0; | ||
304 | cx231xx_info("XC5000 firmware download failed !!!\n"); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | } | ||
309 | |||
310 | return status; | ||
311 | } | ||
312 | |||
313 | |||
314 | /* ------------------------------------------------------------------ */ | ||
315 | |||
316 | static int register_dvb(struct cx231xx_dvb *dvb, | ||
317 | struct module *module, | ||
318 | struct cx231xx *dev, | ||
319 | struct device *device) | ||
320 | { | ||
321 | int result; | ||
322 | |||
323 | mutex_init(&dvb->lock); | ||
324 | |||
325 | /* register adapter */ | ||
326 | result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, | ||
327 | adapter_nr); | ||
328 | if (result < 0) { | ||
329 | printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", | ||
330 | dev->name, result); | ||
331 | goto fail_adapter; | ||
332 | } | ||
333 | |||
334 | /* Ensure all frontends negotiate bus access */ | ||
335 | dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; | ||
336 | |||
337 | dvb->adapter.priv = dev; | ||
338 | |||
339 | /* register frontend */ | ||
340 | result = dvb_register_frontend(&dvb->adapter, dvb->frontend); | ||
341 | if (result < 0) { | ||
342 | printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", | ||
343 | dev->name, result); | ||
344 | goto fail_frontend; | ||
345 | } | ||
346 | |||
347 | /* register demux stuff */ | ||
348 | dvb->demux.dmx.capabilities = | ||
349 | DMX_TS_FILTERING | DMX_SECTION_FILTERING | | ||
350 | DMX_MEMORY_BASED_FILTERING; | ||
351 | dvb->demux.priv = dvb; | ||
352 | dvb->demux.filternum = 256; | ||
353 | dvb->demux.feednum = 256; | ||
354 | dvb->demux.start_feed = start_feed; | ||
355 | dvb->demux.stop_feed = stop_feed; | ||
356 | |||
357 | result = dvb_dmx_init(&dvb->demux); | ||
358 | if (result < 0) { | ||
359 | printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", | ||
360 | dev->name, result); | ||
361 | goto fail_dmx; | ||
362 | } | ||
363 | |||
364 | dvb->dmxdev.filternum = 256; | ||
365 | dvb->dmxdev.demux = &dvb->demux.dmx; | ||
366 | dvb->dmxdev.capabilities = 0; | ||
367 | result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); | ||
368 | if (result < 0) { | ||
369 | printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", | ||
370 | dev->name, result); | ||
371 | goto fail_dmxdev; | ||
372 | } | ||
373 | |||
374 | dvb->fe_hw.source = DMX_FRONTEND_0; | ||
375 | result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); | ||
376 | if (result < 0) { | ||
377 | printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", | ||
378 | dev->name, result); | ||
379 | goto fail_fe_hw; | ||
380 | } | ||
381 | |||
382 | dvb->fe_mem.source = DMX_MEMORY_FE; | ||
383 | result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); | ||
384 | if (result < 0) { | ||
385 | printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", | ||
386 | dev->name, result); | ||
387 | goto fail_fe_mem; | ||
388 | } | ||
389 | |||
390 | result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); | ||
391 | if (result < 0) { | ||
392 | printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", | ||
393 | dev->name, result); | ||
394 | goto fail_fe_conn; | ||
395 | } | ||
396 | |||
397 | /* register network adapter */ | ||
398 | dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); | ||
399 | return 0; | ||
400 | |||
401 | fail_fe_conn: | ||
402 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); | ||
403 | fail_fe_mem: | ||
404 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); | ||
405 | fail_fe_hw: | ||
406 | dvb_dmxdev_release(&dvb->dmxdev); | ||
407 | fail_dmxdev: | ||
408 | dvb_dmx_release(&dvb->demux); | ||
409 | fail_dmx: | ||
410 | dvb_unregister_frontend(dvb->frontend); | ||
411 | fail_frontend: | ||
412 | dvb_frontend_detach(dvb->frontend); | ||
413 | dvb_unregister_adapter(&dvb->adapter); | ||
414 | fail_adapter: | ||
415 | return result; | ||
416 | } | ||
417 | |||
418 | static void unregister_dvb(struct cx231xx_dvb *dvb) | ||
419 | { | ||
420 | dvb_net_release(&dvb->net); | ||
421 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); | ||
422 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); | ||
423 | dvb_dmxdev_release(&dvb->dmxdev); | ||
424 | dvb_dmx_release(&dvb->demux); | ||
425 | dvb_unregister_frontend(dvb->frontend); | ||
426 | dvb_frontend_detach(dvb->frontend); | ||
427 | dvb_unregister_adapter(&dvb->adapter); | ||
428 | } | ||
429 | |||
430 | |||
431 | static int dvb_init(struct cx231xx *dev) | ||
432 | { | ||
433 | int result = 0; | ||
434 | struct cx231xx_dvb *dvb; | ||
435 | |||
436 | if (!dev->board.has_dvb) { | ||
437 | /* This device does not support the extension */ | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL); | ||
442 | |||
443 | if (dvb == NULL) { | ||
444 | printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n"); | ||
445 | return -ENOMEM; | ||
446 | } | ||
447 | dev->dvb = dvb; | ||
448 | dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq; | ||
449 | dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner; | ||
450 | |||
451 | cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); | ||
452 | /* init frontend */ | ||
453 | switch (dev->model) { | ||
454 | case CX231XX_BOARD_CNXT_RDE_250: | ||
455 | |||
456 | /* dev->dvb->frontend = dvb_attach(s5h1411_attach, | ||
457 | &dvico_s5h1411_config, | ||
458 | &dev->i2c_bus[1].i2c_adap);*/ | ||
459 | dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach); | ||
460 | |||
461 | if(dev->dvb->frontend == NULL) { | ||
462 | printk(DRIVER_NAME ": Failed to attach dummy front end\n"); | ||
463 | result = -EINVAL; | ||
464 | goto out_free; | ||
465 | } | ||
466 | |||
467 | /* define general-purpose callback pointer */ | ||
468 | dvb->frontend->callback = cx231xx_tuner_callback; | ||
469 | |||
470 | if(dvb_attach(xc5000_attach, dev->dvb->frontend, | ||
471 | &dev->i2c_bus[1].i2c_adap, | ||
472 | &cnxt_rde250_tunerconfig) < 0) { | ||
473 | result = -EINVAL; | ||
474 | goto out_free; | ||
475 | } | ||
476 | |||
477 | break; | ||
478 | case CX231XX_BOARD_CNXT_RDU_250: | ||
479 | |||
480 | dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach); | ||
481 | |||
482 | if(dev->dvb->frontend == NULL) { | ||
483 | printk(DRIVER_NAME ": Failed to attach dummy front end\n"); | ||
484 | result = -EINVAL; | ||
485 | goto out_free; | ||
486 | } | ||
487 | |||
488 | /* define general-purpose callback pointer */ | ||
489 | dvb->frontend->callback = cx231xx_tuner_callback; | ||
490 | |||
491 | if(dvb_attach(xc5000_attach, dev->dvb->frontend, | ||
492 | &dev->i2c_bus[1].i2c_adap, | ||
493 | &cnxt_rde250_tunerconfig) < 0) { | ||
494 | result = -EINVAL; | ||
495 | goto out_free; | ||
496 | } | ||
497 | break; | ||
498 | |||
499 | default: | ||
500 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" | ||
501 | " isn't supported yet\n", | ||
502 | dev->name); | ||
503 | break; | ||
504 | } | ||
505 | if (NULL == dvb->frontend) { | ||
506 | printk(KERN_ERR | ||
507 | "%s/2: frontend initialization failed\n", | ||
508 | dev->name); | ||
509 | result = -EINVAL; | ||
510 | goto out_free; | ||
511 | } | ||
512 | |||
513 | |||
514 | /* register everything */ | ||
515 | result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); | ||
516 | |||
517 | if (result < 0) | ||
518 | goto out_free; | ||
519 | |||
520 | cx231xx_set_mode(dev, CX231XX_SUSPEND); | ||
521 | printk(KERN_INFO "Successfully loaded cx231xx-dvb\n"); | ||
522 | return 0; | ||
523 | |||
524 | out_free: | ||
525 | cx231xx_set_mode(dev, CX231XX_SUSPEND); | ||
526 | kfree(dvb); | ||
527 | dev->dvb = NULL; | ||
528 | return result; | ||
529 | } | ||
530 | |||
531 | static int dvb_fini(struct cx231xx *dev) | ||
532 | { | ||
533 | if (!dev->board.has_dvb) { | ||
534 | /* This device does not support the extension */ | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | if (dev->dvb) { | ||
539 | unregister_dvb(dev->dvb); | ||
540 | dev->dvb = NULL; | ||
541 | } | ||
542 | |||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | static struct cx231xx_ops dvb_ops = { | ||
547 | .id = CX231XX_DVB, | ||
548 | .name = "Cx231xx dvb Extension", | ||
549 | .init = dvb_init, | ||
550 | .fini = dvb_fini, | ||
551 | }; | ||
552 | |||
553 | static int __init cx231xx_dvb_register(void) | ||
554 | { | ||
555 | return cx231xx_register_extension(&dvb_ops); | ||
556 | } | ||
557 | |||
558 | static void __exit cx231xx_dvb_unregister(void) | ||
559 | { | ||
560 | cx231xx_unregister_extension(&dvb_ops); | ||
561 | } | ||
562 | |||
563 | module_init(cx231xx_dvb_register); | ||
564 | module_exit(cx231xx_dvb_unregister); | ||
565 | |||
diff --git a/drivers/media/video/cx231xx/cx231xx-i2c.c b/drivers/media/video/cx231xx/cx231xx-i2c.c new file mode 100644 index 000000000000..d75ed6c3c8d7 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-i2c.c | |||
@@ -0,0 +1,577 @@ | |||
1 | /* | ||
2 | cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on em28xx driver | ||
6 | Based on Cx23885 driver | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <media/v4l2-common.h> | ||
28 | #include <media/tuner.h> | ||
29 | |||
30 | #include "cx231xx.h" | ||
31 | |||
32 | |||
33 | /* ----------------------------------------------------------- */ | ||
34 | |||
35 | static unsigned int i2c_scan; | ||
36 | module_param(i2c_scan, int, 0444); | ||
37 | MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); | ||
38 | |||
39 | static unsigned int i2c_debug; | ||
40 | module_param(i2c_debug, int, 0644); | ||
41 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | ||
42 | |||
43 | |||
44 | #define dprintk1(lvl, fmt, args...) \ | ||
45 | do { \ | ||
46 | if (i2c_debug >= lvl) { \ | ||
47 | printk(fmt, ##args); \ | ||
48 | } \ | ||
49 | } while (0) | ||
50 | |||
51 | #define dprintk2(lvl, fmt, args...) \ | ||
52 | do { \ | ||
53 | if (i2c_debug >= lvl) { \ | ||
54 | printk(KERN_DEBUG "%s at %s: " fmt, \ | ||
55 | dev->name, __func__ , ##args); \ | ||
56 | } \ | ||
57 | } while (0) | ||
58 | |||
59 | |||
60 | /* | ||
61 | * cx231xx_i2c_send_bytes() | ||
62 | */ | ||
63 | int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, | ||
64 | const struct i2c_msg *msg) | ||
65 | { | ||
66 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | ||
67 | struct cx231xx *dev = bus->dev; | ||
68 | struct cx231xx_i2c_xfer_data req_data; | ||
69 | int status = 0; | ||
70 | u16 size = 0; | ||
71 | u8 loop = 0; | ||
72 | u8 saddr_len = 1; | ||
73 | u8 *buf_ptr = NULL; | ||
74 | u16 saddr = 0; | ||
75 | u8 need_gpio = 0; | ||
76 | |||
77 | |||
78 | if( (bus->nr ==1) && (msg->addr == 0x61) && (dev->tuner_type == TUNER_XC5000) ) { | ||
79 | |||
80 | size = msg->len; | ||
81 | |||
82 | if( size == 2 ) { /* register write sub addr*/ | ||
83 | |||
84 | /* Just writing sub address will cause problem to XC5000 | ||
85 | So ignore the request */ | ||
86 | return 0; | ||
87 | |||
88 | } else if( size == 4 ) { /* register write with sub addr*/ | ||
89 | |||
90 | if(msg->len >= 2 ) | ||
91 | saddr = msg->buf[0] << 8 | msg->buf[1]; | ||
92 | else if ( msg->len == 1 ) | ||
93 | saddr = msg->buf[0]; | ||
94 | |||
95 | switch(saddr) { | ||
96 | case 0x0000: /* start tuner calibration mode */ | ||
97 | need_gpio = 1; | ||
98 | dev->xc_fw_load_done = 1; /* FW Loading is done */ | ||
99 | break; | ||
100 | case 0x000D: /* Set signal source */ | ||
101 | case 0x0001: /* Set TV standard - Video */ | ||
102 | case 0x0002: /* Set TV standard - Audio */ | ||
103 | case 0x0003: /* Set RF Frequency */ | ||
104 | need_gpio = 1; | ||
105 | break; | ||
106 | default: | ||
107 | if(dev->xc_fw_load_done) | ||
108 | need_gpio = 1; | ||
109 | break; | ||
110 | } | ||
111 | |||
112 | if(need_gpio ) { | ||
113 | dprintk1(1, " GPIO W R I T E : addr 0x%x, len %d, saddr 0x%x\n", | ||
114 | msg->addr, msg->len, saddr); | ||
115 | |||
116 | return dev->cx231xx_gpio_i2c_write(dev, msg->addr, msg->buf, msg->len); | ||
117 | } | ||
118 | |||
119 | } | ||
120 | |||
121 | /* special case for Xc5000 tuner case */ | ||
122 | saddr_len = 1; | ||
123 | |||
124 | /* adjust the length to correct length */ | ||
125 | size -= saddr_len; | ||
126 | buf_ptr = (u8*) (msg->buf + 1 ); | ||
127 | |||
128 | do { | ||
129 | /* prepare xfer_data struct */ | ||
130 | req_data.dev_addr = msg->addr; | ||
131 | req_data.direction = msg->flags; | ||
132 | req_data.saddr_len = saddr_len; | ||
133 | req_data.saddr_dat = msg->buf[0]; | ||
134 | req_data.buf_size = size > 16 ? 16: size; | ||
135 | req_data.p_buffer = (u8*)(buf_ptr + loop * 16); | ||
136 | |||
137 | bus->i2c_nostop = (size > 16) ? 1: 0; | ||
138 | bus->i2c_reserve = (loop == 0) ? 0: 1; | ||
139 | |||
140 | /* usb send command */ | ||
141 | status = dev->cx231xx_send_usb_command(bus, &req_data); | ||
142 | loop++; | ||
143 | |||
144 | if( size >= 16 ) | ||
145 | size -= 16; | ||
146 | else | ||
147 | size = 0; | ||
148 | |||
149 | }while( size > 0 ); | ||
150 | |||
151 | bus->i2c_nostop = 0; | ||
152 | bus->i2c_reserve = 0; | ||
153 | |||
154 | } else { /* regular case */ | ||
155 | |||
156 | /* prepare xfer_data struct */ | ||
157 | req_data.dev_addr = msg->addr; | ||
158 | req_data.direction = msg->flags; | ||
159 | req_data.saddr_len = 0; | ||
160 | req_data.saddr_dat = 0; | ||
161 | req_data.buf_size = msg->len; | ||
162 | req_data.p_buffer = msg->buf; | ||
163 | |||
164 | /* usb send command */ | ||
165 | status = dev->cx231xx_send_usb_command(bus, &req_data); | ||
166 | } | ||
167 | |||
168 | return status < 0 ? status: 0; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * cx231xx_i2c_recv_bytes() | ||
173 | * read a byte from the i2c device | ||
174 | */ | ||
175 | static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, | ||
176 | const struct i2c_msg *msg) | ||
177 | { | ||
178 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | ||
179 | struct cx231xx *dev = bus->dev; | ||
180 | struct cx231xx_i2c_xfer_data req_data; | ||
181 | int status = 0; | ||
182 | u16 saddr = 0; | ||
183 | u8 need_gpio = 0; | ||
184 | |||
185 | if((bus->nr ==1) && (msg->addr == 0x61) && dev->tuner_type == TUNER_XC5000) { | ||
186 | |||
187 | if(msg->len == 2 ) | ||
188 | saddr = msg->buf[0] << 8 | msg->buf[1]; | ||
189 | else if ( msg->len == 1 ) | ||
190 | saddr = msg->buf[0]; | ||
191 | |||
192 | if( dev->xc_fw_load_done) { | ||
193 | |||
194 | switch(saddr) { | ||
195 | case 0x0009: /* BUSY check */ | ||
196 | dprintk1(1, " GPIO R E A D : Special case BUSY check \n"); | ||
197 | /* Try to read BUSY register, just set it to zero */ | ||
198 | msg->buf[0] = 0; | ||
199 | if(msg->len == 2 ) | ||
200 | msg->buf[1] = 0; | ||
201 | return 0; | ||
202 | case 0x0004: /* read Lock status */ | ||
203 | need_gpio = 1; | ||
204 | break; | ||
205 | |||
206 | } | ||
207 | |||
208 | if(need_gpio) { | ||
209 | /* this is a special case to handle Xceive tuner clock stretch issue | ||
210 | with gpio based I2C interface */ | ||
211 | dprintk1(1, " GPIO R E A D : addr 0x%x, len %d, saddr 0x%x\n", | ||
212 | msg->addr, msg->len, msg->buf[0] << 8| msg->buf[1]); | ||
213 | status = dev->cx231xx_gpio_i2c_write(dev, msg->addr, msg->buf, msg->len); | ||
214 | status = dev->cx231xx_gpio_i2c_read(dev, msg->addr, msg->buf, msg->len); | ||
215 | return status; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* prepare xfer_data struct */ | ||
220 | req_data.dev_addr = msg->addr; | ||
221 | req_data.direction = msg->flags; | ||
222 | req_data.saddr_len = msg->len; | ||
223 | req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1]; | ||
224 | req_data.buf_size = msg->len; | ||
225 | req_data.p_buffer = msg->buf; | ||
226 | |||
227 | /* usb send command */ | ||
228 | status = dev->cx231xx_send_usb_command(bus, &req_data); | ||
229 | |||
230 | } else { | ||
231 | |||
232 | /* prepare xfer_data struct */ | ||
233 | req_data.dev_addr = msg->addr; | ||
234 | req_data.direction = msg->flags; | ||
235 | req_data.saddr_len = 0; | ||
236 | req_data.saddr_dat = 0; | ||
237 | req_data.buf_size = msg->len; | ||
238 | req_data.p_buffer = msg->buf; | ||
239 | |||
240 | /* usb send command */ | ||
241 | status = dev->cx231xx_send_usb_command(bus, &req_data); | ||
242 | } | ||
243 | |||
244 | return status < 0 ? status: 0; | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * cx231xx_i2c_recv_bytes_with_saddr() | ||
249 | * read a byte from the i2c device | ||
250 | */ | ||
251 | static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap, | ||
252 | const struct i2c_msg *msg1, const struct i2c_msg *msg2) | ||
253 | { | ||
254 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | ||
255 | struct cx231xx *dev = bus->dev; | ||
256 | struct cx231xx_i2c_xfer_data req_data; | ||
257 | int status = 0; | ||
258 | u16 saddr = 0; | ||
259 | u8 need_gpio = 0; | ||
260 | |||
261 | if(msg1->len == 2 ) | ||
262 | saddr = msg1->buf[0] << 8 | msg1->buf[1]; | ||
263 | else if ( msg1->len == 1 ) | ||
264 | saddr = msg1->buf[0]; | ||
265 | |||
266 | if ( (bus->nr ==1) && (msg2->addr == 0x61) && dev->tuner_type == TUNER_XC5000) { | ||
267 | |||
268 | if( (msg2->len < 16) ) { | ||
269 | |||
270 | dprintk1(1, " i2c_read : addr 0x%x, len %d, subaddr 0x%x, leng %d\n", | ||
271 | msg2->addr, msg2->len, saddr, msg1->len); | ||
272 | |||
273 | switch(saddr) { | ||
274 | case 0x0008: /* read FW load status */ | ||
275 | need_gpio = 1; | ||
276 | break; | ||
277 | case 0x0004: /* read Lock status */ | ||
278 | need_gpio = 1; | ||
279 | break; | ||
280 | } | ||
281 | |||
282 | if(need_gpio ) { | ||
283 | status = dev->cx231xx_gpio_i2c_write(dev, msg1->addr, msg1->buf, msg1->len); | ||
284 | status = dev->cx231xx_gpio_i2c_read(dev, msg2->addr, msg2->buf, msg2->len); | ||
285 | return status; | ||
286 | } | ||
287 | } | ||
288 | } | ||
289 | |||
290 | /* prepare xfer_data struct */ | ||
291 | req_data.dev_addr = msg2->addr; | ||
292 | req_data.direction = msg2->flags; | ||
293 | req_data.saddr_len = msg1->len; | ||
294 | req_data.saddr_dat = saddr; | ||
295 | req_data.buf_size = msg2->len; | ||
296 | req_data.p_buffer = msg2->buf; | ||
297 | |||
298 | /* usb send command */ | ||
299 | status = dev->cx231xx_send_usb_command(bus, &req_data); | ||
300 | |||
301 | return status < 0 ? status: 0; | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * cx231xx_i2c_check_for_device() | ||
306 | * check if there is a i2c_device at the supplied address | ||
307 | */ | ||
308 | static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap, | ||
309 | const struct i2c_msg *msg) | ||
310 | { | ||
311 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | ||
312 | struct cx231xx *dev = bus->dev; | ||
313 | struct cx231xx_i2c_xfer_data req_data; | ||
314 | int status = 0; | ||
315 | |||
316 | /* prepare xfer_data struct */ | ||
317 | req_data.dev_addr = msg->addr; | ||
318 | req_data.direction = msg->flags; | ||
319 | req_data.saddr_len = 0; | ||
320 | req_data.saddr_dat = 0; | ||
321 | req_data.buf_size = 0; | ||
322 | req_data.p_buffer = NULL; | ||
323 | |||
324 | /* usb send command */ | ||
325 | status = dev->cx231xx_send_usb_command(bus, &req_data); | ||
326 | |||
327 | return status < 0 ? status: 0; | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * cx231xx_i2c_xfer() | ||
332 | * the main i2c transfer function | ||
333 | */ | ||
334 | static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, | ||
335 | struct i2c_msg msgs[], int num) | ||
336 | { | ||
337 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | ||
338 | struct cx231xx *dev = bus->dev; | ||
339 | int addr, rc, i, byte; | ||
340 | |||
341 | if (num <= 0) | ||
342 | return 0; | ||
343 | |||
344 | for (i = 0; i < num; i++) { | ||
345 | |||
346 | addr = msgs[i].addr >> 1; | ||
347 | |||
348 | dprintk2(2, "%s %s addr=%x len=%d:", | ||
349 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", | ||
350 | i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); | ||
351 | if (!msgs[i].len) { /* no len: check only for device presence */ | ||
352 | rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]); | ||
353 | if (rc < 0) { | ||
354 | dprintk2(2, " no device\n"); | ||
355 | return rc; | ||
356 | } | ||
357 | |||
358 | } else if (msgs[i].flags & I2C_M_RD) { | ||
359 | /* read bytes */ | ||
360 | rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]); | ||
361 | if (i2c_debug >= 2) { | ||
362 | for (byte = 0; byte < msgs[i].len; byte++) | ||
363 | printk(" %02x", msgs[i].buf[byte]); | ||
364 | } | ||
365 | } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && | ||
366 | msgs[i].addr == msgs[i + 1].addr && (msgs[i].len <= 2) && (bus->nr < 2)) { | ||
367 | /* read bytes */ | ||
368 | rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, &msgs[i], &msgs[i+1]); | ||
369 | if (i2c_debug >= 2) { | ||
370 | for (byte = 0; byte < msgs[i].len; byte++) | ||
371 | printk(" %02x", msgs[i].buf[byte]); | ||
372 | } | ||
373 | i++; | ||
374 | } else { | ||
375 | /* write bytes */ | ||
376 | if (i2c_debug >= 2) { | ||
377 | for (byte = 0; byte < msgs[i].len; byte++) | ||
378 | printk(" %02x", msgs[i].buf[byte]); | ||
379 | } | ||
380 | rc = cx231xx_i2c_send_bytes(i2c_adap,&msgs[i]); | ||
381 | } | ||
382 | if (rc < 0) | ||
383 | goto err; | ||
384 | if (i2c_debug >= 2) | ||
385 | printk("\n"); | ||
386 | } | ||
387 | |||
388 | return num; | ||
389 | err: | ||
390 | dprintk2(2, " ERROR: %i\n", rc); | ||
391 | return rc; | ||
392 | } | ||
393 | |||
394 | /* ----------------------------------------------------------- */ | ||
395 | |||
396 | /* | ||
397 | * functionality() | ||
398 | */ | ||
399 | static u32 functionality(struct i2c_adapter *adap) | ||
400 | { | ||
401 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * attach_inform() | ||
406 | * gets called when a device attaches to the i2c bus | ||
407 | * does some basic configuration | ||
408 | */ | ||
409 | static int attach_inform(struct i2c_client *client) | ||
410 | { | ||
411 | struct cx231xx_i2c *bus = i2c_get_adapdata(client->adapter); | ||
412 | struct cx231xx *dev = bus->dev; | ||
413 | |||
414 | switch (client->addr << 1) { | ||
415 | case 0x32: | ||
416 | dprintk1(1, "attach_inform: Geminit III detected.\n"); | ||
417 | break; | ||
418 | case 0x02: | ||
419 | dprintk1(1, "attach_inform: Acquarius detected.\n"); | ||
420 | break; | ||
421 | case 0xa0: | ||
422 | dprintk1(1, "attach_inform: eeprom detected.\n"); | ||
423 | break; | ||
424 | case 0x60: | ||
425 | dprintk1(1, "attach_inform: Colibri detected.\n"); | ||
426 | break; | ||
427 | case 0x8e: | ||
428 | { | ||
429 | struct IR_i2c *ir = i2c_get_clientdata(client); | ||
430 | dprintk1(1, "attach_inform: IR detected (%s).\n", | ||
431 | ir->phys); | ||
432 | cx231xx_set_ir(dev, ir); | ||
433 | break; | ||
434 | } | ||
435 | case 0x80: | ||
436 | case 0x88: | ||
437 | dprintk1(1, "attach_inform: Hammerhead detected.\n"); | ||
438 | break; | ||
439 | |||
440 | default: | ||
441 | if (!dev->tuner_addr) | ||
442 | dev->tuner_addr = client->addr; | ||
443 | |||
444 | dprintk1(1, "attach inform: detected I2C address %x\n", | ||
445 | client->addr << 1); | ||
446 | } | ||
447 | |||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static int detach_inform(struct i2c_client *client) | ||
452 | { | ||
453 | dprintk1(1, "i2c detach [client=%s]\n", client->name); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | |||
458 | static struct i2c_algorithm cx231xx_algo = { | ||
459 | .master_xfer = cx231xx_i2c_xfer, | ||
460 | .functionality = functionality, | ||
461 | }; | ||
462 | |||
463 | static struct i2c_adapter cx231xx_adap_template = { | ||
464 | .owner = THIS_MODULE, | ||
465 | .class = I2C_CLASS_TV_ANALOG, | ||
466 | .name = "cx231xx", | ||
467 | .id = I2C_HW_B_CX231XX, | ||
468 | .algo = &cx231xx_algo, | ||
469 | .client_register = attach_inform, | ||
470 | .client_unregister = detach_inform, | ||
471 | }; | ||
472 | |||
473 | static struct i2c_client cx231xx_client_template = { | ||
474 | .name = "cx231xx internal", | ||
475 | }; | ||
476 | |||
477 | /* ----------------------------------------------------------- */ | ||
478 | |||
479 | /* | ||
480 | * i2c_devs | ||
481 | * incomplete list of known devices | ||
482 | */ | ||
483 | static char *i2c_devs[128] = { | ||
484 | [0x60 >> 1] = "colibri", | ||
485 | [0x88 >> 1] = "hammerhead", | ||
486 | [0x8e >> 1] = "CIR", | ||
487 | [0x32 >> 1] = "GeminiIII", | ||
488 | [0x02 >> 1] = "Aquarius", | ||
489 | [0xa0 >> 1] = "eeprom", | ||
490 | [0xc0 >> 1] = "tuner/XC3028", | ||
491 | [0xc2 >> 1] = "tuner/XC5000", | ||
492 | }; | ||
493 | |||
494 | /* | ||
495 | * cx231xx_do_i2c_scan() | ||
496 | * check i2c address range for devices | ||
497 | */ | ||
498 | void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c) | ||
499 | { | ||
500 | unsigned char buf; | ||
501 | int i, rc; | ||
502 | |||
503 | cx231xx_info(": Checking for I2C devices ..\n"); | ||
504 | for (i = 0; i < 128; i++) { | ||
505 | c->addr = i; | ||
506 | rc = i2c_master_recv(c, &buf, 0); | ||
507 | if (rc < 0) | ||
508 | continue; | ||
509 | cx231xx_info("%s: i2c scan: found device @ 0x%x [%s]\n", | ||
510 | dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); | ||
511 | } | ||
512 | cx231xx_info(": Completed Checking for I2C devices.\n"); | ||
513 | } | ||
514 | |||
515 | /* | ||
516 | * cx231xx_i2c_call_clients() | ||
517 | * send commands to all attached i2c devices | ||
518 | */ | ||
519 | void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, void *arg) | ||
520 | { | ||
521 | /* struct cx231xx *dev = bus->dev; */ | ||
522 | |||
523 | BUG_ON(NULL == bus->i2c_adap.algo_data); | ||
524 | i2c_clients_command(&bus->i2c_adap, cmd, arg); | ||
525 | } | ||
526 | |||
527 | /* | ||
528 | * cx231xx_i2c_register() | ||
529 | * register i2c bus | ||
530 | */ | ||
531 | int cx231xx_i2c_register(struct cx231xx_i2c *bus) | ||
532 | { | ||
533 | struct cx231xx *dev = bus->dev; | ||
534 | |||
535 | BUG_ON(!dev->cx231xx_send_usb_command); | ||
536 | |||
537 | cx231xx_info("%s(bus = %d)\n", __func__, bus->nr); | ||
538 | |||
539 | memcpy(&bus->i2c_adap, &cx231xx_adap_template, | ||
540 | sizeof(bus->i2c_adap)); | ||
541 | memcpy(&bus->i2c_algo, &cx231xx_algo, | ||
542 | sizeof(bus->i2c_algo)); | ||
543 | memcpy(&bus->i2c_client, &cx231xx_client_template, | ||
544 | sizeof(bus->i2c_client)); | ||
545 | |||
546 | bus->i2c_adap.dev.parent = &dev->udev->dev; | ||
547 | |||
548 | strlcpy(bus->i2c_adap.name, bus->dev->name, | ||
549 | sizeof(bus->i2c_adap.name)); | ||
550 | |||
551 | bus->i2c_algo.data = bus; | ||
552 | bus->i2c_adap.algo_data = bus; | ||
553 | i2c_set_adapdata(&bus->i2c_adap, bus); | ||
554 | i2c_add_adapter(&bus->i2c_adap); | ||
555 | |||
556 | bus->i2c_client.adapter = &bus->i2c_adap; | ||
557 | |||
558 | if (0 == bus->i2c_rc) { | ||
559 | cx231xx_info("%s: i2c bus %d registered\n", dev->name, bus->nr); | ||
560 | if (i2c_scan) | ||
561 | cx231xx_do_i2c_scan(dev, &bus->i2c_client); | ||
562 | } else | ||
563 | cx231xx_warn("%s: i2c bus %d register FAILED\n", | ||
564 | dev->name, bus->nr); | ||
565 | |||
566 | return bus->i2c_rc; | ||
567 | } | ||
568 | |||
569 | /* | ||
570 | * cx231xx_i2c_unregister() | ||
571 | * unregister i2c_bus | ||
572 | */ | ||
573 | int cx231xx_i2c_unregister(struct cx231xx_i2c *bus) | ||
574 | { | ||
575 | i2c_del_adapter(&bus->i2c_adap); | ||
576 | return 0; | ||
577 | } | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c new file mode 100644 index 000000000000..fdc37a838d10 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-input.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | handle cx231xx IR remotes via linux kernel input layer. | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on em28xx driver | ||
6 | |||
7 | < This is a place holder for IR now.> | ||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/input.h> | ||
29 | #include <linux/usb.h> | ||
30 | |||
31 | #include "cx231xx.h" | ||
32 | |||
33 | |||
34 | static unsigned int ir_debug; | ||
35 | module_param(ir_debug, int, 0644); | ||
36 | MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); | ||
37 | |||
38 | #define i2cdprintk(fmt, arg...) \ | ||
39 | if (ir_debug) { \ | ||
40 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \ | ||
41 | } | ||
42 | |||
43 | #define dprintk(fmt, arg...) \ | ||
44 | if (ir_debug) { \ | ||
45 | printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ | ||
46 | } | ||
47 | |||
48 | /********************************************************** | ||
49 | Polling structure used by cx231xx IR's | ||
50 | **********************************************************/ | ||
51 | |||
52 | struct cx231xx_ir_poll_result { | ||
53 | unsigned int toggle_bit:1; | ||
54 | unsigned int read_count:7; | ||
55 | u8 rc_address; | ||
56 | u8 rc_data[4]; | ||
57 | }; | ||
58 | |||
59 | struct cx231xx_IR { | ||
60 | struct cx231xx *dev; | ||
61 | struct input_dev *input; | ||
62 | struct ir_input_state ir; | ||
63 | char name[32]; | ||
64 | char phys[32]; | ||
65 | |||
66 | /* poll external decoder */ | ||
67 | int polling; | ||
68 | struct work_struct work; | ||
69 | struct timer_list timer; | ||
70 | unsigned int last_toggle:1; | ||
71 | unsigned int last_readcount; | ||
72 | unsigned int repeat_interval; | ||
73 | |||
74 | int (*get_key)(struct cx231xx_IR *, struct cx231xx_ir_poll_result *); | ||
75 | }; | ||
76 | |||
77 | |||
78 | |||
79 | /********************************************************** | ||
80 | Polling code for cx231xx | ||
81 | **********************************************************/ | ||
82 | |||
83 | static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) | ||
84 | { | ||
85 | int result; | ||
86 | int do_sendkey = 0; | ||
87 | struct cx231xx_ir_poll_result poll_result; | ||
88 | |||
89 | /* read the registers containing the IR status */ | ||
90 | result = ir->get_key(ir, &poll_result); | ||
91 | if (result < 0) { | ||
92 | dprintk("ir->get_key() failed %d\n", result); | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x\n", | ||
97 | poll_result.toggle_bit, poll_result.read_count, | ||
98 | ir->last_readcount, poll_result.rc_data[0]); | ||
99 | |||
100 | if (ir->dev->chip_id == CHIP_ID_EM2874) { | ||
101 | /* The em2874 clears the readcount field every time the | ||
102 | register is read. The em2860/2880 datasheet says that it | ||
103 | is supposed to clear the readcount, but it doesn't. So with | ||
104 | the em2874, we are looking for a non-zero read count as | ||
105 | opposed to a readcount that is incrementing */ | ||
106 | ir->last_readcount = 0; | ||
107 | } | ||
108 | |||
109 | if (poll_result.read_count == 0) { | ||
110 | /* The button has not been pressed since the last read */ | ||
111 | } else if (ir->last_toggle != poll_result.toggle_bit) { | ||
112 | /* A button has been pressed */ | ||
113 | dprintk("button has been pressed\n"); | ||
114 | ir->last_toggle = poll_result.toggle_bit; | ||
115 | ir->repeat_interval = 0; | ||
116 | do_sendkey = 1; | ||
117 | } else if (poll_result.toggle_bit == ir->last_toggle && | ||
118 | poll_result.read_count > 0 && | ||
119 | poll_result.read_count != ir->last_readcount) { | ||
120 | /* The button is still being held down */ | ||
121 | dprintk("button being held down\n"); | ||
122 | |||
123 | /* Debouncer for first keypress */ | ||
124 | if (ir->repeat_interval++ > 9) { | ||
125 | /* Start repeating after 1 second */ | ||
126 | do_sendkey = 1; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | if (do_sendkey) { | ||
131 | dprintk("sending keypress\n"); | ||
132 | ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0], | ||
133 | poll_result.rc_data[0]); | ||
134 | ir_input_nokey(ir->input, &ir->ir); | ||
135 | } | ||
136 | |||
137 | ir->last_readcount = poll_result.read_count; | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | static void ir_timer(unsigned long data) | ||
142 | { | ||
143 | struct cx231xx_IR *ir = (struct cx231xx_IR *)data; | ||
144 | |||
145 | schedule_work(&ir->work); | ||
146 | } | ||
147 | |||
148 | static void cx231xx_ir_work(struct work_struct *work) | ||
149 | { | ||
150 | struct cx231xx_IR *ir = container_of(work, struct cx231xx_IR, work); | ||
151 | |||
152 | cx231xx_ir_handle_key(ir); | ||
153 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); | ||
154 | } | ||
155 | |||
156 | void cx231xx_ir_start(struct cx231xx_IR *ir) | ||
157 | { | ||
158 | setup_timer(&ir->timer, ir_timer, (unsigned long)ir); | ||
159 | INIT_WORK(&ir->work, cx231xx_ir_work); | ||
160 | schedule_work(&ir->work); | ||
161 | } | ||
162 | |||
163 | static void cx231xx_ir_stop(struct cx231xx_IR *ir) | ||
164 | { | ||
165 | del_timer_sync(&ir->timer); | ||
166 | flush_scheduled_work(); | ||
167 | } | ||
168 | |||
169 | int cx231xx_ir_init(struct cx231xx *dev) | ||
170 | { | ||
171 | struct cx231xx_IR *ir; | ||
172 | struct input_dev *input_dev; | ||
173 | u8 ir_config; | ||
174 | int err = -ENOMEM; | ||
175 | |||
176 | if (dev->board.ir_codes == NULL) { | ||
177 | /* No remote control support */ | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
182 | input_dev = input_allocate_device(); | ||
183 | if (!ir || !input_dev) | ||
184 | goto err_out_free; | ||
185 | |||
186 | ir->input = input_dev; | ||
187 | |||
188 | /* Setup the proper handler based on the chip */ | ||
189 | switch (dev->chip_id) { | ||
190 | default: | ||
191 | printk("Unrecognized cx231xx chip id: IR not supported\n"); | ||
192 | goto err_out_free; | ||
193 | } | ||
194 | |||
195 | /* This is how often we ask the chip for IR information */ | ||
196 | ir->polling = 100; /* ms */ | ||
197 | |||
198 | /* init input device */ | ||
199 | snprintf(ir->name, sizeof(ir->name), "cx231xx IR (%s)", | ||
200 | dev->name); | ||
201 | |||
202 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | ||
203 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | ||
204 | |||
205 | ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, dev->board.ir_codes); | ||
206 | input_dev->name = ir->name; | ||
207 | input_dev->phys = ir->phys; | ||
208 | input_dev->id.bustype = BUS_USB; | ||
209 | input_dev->id.version = 1; | ||
210 | input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); | ||
211 | input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); | ||
212 | |||
213 | input_dev->dev.parent = &dev->udev->dev; | ||
214 | /* record handles to ourself */ | ||
215 | ir->dev = dev; | ||
216 | dev->ir = ir; | ||
217 | |||
218 | cx231xx_ir_start(ir); | ||
219 | |||
220 | /* all done */ | ||
221 | err = input_register_device(ir->input); | ||
222 | if (err) | ||
223 | goto err_out_stop; | ||
224 | |||
225 | return 0; | ||
226 | err_out_stop: | ||
227 | cx231xx_ir_stop(ir); | ||
228 | dev->ir = NULL; | ||
229 | err_out_free: | ||
230 | input_free_device(input_dev); | ||
231 | kfree(ir); | ||
232 | return err; | ||
233 | } | ||
234 | |||
235 | int cx231xx_ir_fini(struct cx231xx *dev) | ||
236 | { | ||
237 | struct cx231xx_IR *ir = dev->ir; | ||
238 | |||
239 | /* skip detach on non attached boards */ | ||
240 | if (!ir) | ||
241 | return 0; | ||
242 | |||
243 | cx231xx_ir_stop(ir); | ||
244 | input_unregister_device(ir->input); | ||
245 | kfree(ir); | ||
246 | |||
247 | /* done */ | ||
248 | dev->ir = NULL; | ||
249 | return 0; | ||
250 | } | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-reg.h b/drivers/media/video/cx231xx/cx231xx-reg.h new file mode 100644 index 000000000000..ef24781418e4 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-reg.h | |||
@@ -0,0 +1,1574 @@ | |||
1 | /* | ||
2 | cx231xx-reg.h - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef _CX231XX_REG_H | ||
22 | #define _CX231XX_REG_H | ||
23 | |||
24 | /***************************************************************************** | ||
25 | * VBI codes * | ||
26 | *****************************************************************************/ | ||
27 | |||
28 | #define SAV_ACTIVE_VIDEO_FIELD1 0x80 | ||
29 | #define EAV_ACTIVE_VIDEO_FIELD1 0x90 | ||
30 | |||
31 | #define SAV_ACTIVE_VIDEO_FIELD2 0xC0 | ||
32 | #define EAV_ACTIVE_VIDEO_FIELD2 0xD0 | ||
33 | |||
34 | #define SAV_VBLANK_FIELD1 0xA0 | ||
35 | #define EAV_VBLANK_FIELD1 0xB0 | ||
36 | |||
37 | #define SAV_VBLANK_FIELD2 0xE0 | ||
38 | #define EAV_VBLANK_FIELD2 0xF0 | ||
39 | |||
40 | #define SAV_VBI_FIELD1 0x20 | ||
41 | #define EAV_VBI_FIELD1 0x30 | ||
42 | |||
43 | #define SAV_VBI_FIELD2 0x60 | ||
44 | #define EAV_VBI_FIELD2 0x70 | ||
45 | |||
46 | /*****************************************************************************/ | ||
47 | /* Audio ADC Registers */ | ||
48 | #define CH_PWR_CTRL1 0x0000000E | ||
49 | #define CH_PWR_CTRL2 0x0000000F | ||
50 | /*****************************************************************************/ | ||
51 | |||
52 | #define HOST_REG1 0x000 | ||
53 | #define FLD_FORCE_CHIP_SEL 0x80 | ||
54 | #define FLD_AUTO_INC_DIS 0x20 | ||
55 | #define FLD_PREFETCH_EN 0x10 | ||
56 | /* Reserved [2:3] */ | ||
57 | #define FLD_DIGITAL_PWR_DN 0x02 | ||
58 | #define FLD_SLEEP 0x01 | ||
59 | |||
60 | /*****************************************************************************/ | ||
61 | #define HOST_REG2 0x001 | ||
62 | |||
63 | |||
64 | /*****************************************************************************/ | ||
65 | #define HOST_REG3 0x002 | ||
66 | |||
67 | /*****************************************************************************/ | ||
68 | /* added for polaris */ | ||
69 | #define GPIO_PIN_CTL0 0x3 | ||
70 | #define GPIO_PIN_CTL1 0x4 | ||
71 | #define GPIO_PIN_CTL2 0x5 | ||
72 | #define GPIO_PIN_CTL3 0x6 | ||
73 | #define TS1_PIN_CTL0 0x7 | ||
74 | #define TS1_PIN_CTL1 0x8 | ||
75 | /*****************************************************************************/ | ||
76 | |||
77 | #define FLD_CLK_IN_EN 0x80 | ||
78 | #define FLD_XTAL_CTRL 0x70 | ||
79 | #define FLD_BB_CLK_MODE 0x0C | ||
80 | #define FLD_REF_DIV_PLL 0x02 | ||
81 | #define FLD_REF_SEL_PLL1 0x01 | ||
82 | |||
83 | /*****************************************************************************/ | ||
84 | #define CHIP_CTRL 0x100 | ||
85 | /* Reserved [27] */ | ||
86 | /* Reserved [31:21] */ | ||
87 | #define FLD_CHIP_ACFG_DIS 0x00100000 | ||
88 | /* Reserved [19] */ | ||
89 | #define FLD_DUAL_MODE_ADC2 0x00040000 | ||
90 | #define FLD_SIF_EN 0x00020000 | ||
91 | #define FLD_SOFT_RST 0x00010000 | ||
92 | #define FLD_DEVICE_ID 0x0000FFFF | ||
93 | |||
94 | /*****************************************************************************/ | ||
95 | #define AFE_CTRL 0x104 | ||
96 | #define AFE_CTRL_C2HH_SRC_CTRL 0x104 | ||
97 | #define FLD_DIF_OUT_SEL 0xC0000000 | ||
98 | #define FLD_AUX_PLL_CLK_ALT_SEL 0x3C000000 | ||
99 | #define FLD_UV_ORDER_MODE 0x02000000 | ||
100 | #define FLD_FUNC_MODE 0x01800000 | ||
101 | #define FLD_ROT1_PHASE_CTL 0x007F8000 | ||
102 | #define FLD_AUD_IN_SEL 0x00004000 | ||
103 | #define FLD_LUMA_IN_SEL 0x00002000 | ||
104 | #define FLD_CHROMA_IN_SEL 0x00001000 | ||
105 | /* reserve [11:10] */ | ||
106 | #define FLD_INV_SPEC_DIS 0x00000200 | ||
107 | #define FLD_VGA_SEL_CH3 0x00000100 | ||
108 | #define FLD_VGA_SEL_CH2 0x00000080 | ||
109 | #define FLD_VGA_SEL_CH1 0x00000040 | ||
110 | #define FLD_DCR_BYP_CH1 0x00000020 | ||
111 | #define FLD_DCR_BYP_CH2 0x00000010 | ||
112 | #define FLD_DCR_BYP_CH3 0x00000008 | ||
113 | #define FLD_EN_12DB_CH3 0x00000004 | ||
114 | #define FLD_EN_12DB_CH2 0x00000002 | ||
115 | #define FLD_EN_12DB_CH1 0x00000001 | ||
116 | |||
117 | /* redefine in Cx231xx */ | ||
118 | /*****************************************************************************/ | ||
119 | #define DC_CTRL1 0x108 | ||
120 | /* reserve [31:30] */ | ||
121 | #define FLD_CLAMP_LVL_CH1 0x3FFF8000 | ||
122 | #define FLD_CLAMP_LVL_CH2 0x00007FFF | ||
123 | /*****************************************************************************/ | ||
124 | |||
125 | /*****************************************************************************/ | ||
126 | #define DC_CTRL2 0x10c | ||
127 | /* reserve [31:28] */ | ||
128 | #define FLD_CLAMP_LVL_CH3 0x00FFFE00 | ||
129 | #define FLD_CLAMP_WIND_LENTH 0x000001E0 | ||
130 | #define FLD_C2HH_SAT_MIN 0x0000001E | ||
131 | #define FLD_FLT_BYP_SEL 0x00000001 | ||
132 | /*****************************************************************************/ | ||
133 | |||
134 | /*****************************************************************************/ | ||
135 | #define DC_CTRL3 0x110 | ||
136 | /* reserve [31:16] */ | ||
137 | #define FLD_ERR_GAIN_CTL 0x00070000 | ||
138 | #define FLD_LPF_MIN 0x0000FFFF | ||
139 | /*****************************************************************************/ | ||
140 | |||
141 | /*****************************************************************************/ | ||
142 | #define DC_CTRL4 0x114 | ||
143 | /* reserve [31:31] */ | ||
144 | #define FLD_INTG_CH1 0x7FFFFFFF | ||
145 | /*****************************************************************************/ | ||
146 | |||
147 | /*****************************************************************************/ | ||
148 | #define DC_CTRL5 0x118 | ||
149 | /* reserve [31:31] */ | ||
150 | #define FLD_INTG_CH2 0x7FFFFFFF | ||
151 | /*****************************************************************************/ | ||
152 | |||
153 | /*****************************************************************************/ | ||
154 | #define DC_CTRL6 0x11c | ||
155 | /* reserve [31:31] */ | ||
156 | #define FLD_INTG_CH3 0x7FFFFFFF | ||
157 | /*****************************************************************************/ | ||
158 | |||
159 | /*****************************************************************************/ | ||
160 | #define PIN_CTRL 0x120 | ||
161 | #define FLD_OEF_AGC_RF 0x00000001 | ||
162 | #define FLD_OEF_AGC_IFVGA 0x00000002 | ||
163 | #define FLD_OEF_AGC_IF 0x00000004 | ||
164 | #define FLD_REG_BO_PUD 0x80000000 | ||
165 | #define FLD_IR_IRQ_STAT 0x40000000 | ||
166 | #define FLD_AUD_IRQ_STAT 0x20000000 | ||
167 | #define FLD_VID_IRQ_STAT 0x10000000 | ||
168 | /* Reserved [27:26] */ | ||
169 | #define FLD_IRQ_N_OUT_EN 0x02000000 | ||
170 | #define FLD_IRQ_N_POLAR 0x01000000 | ||
171 | /* Reserved [23:6] */ | ||
172 | #define FLD_OE_AUX_PLL_CLK 0x00000020 | ||
173 | #define FLD_OE_I2S_BCLK 0x00000010 | ||
174 | #define FLD_OE_I2S_WCLK 0x00000008 | ||
175 | #define FLD_OE_AGC_IF 0x00000004 | ||
176 | #define FLD_OE_AGC_IFVGA 0x00000002 | ||
177 | #define FLD_OE_AGC_RF 0x00000001 | ||
178 | |||
179 | /*****************************************************************************/ | ||
180 | #define AUD_IO_CTRL 0x124 | ||
181 | /* Reserved [31:8] */ | ||
182 | #define FLD_I2S_PORT_DIR 0x00000080 | ||
183 | #define FLD_I2S_OUT_SRC 0x00000040 | ||
184 | #define FLD_AUD_CHAN3_SRC 0x00000030 | ||
185 | #define FLD_AUD_CHAN2_SRC 0x0000000C | ||
186 | #define FLD_AUD_CHAN1_SRC 0x00000003 | ||
187 | |||
188 | /*****************************************************************************/ | ||
189 | #define AUD_LOCK1 0x128 | ||
190 | #define FLD_AUD_LOCK_KI_SHIFT 0xC0000000 | ||
191 | #define FLD_AUD_LOCK_KD_SHIFT 0x30000000 | ||
192 | /* Reserved [27:25] */ | ||
193 | #define FLD_EN_AV_LOCK 0x01000000 | ||
194 | #define FLD_VID_COUNT 0x00FFFFFF | ||
195 | |||
196 | /*****************************************************************************/ | ||
197 | #define AUD_LOCK2 0x12C | ||
198 | #define FLD_AUD_LOCK_KI_MULT 0xF0000000 | ||
199 | #define FLD_AUD_LOCK_KD_MULT 0x0F000000 | ||
200 | /* Reserved [23:22] */ | ||
201 | #define FLD_AUD_LOCK_FREQ_SHIFT 0x00300000 | ||
202 | #define FLD_AUD_COUNT 0x000FFFFF | ||
203 | |||
204 | /*****************************************************************************/ | ||
205 | #define AFE_DIAG_CTRL1 0x134 | ||
206 | /* Reserved [31:16] */ | ||
207 | #define FLD_CUV_DLY_LENGTH 0x0000FF00 | ||
208 | #define FLD_YC_DLY_LENGTH 0x000000FF | ||
209 | |||
210 | /*****************************************************************************/ | ||
211 | /* Poalris redefine */ | ||
212 | #define AFE_DIAG_CTRL3 0x138 | ||
213 | /* Reserved [31:26] */ | ||
214 | #define FLD_AUD_DUAL_FLAG_POL 0x02000000 | ||
215 | #define FLD_VID_DUAL_FLAG_POL 0x01000000 | ||
216 | /* Reserved [23:23] */ | ||
217 | #define FLD_COL_CLAMP_DIS_CH1 0x00400000 | ||
218 | #define FLD_COL_CLAMP_DIS_CH2 0x00200000 | ||
219 | #define FLD_COL_CLAMP_DIS_CH3 0x00100000 | ||
220 | |||
221 | #define TEST_CTRL1 0x144 | ||
222 | /* Reserved [31:29] */ | ||
223 | #define FLD_LBIST_EN 0x10000000 | ||
224 | /* Reserved [27:10] */ | ||
225 | #define FLD_FI_BIST_INTR_R 0x0000200 | ||
226 | #define FLD_FI_BIST_INTR_L 0x0000100 | ||
227 | #define FLD_BIST_FAIL_AUD_PLL 0x0000080 | ||
228 | #define FLD_BIST_INTR_AUD_PLL 0x0000040 | ||
229 | #define FLD_BIST_FAIL_VID_PLL 0x0000020 | ||
230 | #define FLD_BIST_INTR_VID_PLL 0x0000010 | ||
231 | /* Reserved [3:1] */ | ||
232 | #define FLD_CIR_TEST_DIS 0x00000001 | ||
233 | |||
234 | |||
235 | /*****************************************************************************/ | ||
236 | #define TEST_CTRL2 0x148 | ||
237 | #define FLD_TSXCLK_POL_CTL 0x80000000 | ||
238 | #define FLD_ISO_CTL_SEL 0x40000000 | ||
239 | #define FLD_ISO_CTL_EN 0x20000000 | ||
240 | #define FLD_BIST_DEBUGZ 0x10000000 | ||
241 | #define FLD_AUD_BIST_TEST_H 0x0F000000 | ||
242 | /* Reserved [23:22] */ | ||
243 | #define FLD_FLTRN_BIST_TEST_H 0x00020000 | ||
244 | #define FLD_VID_BIST_TEST_H 0x00010000 | ||
245 | /* Reserved [19:17] */ | ||
246 | #define FLD_BIST_TEST_H 0x00010000 | ||
247 | /* Reserved [15:13] */ | ||
248 | #define FLD_TAB_EN 0x00001000 | ||
249 | /* Reserved [11:0] */ | ||
250 | |||
251 | /*****************************************************************************/ | ||
252 | #define BIST_STAT 0x14C | ||
253 | #define FLD_AUD_BIST_FAIL_H 0xFFF00000 | ||
254 | #define FLD_FLTRN_BIST_FAIL_H 0x00180000 | ||
255 | #define FLD_VID_BIST_FAIL_H 0x00070000 | ||
256 | #define FLD_AUD_BIST_TST_DONE 0x0000FFF0 | ||
257 | #define FLD_FLTRN_BIST_TST_DONE 0x00000008 | ||
258 | #define FLD_VID_BIST_TST_DONE 0x00000007 | ||
259 | |||
260 | |||
261 | /*****************************************************************************/ | ||
262 | /* DirectIF registers definition have been moved to DIF_reg.h */ | ||
263 | /*****************************************************************************/ | ||
264 | #define MODE_CTRL 0x400 | ||
265 | #define FLD_AFD_PAL60_DIS 0x20000000 | ||
266 | #define FLD_AFD_FORCE_SECAM 0x10000000 | ||
267 | #define FLD_AFD_FORCE_PALNC 0x08000000 | ||
268 | #define FLD_AFD_FORCE_PAL 0x04000000 | ||
269 | #define FLD_AFD_PALM_SEL 0x03000000 | ||
270 | #define FLD_CKILL_MODE 0x00300000 | ||
271 | #define FLD_COMB_NOTCH_MODE 0x00c00000 /* bit[19:18] */ | ||
272 | #define FLD_CLR_LOCK_STAT 0x00020000 | ||
273 | #define FLD_FAST_LOCK_MD 0x00010000 | ||
274 | #define FLD_WCEN 0x00008000 | ||
275 | #define FLD_CAGCEN 0x00004000 | ||
276 | #define FLD_CKILLEN 0x00002000 | ||
277 | #define FLD_AUTO_SC_LOCK 0x00001000 | ||
278 | #define FLD_MAN_SC_FAST_LOCK 0x00000800 | ||
279 | #define FLD_INPUT_MODE 0x00000600 | ||
280 | #define FLD_AFD_ACQUIRE 0x00000100 | ||
281 | #define FLD_AFD_NTSC_SEL 0x00000080 | ||
282 | #define FLD_AFD_PAL_SEL 0x00000040 | ||
283 | #define FLD_ACFG_DIS 0x00000020 | ||
284 | #define FLD_SQ_PIXEL 0x00000010 | ||
285 | #define FLD_VID_FMT_SEL 0x0000000F | ||
286 | |||
287 | /*****************************************************************************/ | ||
288 | #define OUT_CTRL1 0x404 | ||
289 | #define FLD_POLAR 0x7F000000 | ||
290 | /* Reserved [23] */ | ||
291 | #define FLD_RND_MODE 0x00600000 | ||
292 | #define FLD_VIPCLAMP_EN 0x00100000 | ||
293 | #define FLD_VIPBLANK_EN 0x00080000 | ||
294 | #define FLD_VIP_OPT_AL 0x00040000 | ||
295 | #define FLD_IDID0_SOURCE 0x00020000 | ||
296 | #define FLD_DCMODE 0x00010000 | ||
297 | #define FLD_CLK_GATING 0x0000C000 | ||
298 | #define FLD_CLK_INVERT 0x00002000 | ||
299 | #define FLD_HSFMT 0x00001000 | ||
300 | #define FLD_VALIDFMT 0x00000800 | ||
301 | #define FLD_ACTFMT 0x00000400 | ||
302 | #define FLD_SWAPRAW 0x00000200 | ||
303 | #define FLD_CLAMPRAW_EN 0x00000100 | ||
304 | #define FLD_BLUE_FIELD_EN 0x00000080 | ||
305 | #define FLD_BLUE_FIELD_ACT 0x00000040 | ||
306 | #define FLD_TASKBIT_VAL 0x00000020 | ||
307 | #define FLD_ANC_DATA_EN 0x00000010 | ||
308 | #define FLD_VBIHACTRAW_EN 0x00000008 | ||
309 | #define FLD_MODE10B 0x00000004 | ||
310 | #define FLD_OUT_MODE 0x00000003 | ||
311 | |||
312 | /*****************************************************************************/ | ||
313 | #define OUT_CTRL2 0x408 | ||
314 | #define FLD_AUD_GRP 0xC0000000 | ||
315 | #define FLD_SAMPLE_RATE 0x30000000 | ||
316 | #define FLD_AUD_ANC_EN 0x08000000 | ||
317 | #define FLD_EN_C 0x04000000 | ||
318 | #define FLD_EN_B 0x02000000 | ||
319 | #define FLD_EN_A 0x01000000 | ||
320 | /* Reserved [23:20] */ | ||
321 | #define FLD_IDID1_LSB 0x000C0000 | ||
322 | #define FLD_IDID0_LSB 0x00030000 | ||
323 | #define FLD_IDID1_MSB 0x0000FF00 | ||
324 | #define FLD_IDID0_MSB 0x000000FF | ||
325 | |||
326 | /*****************************************************************************/ | ||
327 | #define GEN_STAT 0x40C | ||
328 | #define FLD_VCR_DETECT 0x00800000 | ||
329 | #define FLD_SPECIAL_PLAY_N 0x00400000 | ||
330 | #define FLD_VPRES 0x00200000 | ||
331 | #define FLD_AGC_LOCK 0x00100000 | ||
332 | #define FLD_CSC_LOCK 0x00080000 | ||
333 | #define FLD_VLOCK 0x00040000 | ||
334 | #define FLD_SRC_LOCK 0x00020000 | ||
335 | #define FLD_HLOCK 0x00010000 | ||
336 | #define FLD_VSYNC_N 0x00008000 | ||
337 | #define FLD_SRC_FIFO_UFLOW 0x00004000 | ||
338 | #define FLD_SRC_FIFO_OFLOW 0x00002000 | ||
339 | #define FLD_FIELD 0x00001000 | ||
340 | #define FLD_AFD_FMT_STAT 0x00000F00 | ||
341 | #define FLD_MV_TYPE2_PAIR 0x00000080 | ||
342 | #define FLD_MV_T3CS 0x00000040 | ||
343 | #define FLD_MV_CS 0x00000020 | ||
344 | #define FLD_MV_PSP 0x00000010 | ||
345 | /* Reserved [3] */ | ||
346 | #define FLD_MV_CDAT 0x00000003 | ||
347 | |||
348 | /*****************************************************************************/ | ||
349 | #define INT_STAT_MASK 0x410 | ||
350 | #define FLD_COMB_3D_FIFO_MSK 0x80000000 | ||
351 | #define FLD_WSS_DAT_AVAIL_MSK 0x40000000 | ||
352 | #define FLD_GS2_DAT_AVAIL_MSK 0x20000000 | ||
353 | #define FLD_GS1_DAT_AVAIL_MSK 0x10000000 | ||
354 | #define FLD_CC_DAT_AVAIL_MSK 0x08000000 | ||
355 | #define FLD_VPRES_CHANGE_MSK 0x04000000 | ||
356 | #define FLD_MV_CHANGE_MSK 0x02000000 | ||
357 | #define FLD_END_VBI_EVEN_MSK 0x01000000 | ||
358 | #define FLD_END_VBI_ODD_MSK 0x00800000 | ||
359 | #define FLD_FMT_CHANGE_MSK 0x00400000 | ||
360 | #define FLD_VSYNC_TRAIL_MSK 0x00200000 | ||
361 | #define FLD_HLOCK_CHANGE_MSK 0x00100000 | ||
362 | #define FLD_VLOCK_CHANGE_MSK 0x00080000 | ||
363 | #define FLD_CSC_LOCK_CHANGE_MSK 0x00040000 | ||
364 | #define FLD_SRC_FIFO_UFLOW_MSK 0x00020000 | ||
365 | #define FLD_SRC_FIFO_OFLOW_MSK 0x00010000 | ||
366 | #define FLD_COMB_3D_FIFO_STAT 0x00008000 | ||
367 | #define FLD_WSS_DAT_AVAIL_STAT 0x00004000 | ||
368 | #define FLD_GS2_DAT_AVAIL_STAT 0x00002000 | ||
369 | #define FLD_GS1_DAT_AVAIL_STAT 0x00001000 | ||
370 | #define FLD_CC_DAT_AVAIL_STAT 0x00000800 | ||
371 | #define FLD_VPRES_CHANGE_STAT 0x00000400 | ||
372 | #define FLD_MV_CHANGE_STAT 0x00000200 | ||
373 | #define FLD_END_VBI_EVEN_STAT 0x00000100 | ||
374 | #define FLD_END_VBI_ODD_STAT 0x00000080 | ||
375 | #define FLD_FMT_CHANGE_STAT 0x00000040 | ||
376 | #define FLD_VSYNC_TRAIL_STAT 0x00000020 | ||
377 | #define FLD_HLOCK_CHANGE_STAT 0x00000010 | ||
378 | #define FLD_VLOCK_CHANGE_STAT 0x00000008 | ||
379 | #define FLD_CSC_LOCK_CHANGE_STAT 0x00000004 | ||
380 | #define FLD_SRC_FIFO_UFLOW_STAT 0x00000002 | ||
381 | #define FLD_SRC_FIFO_OFLOW_STAT 0x00000001 | ||
382 | |||
383 | /*****************************************************************************/ | ||
384 | #define LUMA_CTRL 0x414 | ||
385 | #define BRIGHTNESS_CTRL_BYTE 0x414 | ||
386 | #define CONTRAST_CTRL_BYTE 0x415 | ||
387 | #define LUMA_CTRL_BYTE_3 0x416 | ||
388 | #define FLD_LUMA_CORE_SEL 0x00C00000 | ||
389 | #define FLD_RANGE 0x00300000 | ||
390 | /* Reserved [19] */ | ||
391 | #define FLD_PEAK_EN 0x00040000 | ||
392 | #define FLD_PEAK_SEL 0x00030000 | ||
393 | #define FLD_CNTRST 0x0000FF00 | ||
394 | #define FLD_BRITE 0x000000FF | ||
395 | |||
396 | /*****************************************************************************/ | ||
397 | #define HSCALE_CTRL 0x418 | ||
398 | #define FLD_HFILT 0x03000000 | ||
399 | #define FLD_HSCALE 0x00FFFFFF | ||
400 | |||
401 | /*****************************************************************************/ | ||
402 | #define VSCALE_CTRL 0x41C | ||
403 | #define FLD_LINE_AVG_DIS 0x01000000 | ||
404 | /* Reserved [23:20] */ | ||
405 | #define FLD_VS_INTRLACE 0x00080000 | ||
406 | #define FLD_VFILT 0x00070000 | ||
407 | /* Reserved [15:13] */ | ||
408 | #define FLD_VSCALE 0x00001FFF | ||
409 | |||
410 | /*****************************************************************************/ | ||
411 | #define CHROMA_CTRL 0x420 | ||
412 | #define USAT_CTRL_BYTE 0x420 | ||
413 | #define VSAT_CTRL_BYTE 0x421 | ||
414 | #define HUE_CTRL_BYTE 0x422 | ||
415 | #define FLD_C_LPF_EN 0x20000000 | ||
416 | #define FLD_CHR_DELAY 0x1C000000 | ||
417 | #define FLD_C_CORE_SEL 0x03000000 | ||
418 | #define FLD_HUE 0x00FF0000 | ||
419 | #define FLD_VSAT 0x0000FF00 | ||
420 | #define FLD_USAT 0x000000FF | ||
421 | |||
422 | /*****************************************************************************/ | ||
423 | #define VBI_LINE_CTRL1 0x424 | ||
424 | #define FLD_VBI_MD_LINE4 0xFF000000 | ||
425 | #define FLD_VBI_MD_LINE3 0x00FF0000 | ||
426 | #define FLD_VBI_MD_LINE2 0x0000FF00 | ||
427 | #define FLD_VBI_MD_LINE1 0x000000FF | ||
428 | |||
429 | /*****************************************************************************/ | ||
430 | #define VBI_LINE_CTRL2 0x428 | ||
431 | #define FLD_VBI_MD_LINE8 0xFF000000 | ||
432 | #define FLD_VBI_MD_LINE7 0x00FF0000 | ||
433 | #define FLD_VBI_MD_LINE6 0x0000FF00 | ||
434 | #define FLD_VBI_MD_LINE5 0x000000FF | ||
435 | |||
436 | /*****************************************************************************/ | ||
437 | #define VBI_LINE_CTRL3 0x42C | ||
438 | #define FLD_VBI_MD_LINE12 0xFF000000 | ||
439 | #define FLD_VBI_MD_LINE11 0x00FF0000 | ||
440 | #define FLD_VBI_MD_LINE10 0x0000FF00 | ||
441 | #define FLD_VBI_MD_LINE9 0x000000FF | ||
442 | |||
443 | /*****************************************************************************/ | ||
444 | #define VBI_LINE_CTRL4 0x430 | ||
445 | #define FLD_VBI_MD_LINE16 0xFF000000 | ||
446 | #define FLD_VBI_MD_LINE15 0x00FF0000 | ||
447 | #define FLD_VBI_MD_LINE14 0x0000FF00 | ||
448 | #define FLD_VBI_MD_LINE13 0x000000FF | ||
449 | |||
450 | /*****************************************************************************/ | ||
451 | #define VBI_LINE_CTRL5 0x434 | ||
452 | #define FLD_VBI_MD_LINE17 0x000000FF | ||
453 | |||
454 | /*****************************************************************************/ | ||
455 | #define VBI_FC_CFG 0x438 | ||
456 | #define FLD_FC_ALT2 0xFF000000 | ||
457 | #define FLD_FC_ALT1 0x00FF0000 | ||
458 | #define FLD_FC_ALT2_TYPE 0x0000F000 | ||
459 | #define FLD_FC_ALT1_TYPE 0x00000F00 | ||
460 | /* Reserved [7:1] */ | ||
461 | #define FLD_FC_SEARCH_MODE 0x00000001 | ||
462 | |||
463 | /*****************************************************************************/ | ||
464 | #define VBI_MISC_CFG1 0x43C | ||
465 | #define FLD_TTX_PKTADRU 0xFFF00000 | ||
466 | #define FLD_TTX_PKTADRL 0x000FFF00 | ||
467 | /* Reserved [7:6] */ | ||
468 | #define FLD_MOJI_PACK_DIS 0x00000020 | ||
469 | #define FLD_VPS_DEC_DIS 0x00000010 | ||
470 | #define FLD_CRI_MARG_SCALE 0x0000000C | ||
471 | #define FLD_EDGE_RESYNC_EN 0x00000002 | ||
472 | #define FLD_ADAPT_SLICE_DIS 0x00000001 | ||
473 | |||
474 | /*****************************************************************************/ | ||
475 | #define VBI_MISC_CFG2 0x440 | ||
476 | #define FLD_HAMMING_TYPE 0x0F000000 | ||
477 | /* Reserved [23:20] */ | ||
478 | #define FLD_WSS_FIFO_RST 0x00080000 | ||
479 | #define FLD_GS2_FIFO_RST 0x00040000 | ||
480 | #define FLD_GS1_FIFO_RST 0x00020000 | ||
481 | #define FLD_CC_FIFO_RST 0x00010000 | ||
482 | /* Reserved [15:12] */ | ||
483 | #define FLD_VBI3_SDID 0x00000F00 | ||
484 | #define FLD_VBI2_SDID 0x000000F0 | ||
485 | #define FLD_VBI1_SDID 0x0000000F | ||
486 | |||
487 | /*****************************************************************************/ | ||
488 | #define VBI_PAY1 0x444 | ||
489 | #define FLD_GS1_FIFO_DAT 0xFF000000 | ||
490 | #define FLD_GS1_STAT 0x00FF0000 | ||
491 | #define FLD_CC_FIFO_DAT 0x0000FF00 | ||
492 | #define FLD_CC_STAT 0x000000FF | ||
493 | |||
494 | /*****************************************************************************/ | ||
495 | #define VBI_PAY2 0x448 | ||
496 | #define FLD_WSS_FIFO_DAT 0xFF000000 | ||
497 | #define FLD_WSS_STAT 0x00FF0000 | ||
498 | #define FLD_GS2_FIFO_DAT 0x0000FF00 | ||
499 | #define FLD_GS2_STAT 0x000000FF | ||
500 | |||
501 | /*****************************************************************************/ | ||
502 | #define VBI_CUST1_CFG1 0x44C | ||
503 | /* Reserved [31] */ | ||
504 | #define FLD_VBI1_CRIWIN 0x7F000000 | ||
505 | #define FLD_VBI1_SLICE_DIST 0x00F00000 | ||
506 | #define FLD_VBI1_BITINC 0x000FFF00 | ||
507 | #define FLD_VBI1_HDELAY 0x000000FF | ||
508 | |||
509 | /*****************************************************************************/ | ||
510 | #define VBI_CUST1_CFG2 0x450 | ||
511 | #define FLD_VBI1_FC_LENGTH 0x1F000000 | ||
512 | #define FLD_VBI1_FRAME_CODE 0x00FFFFFF | ||
513 | |||
514 | /*****************************************************************************/ | ||
515 | #define VBI_CUST1_CFG3 0x454 | ||
516 | #define FLD_VBI1_HAM_EN 0x80000000 | ||
517 | #define FLD_VBI1_FIFO_MODE 0x70000000 | ||
518 | #define FLD_VBI1_FORMAT_TYPE 0x0F000000 | ||
519 | #define FLD_VBI1_PAYLD_LENGTH 0x00FF0000 | ||
520 | #define FLD_VBI1_CRI_LENGTH 0x0000F000 | ||
521 | #define FLD_VBI1_CRI_MARGIN 0x00000F00 | ||
522 | #define FLD_VBI1_CRI_TIME 0x000000FF | ||
523 | |||
524 | /*****************************************************************************/ | ||
525 | #define VBI_CUST2_CFG1 0x458 | ||
526 | /* Reserved [31] */ | ||
527 | #define FLD_VBI2_CRIWIN 0x7F000000 | ||
528 | #define FLD_VBI2_SLICE_DIST 0x00F00000 | ||
529 | #define FLD_VBI2_BITINC 0x000FFF00 | ||
530 | #define FLD_VBI2_HDELAY 0x000000FF | ||
531 | |||
532 | /*****************************************************************************/ | ||
533 | #define VBI_CUST2_CFG2 0x45C | ||
534 | #define FLD_VBI2_FC_LENGTH 0x1F000000 | ||
535 | #define FLD_VBI2_FRAME_CODE 0x00FFFFFF | ||
536 | |||
537 | /*****************************************************************************/ | ||
538 | #define VBI_CUST2_CFG3 0x460 | ||
539 | #define FLD_VBI2_HAM_EN 0x80000000 | ||
540 | #define FLD_VBI2_FIFO_MODE 0x70000000 | ||
541 | #define FLD_VBI2_FORMAT_TYPE 0x0F000000 | ||
542 | #define FLD_VBI2_PAYLD_LENGTH 0x00FF0000 | ||
543 | #define FLD_VBI2_CRI_LENGTH 0x0000F000 | ||
544 | #define FLD_VBI2_CRI_MARGIN 0x00000F00 | ||
545 | #define FLD_VBI2_CRI_TIME 0x000000FF | ||
546 | |||
547 | /*****************************************************************************/ | ||
548 | #define VBI_CUST3_CFG1 0x464 | ||
549 | /* Reserved [31] */ | ||
550 | #define FLD_VBI3_CRIWIN 0x7F000000 | ||
551 | #define FLD_VBI3_SLICE_DIST 0x00F00000 | ||
552 | #define FLD_VBI3_BITINC 0x000FFF00 | ||
553 | #define FLD_VBI3_HDELAY 0x000000FF | ||
554 | |||
555 | /*****************************************************************************/ | ||
556 | #define VBI_CUST3_CFG2 0x468 | ||
557 | #define FLD_VBI3_FC_LENGTH 0x1F000000 | ||
558 | #define FLD_VBI3_FRAME_CODE 0x00FFFFFF | ||
559 | |||
560 | /*****************************************************************************/ | ||
561 | #define VBI_CUST3_CFG3 0x46C | ||
562 | #define FLD_VBI3_HAM_EN 0x80000000 | ||
563 | #define FLD_VBI3_FIFO_MODE 0x70000000 | ||
564 | #define FLD_VBI3_FORMAT_TYPE 0x0F000000 | ||
565 | #define FLD_VBI3_PAYLD_LENGTH 0x00FF0000 | ||
566 | #define FLD_VBI3_CRI_LENGTH 0x0000F000 | ||
567 | #define FLD_VBI3_CRI_MARGIN 0x00000F00 | ||
568 | #define FLD_VBI3_CRI_TIME 0x000000FF | ||
569 | |||
570 | /*****************************************************************************/ | ||
571 | #define HORIZ_TIM_CTRL 0x470 | ||
572 | #define FLD_BGDEL_CNT 0xFF000000 | ||
573 | /* Reserved [23:22] */ | ||
574 | #define FLD_HACTIVE_CNT 0x003FF000 | ||
575 | /* Reserved [11:10] */ | ||
576 | #define FLD_HBLANK_CNT 0x000003FF | ||
577 | |||
578 | /*****************************************************************************/ | ||
579 | #define VERT_TIM_CTRL 0x474 | ||
580 | #define FLD_V656BLANK_CNT 0xFF000000 | ||
581 | /* Reserved [23:22] */ | ||
582 | #define FLD_VACTIVE_CNT 0x003FF000 | ||
583 | /* Reserved [11:10] */ | ||
584 | #define FLD_VBLANK_CNT 0x000003FF | ||
585 | |||
586 | /*****************************************************************************/ | ||
587 | #define SRC_COMB_CFG 0x478 | ||
588 | #define FLD_CCOMB_2LN_CHECK 0x80000000 | ||
589 | #define FLD_CCOMB_3LN_EN 0x40000000 | ||
590 | #define FLD_CCOMB_2LN_EN 0x20000000 | ||
591 | #define FLD_CCOMB_3D_EN 0x10000000 | ||
592 | /* Reserved [27] */ | ||
593 | #define FLD_LCOMB_3LN_EN 0x04000000 | ||
594 | #define FLD_LCOMB_2LN_EN 0x02000000 | ||
595 | #define FLD_LCOMB_3D_EN 0x01000000 | ||
596 | #define FLD_LUMA_LPF_SEL 0x00C00000 | ||
597 | #define FLD_UV_LPF_SEL 0x00300000 | ||
598 | #define FLD_BLEND_SLOPE 0x000F0000 | ||
599 | #define FLD_CCOMB_REDUCE_EN 0x00008000 | ||
600 | /* Reserved [14:10] */ | ||
601 | #define FLD_SRC_DECIM_RATIO 0x000003FF | ||
602 | |||
603 | /*****************************************************************************/ | ||
604 | #define CHROMA_VBIOFF_CFG 0x47C | ||
605 | #define FLD_VBI_VOFFSET 0x1F000000 | ||
606 | /* Reserved [23:20] */ | ||
607 | #define FLD_SC_STEP 0x000FFFFF | ||
608 | |||
609 | /*****************************************************************************/ | ||
610 | #define FIELD_COUNT 0x480 | ||
611 | #define FLD_FIELD_COUNT_FLD 0x000003FF | ||
612 | |||
613 | /*****************************************************************************/ | ||
614 | #define MISC_TIM_CTRL 0x484 | ||
615 | #define FLD_DEBOUNCE_COUNT 0xC0000000 | ||
616 | #define FLD_VT_LINE_CNT_HYST 0x30000000 | ||
617 | /* Reserved [27] */ | ||
618 | #define FLD_AFD_STAT 0x07FF0000 | ||
619 | #define FLD_VPRES_VERT_EN 0x00008000 | ||
620 | /* Reserved [14:12] */ | ||
621 | #define FLD_HR32 0x00000800 | ||
622 | #define FLD_TDALGN 0x00000400 | ||
623 | #define FLD_TDFIELD 0x00000200 | ||
624 | /* Reserved [8:6] */ | ||
625 | #define FLD_TEMPDEC 0x0000003F | ||
626 | |||
627 | /*****************************************************************************/ | ||
628 | #define DFE_CTRL1 0x488 | ||
629 | #define FLD_CLAMP_AUTO_EN 0x80000000 | ||
630 | #define FLD_AGC_AUTO_EN 0x40000000 | ||
631 | #define FLD_VGA_CRUSH_EN 0x20000000 | ||
632 | #define FLD_VGA_AUTO_EN 0x10000000 | ||
633 | #define FLD_VBI_GATE_EN 0x08000000 | ||
634 | #define FLD_CLAMP_LEVEL 0x07000000 | ||
635 | /* Reserved [23:22] */ | ||
636 | #define FLD_CLAMP_SKIP_CNT 0x00300000 | ||
637 | #define FLD_AGC_GAIN 0x000FFF00 | ||
638 | /* Reserved [7:6] */ | ||
639 | #define FLD_VGA_GAIN 0x0000003F | ||
640 | |||
641 | /*****************************************************************************/ | ||
642 | #define DFE_CTRL2 0x48C | ||
643 | #define FLD_VGA_ACQUIRE_RANGE 0x00FF0000 | ||
644 | #define FLD_VGA_TRACK_RANGE 0x0000FF00 | ||
645 | #define FLD_VGA_SYNC 0x000000FF | ||
646 | |||
647 | /*****************************************************************************/ | ||
648 | #define DFE_CTRL3 0x490 | ||
649 | #define FLD_BP_PERCENT 0xFF000000 | ||
650 | #define FLD_DFT_THRESHOLD 0x00FF0000 | ||
651 | /* Reserved [15:12] */ | ||
652 | #define FLD_SYNC_WIDTH_SEL 0x00000600 | ||
653 | #define FLD_BP_LOOP_GAIN 0x00000300 | ||
654 | #define FLD_SYNC_LOOP_GAIN 0x000000C0 | ||
655 | /* Reserved [5:4] */ | ||
656 | #define FLD_AGC_LOOP_GAIN 0x0000000C | ||
657 | #define FLD_DCC_LOOP_GAIN 0x00000003 | ||
658 | |||
659 | /*****************************************************************************/ | ||
660 | #define PLL_CTRL 0x494 | ||
661 | #define FLD_PLL_KD 0xFF000000 | ||
662 | #define FLD_PLL_KI 0x00FF0000 | ||
663 | #define FLD_PLL_MAX_OFFSET 0x0000FFFF | ||
664 | |||
665 | |||
666 | /*****************************************************************************/ | ||
667 | #define HTL_CTRL 0x498 | ||
668 | /* Reserved [31:24] */ | ||
669 | #define FLD_AUTO_LOCK_SPD 0x00080000 | ||
670 | #define FLD_MAN_FAST_LOCK 0x00040000 | ||
671 | #define FLD_HTL_15K_EN 0x00020000 | ||
672 | #define FLD_HTL_500K_EN 0x00010000 | ||
673 | #define FLD_HTL_KD 0x0000FF00 | ||
674 | #define FLD_HTL_KI 0x000000FF | ||
675 | |||
676 | /*****************************************************************************/ | ||
677 | #define COMB_CTRL 0x49C | ||
678 | #define FLD_COMB_PHASE_LIMIT 0xFF000000 | ||
679 | #define FLD_CCOMB_ERR_LIMIT 0x00FF0000 | ||
680 | #define FLD_LUMA_THRESHOLD 0x0000FF00 | ||
681 | #define FLD_LCOMB_ERR_LIMIT 0x000000FF | ||
682 | |||
683 | /*****************************************************************************/ | ||
684 | #define CRUSH_CTRL 0x4A0 | ||
685 | #define FLD_WTW_EN 0x00400000 | ||
686 | #define FLD_CRUSH_FREQ 0x00200000 | ||
687 | #define FLD_MAJ_SEL_EN 0x00100000 | ||
688 | #define FLD_MAJ_SEL 0x000C0000 | ||
689 | /* Reserved [17:15] */ | ||
690 | #define FLD_SYNC_TIP_REDUCE 0x00007E00 | ||
691 | /* Reserved [8:6] */ | ||
692 | #define FLD_SYNC_TIP_INC 0x0000003F | ||
693 | |||
694 | /*****************************************************************************/ | ||
695 | #define SOFT_RST_CTRL 0x4A4 | ||
696 | #define FLD_VD_SOFT_RST 0x00008000 | ||
697 | /* Reserved [14:12] */ | ||
698 | #define FLD_REG_RST_MSK 0x00000800 | ||
699 | #define FLD_VOF_RST_MSK 0x00000400 | ||
700 | #define FLD_MVDET_RST_MSK 0x00000200 | ||
701 | #define FLD_VBI_RST_MSK 0x00000100 | ||
702 | #define FLD_SCALE_RST_MSK 0x00000080 | ||
703 | #define FLD_CHROMA_RST_MSK 0x00000040 | ||
704 | #define FLD_LUMA_RST_MSK 0x00000020 | ||
705 | #define FLD_VTG_RST_MSK 0x00000010 | ||
706 | #define FLD_YCSEP_RST_MSK 0x00000008 | ||
707 | #define FLD_SRC_RST_MSK 0x00000004 | ||
708 | #define FLD_DFE_RST_MSK 0x00000002 | ||
709 | /* Reserved [0] */ | ||
710 | |||
711 | /*****************************************************************************/ | ||
712 | #define MV_DT_CTRL1 0x4A8 | ||
713 | /* Reserved [31:29] */ | ||
714 | #define FLD_PSP_STOP_LINE 0x1F000000 | ||
715 | /* Reserved [23:21] */ | ||
716 | #define FLD_PSP_STRT_LINE 0x001F0000 | ||
717 | /* Reserved [15] */ | ||
718 | #define FLD_PSP_LLIMW 0x00007F00 | ||
719 | /* Reserved [7] */ | ||
720 | #define FLD_PSP_ULIMW 0x0000007F | ||
721 | |||
722 | /*****************************************************************************/ | ||
723 | #define MV_DT_CTRL2 0x4AC | ||
724 | #define FLD_CS_STOPWIN 0xFF000000 | ||
725 | #define FLD_CS_STRTWIN 0x00FF0000 | ||
726 | #define FLD_CS_WIDTH 0x0000FF00 | ||
727 | #define FLD_PSP_SPEC_VAL 0x000000FF | ||
728 | |||
729 | /*****************************************************************************/ | ||
730 | #define MV_DT_CTRL3 0x4B0 | ||
731 | #define FLD_AUTO_RATE_DIS 0x80000000 | ||
732 | #define FLD_HLOCK_DIS 0x40000000 | ||
733 | #define FLD_SEL_FIELD_CNT 0x20000000 | ||
734 | #define FLD_CS_TYPE2_SEL 0x10000000 | ||
735 | #define FLD_CS_LINE_THRSH_SEL 0x08000000 | ||
736 | #define FLD_CS_ATHRESH_SEL 0x04000000 | ||
737 | #define FLD_PSP_SPEC_SEL 0x02000000 | ||
738 | #define FLD_PSP_LINES_SEL 0x01000000 | ||
739 | #define FLD_FIELD_CNT 0x00F00000 | ||
740 | #define FLD_CS_TYPE2_CNT 0x000FC000 | ||
741 | #define FLD_CS_LINE_CNT 0x00003F00 | ||
742 | #define FLD_CS_ATHRESH_LEV 0x000000FF | ||
743 | |||
744 | /*****************************************************************************/ | ||
745 | #define CHIP_VERSION 0x4B4 | ||
746 | /* Cx231xx redefine */ | ||
747 | #define VERSION 0x4B4 | ||
748 | #define FLD_REV_ID 0x000000FF | ||
749 | |||
750 | /*****************************************************************************/ | ||
751 | #define MISC_DIAG_CTRL 0x4B8 | ||
752 | /* Reserved [31:24] */ | ||
753 | #define FLD_SC_CONVERGE_THRESH 0x00FF0000 | ||
754 | #define FLD_CCOMB_ERR_LIMIT_3D 0x0000FF00 | ||
755 | #define FLD_LCOMB_ERR_LIMIT_3D 0x000000FF | ||
756 | |||
757 | /*****************************************************************************/ | ||
758 | #define VBI_PASS_CTRL 0x4BC | ||
759 | #define FLD_VBI_PASS_MD 0x00200000 | ||
760 | #define FLD_VBI_SETUP_DIS 0x00100000 | ||
761 | #define FLD_PASS_LINE_CTRL 0x000FFFFF | ||
762 | |||
763 | /*****************************************************************************/ | ||
764 | /* Cx231xx redefine */ | ||
765 | #define VCR_DET_CTRL 0x4c0 | ||
766 | #define FLD_EN_FIELD_PHASE_DET 0x80000000 | ||
767 | #define FLD_EN_HEAD_SW_DET 0x40000000 | ||
768 | #define FLD_FIELD_PHASE_LENGTH 0x01FF0000 | ||
769 | /* Reserved [29:25] */ | ||
770 | #define FLD_FIELD_PHASE_DELAY 0x0000FF00 | ||
771 | #define FLD_FIELD_PHASE_LIMIT 0x000000F0 | ||
772 | #define FLD_HEAD_SW_DET_LIMIT 0x0000000F | ||
773 | |||
774 | |||
775 | /*****************************************************************************/ | ||
776 | #define DL_CTL 0x800 | ||
777 | #define DL_CTL_ADDRESS_LOW 0x800 /* Byte 1 in DL_CTL */ | ||
778 | #define DL_CTL_ADDRESS_HIGH 0x801 /* Byte 2 in DL_CTL */ | ||
779 | #define DL_CTL_DATA 0x802 /* Byte 3 in DL_CTL */ | ||
780 | #define DL_CTL_CONTROL 0x803 /* Byte 4 in DL_CTL */ | ||
781 | /* Reserved [31:5] */ | ||
782 | #define FLD_START_8051 0x10000000 | ||
783 | #define FLD_DL_ENABLE 0x08000000 | ||
784 | #define FLD_DL_AUTO_INC 0x04000000 | ||
785 | #define FLD_DL_MAP 0x03000000 | ||
786 | |||
787 | /*****************************************************************************/ | ||
788 | #define STD_DET_STATUS 0x804 | ||
789 | #define FLD_SPARE_STATUS1 0xFF000000 | ||
790 | #define FLD_SPARE_STATUS0 0x00FF0000 | ||
791 | #define FLD_MOD_DET_STATUS1 0x0000FF00 | ||
792 | #define FLD_MOD_DET_STATUS0 0x000000FF | ||
793 | |||
794 | /*****************************************************************************/ | ||
795 | #define AUD_BUILD_NUM 0x806 | ||
796 | #define AUD_VER_NUM 0x807 | ||
797 | #define STD_DET_CTL 0x808 | ||
798 | #define STD_DET_CTL_AUD_CTL 0x808 /* Byte 1 in STD_DET_CTL */ | ||
799 | #define STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */ | ||
800 | #define FLD_SPARE_CTL0 0xFF000000 | ||
801 | #define FLD_DIS_DBX 0x00800000 | ||
802 | #define FLD_DIS_BTSC 0x00400000 | ||
803 | #define FLD_DIS_NICAM_A2 0x00200000 | ||
804 | #define FLD_VIDEO_PRESENT 0x00100000 | ||
805 | #define FLD_DW8051_VIDEO_FORMAT 0x000F0000 | ||
806 | #define FLD_PREF_DEC_MODE 0x0000FF00 | ||
807 | #define FLD_AUD_CONFIG 0x000000FF | ||
808 | |||
809 | /*****************************************************************************/ | ||
810 | #define DW8051_INT 0x80C | ||
811 | #define FLD_VIDEO_PRESENT_CHANGE 0x80000000 | ||
812 | #define FLD_VIDEO_CHANGE 0x40000000 | ||
813 | #define FLD_RDS_READY 0x20000000 | ||
814 | #define FLD_AC97_INT 0x10000000 | ||
815 | #define FLD_NICAM_BIT_ERROR_TOO_HIGH 0x08000000 | ||
816 | #define FLD_NICAM_LOCK 0x04000000 | ||
817 | #define FLD_NICAM_UNLOCK 0x02000000 | ||
818 | #define FLD_DFT4_TH_CMP 0x01000000 | ||
819 | /* Reserved [23:22] */ | ||
820 | #define FLD_LOCK_IND_INT 0x00200000 | ||
821 | #define FLD_DFT3_TH_CMP 0x00100000 | ||
822 | #define FLD_DFT2_TH_CMP 0x00080000 | ||
823 | #define FLD_DFT1_TH_CMP 0x00040000 | ||
824 | #define FLD_FM2_DFT_TH_CMP 0x00020000 | ||
825 | #define FLD_FM1_DFT_TH_CMP 0x00010000 | ||
826 | #define FLD_VIDEO_PRESENT_EN 0x00008000 | ||
827 | #define FLD_VIDEO_CHANGE_EN 0x00004000 | ||
828 | #define FLD_RDS_READY_EN 0x00002000 | ||
829 | #define FLD_AC97_INT_EN 0x00001000 | ||
830 | #define FLD_NICAM_BIT_ERROR_TOO_HIGH_EN 0x00000800 | ||
831 | #define FLD_NICAM_LOCK_EN 0x00000400 | ||
832 | #define FLD_NICAM_UNLOCK_EN 0x00000200 | ||
833 | #define FLD_DFT4_TH_CMP_EN 0x00000100 | ||
834 | /* Reserved [7] */ | ||
835 | #define FLD_DW8051_INT6_CTL1 0x00000040 | ||
836 | #define FLD_DW8051_INT5_CTL1 0x00000020 | ||
837 | #define FLD_DW8051_INT4_CTL1 0x00000010 | ||
838 | #define FLD_DW8051_INT3_CTL1 0x00000008 | ||
839 | #define FLD_DW8051_INT2_CTL1 0x00000004 | ||
840 | #define FLD_DW8051_INT1_CTL1 0x00000002 | ||
841 | #define FLD_DW8051_INT0_CTL1 0x00000001 | ||
842 | |||
843 | /*****************************************************************************/ | ||
844 | #define GENERAL_CTL 0x810 | ||
845 | #define FLD_RDS_INT 0x80000000 | ||
846 | #define FLD_NBER_INT 0x40000000 | ||
847 | #define FLD_NLL_INT 0x20000000 | ||
848 | #define FLD_IFL_INT 0x10000000 | ||
849 | #define FLD_FDL_INT 0x08000000 | ||
850 | #define FLD_AFC_INT 0x04000000 | ||
851 | #define FLD_AMC_INT 0x02000000 | ||
852 | #define FLD_AC97_INT_CTL 0x01000000 | ||
853 | #define FLD_RDS_INT_DIS 0x00800000 | ||
854 | #define FLD_NBER_INT_DIS 0x00400000 | ||
855 | #define FLD_NLL_INT_DIS 0x00200000 | ||
856 | #define FLD_IFL_INT_DIS 0x00100000 | ||
857 | #define FLD_FDL_INT_DIS 0x00080000 | ||
858 | #define FLD_FC_INT_DIS 0x00040000 | ||
859 | #define FLD_AMC_INT_DIS 0x00020000 | ||
860 | #define FLD_AC97_INT_DIS 0x00010000 | ||
861 | #define FLD_REV_NUM 0x0000FF00 | ||
862 | /* Reserved [7:5] */ | ||
863 | #define FLD_DBX_SOFT_RESET_REG 0x00000010 | ||
864 | #define FLD_AD_SOFT_RESET_REG 0x00000008 | ||
865 | #define FLD_SRC_SOFT_RESET_REG 0x00000004 | ||
866 | #define FLD_CDMOD_SOFT_RESET 0x00000002 | ||
867 | #define FLD_8051_SOFT_RESET 0x00000001 | ||
868 | |||
869 | /*****************************************************************************/ | ||
870 | #define AAGC_CTL 0x814 | ||
871 | #define FLD_AFE_12DB_EN 0x80000000 | ||
872 | #define FLD_AAGC_DEFAULT_EN 0x40000000 | ||
873 | #define FLD_AAGC_DEFAULT 0x3F000000 | ||
874 | /* Reserved [23] */ | ||
875 | #define FLD_AAGC_GAIN 0x00600000 | ||
876 | #define FLD_AAGC_TH 0x001F0000 | ||
877 | /* Reserved [15:14] */ | ||
878 | #define FLD_AAGC_HYST2 0x00003F00 | ||
879 | /* Reserved [7:6] */ | ||
880 | #define FLD_AAGC_HYST1 0x0000003F | ||
881 | |||
882 | /*****************************************************************************/ | ||
883 | #define IF_SRC_CTL 0x818 | ||
884 | #define FLD_DBX_BYPASS 0x80000000 | ||
885 | /* Reserved [30:25] */ | ||
886 | #define FLD_IF_SRC_MODE 0x01000000 | ||
887 | /* Reserved [23:18] */ | ||
888 | #define FLD_IF_SRC_PHASE_INC 0x0001FFFF | ||
889 | |||
890 | /*****************************************************************************/ | ||
891 | #define ANALOG_DEMOD_CTL 0x81C | ||
892 | #define FLD_ROT1_PHACC_PROG 0xFFFF0000 | ||
893 | /* Reserved [15] */ | ||
894 | #define FLD_FM1_DELAY_FIX 0x00007000 | ||
895 | #define FLD_PDF4_SHIFT 0x00000C00 | ||
896 | #define FLD_PDF3_SHIFT 0x00000300 | ||
897 | #define FLD_PDF2_SHIFT 0x000000C0 | ||
898 | #define FLD_PDF1_SHIFT 0x00000030 | ||
899 | #define FLD_FMBYPASS_MODE2 0x00000008 | ||
900 | #define FLD_FMBYPASS_MODE1 0x00000004 | ||
901 | #define FLD_NICAM_MODE 0x00000002 | ||
902 | #define FLD_BTSC_FMRADIO_MODE 0x00000001 | ||
903 | |||
904 | /*****************************************************************************/ | ||
905 | #define ROT_FREQ_CTL 0x820 | ||
906 | #define FLD_ROT3_PHACC_PROG 0xFFFF0000 | ||
907 | #define FLD_ROT2_PHACC_PROG 0x0000FFFF | ||
908 | |||
909 | /*****************************************************************************/ | ||
910 | #define FM_CTL 0x824 | ||
911 | #define FLD_FM2_DC_FB_SHIFT 0xF0000000 | ||
912 | #define FLD_FM2_DC_INT_SHIFT 0x0F000000 | ||
913 | #define FLD_FM2_AFC_RESET 0x00800000 | ||
914 | #define FLD_FM2_DC_PASS_IN 0x00400000 | ||
915 | #define FLD_FM2_DAGC_SHIFT 0x00380000 | ||
916 | #define FLD_FM2_CORDIC_SHIFT 0x00070000 | ||
917 | #define FLD_FM1_DC_FB_SHIFT 0x0000F000 | ||
918 | #define FLD_FM1_DC_INT_SHIFT 0x00000F00 | ||
919 | #define FLD_FM1_AFC_RESET 0x00000080 | ||
920 | #define FLD_FM1_DC_PASS_IN 0x00000040 | ||
921 | #define FLD_FM1_DAGC_SHIFT 0x00000038 | ||
922 | #define FLD_FM1_CORDIC_SHIFT 0x00000007 | ||
923 | |||
924 | /*****************************************************************************/ | ||
925 | #define LPF_PDF_CTL 0x828 | ||
926 | /* Reserved [31:30] */ | ||
927 | #define FLD_LPF32_SHIFT1 0x30000000 | ||
928 | #define FLD_LPF32_SHIFT2 0x0C000000 | ||
929 | #define FLD_LPF160_SHIFTA 0x03000000 | ||
930 | #define FLD_LPF160_SHIFTB 0x00C00000 | ||
931 | #define FLD_LPF160_SHIFTC 0x00300000 | ||
932 | #define FLD_LPF32_COEF_SEL2 0x000C0000 | ||
933 | #define FLD_LPF32_COEF_SEL1 0x00030000 | ||
934 | #define FLD_LPF160_COEF_SELC 0x0000C000 | ||
935 | #define FLD_LPF160_COEF_SELB 0x00003000 | ||
936 | #define FLD_LPF160_COEF_SELA 0x00000C00 | ||
937 | #define FLD_LPF160_IN_EN_REG 0x00000300 | ||
938 | #define FLD_PDF4_PDF_SEL 0x000000C0 | ||
939 | #define FLD_PDF3_PDF_SEL 0x00000030 | ||
940 | #define FLD_PDF2_PDF_SEL 0x0000000C | ||
941 | #define FLD_PDF1_PDF_SEL 0x00000003 | ||
942 | |||
943 | /*****************************************************************************/ | ||
944 | #define DFT1_CTL1 0x82C | ||
945 | #define FLD_DFT1_DWELL 0xFFFF0000 | ||
946 | #define FLD_DFT1_FREQ 0x0000FFFF | ||
947 | |||
948 | /*****************************************************************************/ | ||
949 | #define DFT1_CTL2 0x830 | ||
950 | #define FLD_DFT1_THRESHOLD 0xFFFFFF00 | ||
951 | #define FLD_DFT1_CMP_CTL 0x00000080 | ||
952 | #define FLD_DFT1_AVG 0x00000070 | ||
953 | /* Reserved [3:1] */ | ||
954 | #define FLD_DFT1_START 0x00000001 | ||
955 | |||
956 | /*****************************************************************************/ | ||
957 | #define DFT1_STATUS 0x834 | ||
958 | #define FLD_DFT1_DONE 0x80000000 | ||
959 | #define FLD_DFT1_TH_CMP_STAT 0x40000000 | ||
960 | #define FLD_DFT1_RESULT 0x3FFFFFFF | ||
961 | |||
962 | /*****************************************************************************/ | ||
963 | #define DFT2_CTL1 0x838 | ||
964 | #define FLD_DFT2_DWELL 0xFFFF0000 | ||
965 | #define FLD_DFT2_FREQ 0x0000FFFF | ||
966 | |||
967 | /*****************************************************************************/ | ||
968 | #define DFT2_CTL2 0x83C | ||
969 | #define FLD_DFT2_THRESHOLD 0xFFFFFF00 | ||
970 | #define FLD_DFT2_CMP_CTL 0x00000080 | ||
971 | #define FLD_DFT2_AVG 0x00000070 | ||
972 | /* Reserved [3:1] */ | ||
973 | #define FLD_DFT2_START 0x00000001 | ||
974 | |||
975 | /*****************************************************************************/ | ||
976 | #define DFT2_STATUS 0x840 | ||
977 | #define FLD_DFT2_DONE 0x80000000 | ||
978 | #define FLD_DFT2_TH_CMP_STAT 0x40000000 | ||
979 | #define FLD_DFT2_RESULT 0x3FFFFFFF | ||
980 | |||
981 | /*****************************************************************************/ | ||
982 | #define DFT3_CTL1 0x844 | ||
983 | #define FLD_DFT3_DWELL 0xFFFF0000 | ||
984 | #define FLD_DFT3_FREQ 0x0000FFFF | ||
985 | |||
986 | /*****************************************************************************/ | ||
987 | #define DFT3_CTL2 0x848 | ||
988 | #define FLD_DFT3_THRESHOLD 0xFFFFFF00 | ||
989 | #define FLD_DFT3_CMP_CTL 0x00000080 | ||
990 | #define FLD_DFT3_AVG 0x00000070 | ||
991 | /* Reserved [3:1] */ | ||
992 | #define FLD_DFT3_START 0x00000001 | ||
993 | |||
994 | /*****************************************************************************/ | ||
995 | #define DFT3_STATUS 0x84C | ||
996 | #define FLD_DFT3_DONE 0x80000000 | ||
997 | #define FLD_DFT3_TH_CMP_STAT 0x40000000 | ||
998 | #define FLD_DFT3_RESULT 0x3FFFFFFF | ||
999 | |||
1000 | /*****************************************************************************/ | ||
1001 | #define DFT4_CTL1 0x850 | ||
1002 | #define FLD_DFT4_DWELL 0xFFFF0000 | ||
1003 | #define FLD_DFT4_FREQ 0x0000FFFF | ||
1004 | |||
1005 | /*****************************************************************************/ | ||
1006 | #define DFT4_CTL2 0x854 | ||
1007 | #define FLD_DFT4_THRESHOLD 0xFFFFFF00 | ||
1008 | #define FLD_DFT4_CMP_CTL 0x00000080 | ||
1009 | #define FLD_DFT4_AVG 0x00000070 | ||
1010 | /* Reserved [3:1] */ | ||
1011 | #define FLD_DFT4_START 0x00000001 | ||
1012 | |||
1013 | /*****************************************************************************/ | ||
1014 | #define DFT4_STATUS 0x858 | ||
1015 | #define FLD_DFT4_DONE 0x80000000 | ||
1016 | #define FLD_DFT4_TH_CMP_STAT 0x40000000 | ||
1017 | #define FLD_DFT4_RESULT 0x3FFFFFFF | ||
1018 | |||
1019 | /*****************************************************************************/ | ||
1020 | #define AM_MTS_DET 0x85C | ||
1021 | #define FLD_AM_MTS_MODE 0x80000000 | ||
1022 | /* Reserved [30:26] */ | ||
1023 | #define FLD_AM_SUB 0x02000000 | ||
1024 | #define FLD_AM_GAIN_EN 0x01000000 | ||
1025 | /* Reserved [23:16] */ | ||
1026 | #define FLD_AMMTS_GAIN_SCALE 0x0000E000 | ||
1027 | #define FLD_MTS_PDF_SHIFT 0x00001800 | ||
1028 | #define FLD_AM_REG_GAIN 0x00000700 | ||
1029 | #define FLD_AGC_REF 0x000000FF | ||
1030 | |||
1031 | /*****************************************************************************/ | ||
1032 | #define ANALOG_MUX_CTL 0x860 | ||
1033 | /* Reserved [31:29] */ | ||
1034 | #define FLD_MUX21_SEL 0x10000000 | ||
1035 | #define FLD_MUX20_SEL 0x08000000 | ||
1036 | #define FLD_MUX19_SEL 0x04000000 | ||
1037 | #define FLD_MUX18_SEL 0x02000000 | ||
1038 | #define FLD_MUX17_SEL 0x01000000 | ||
1039 | #define FLD_MUX16_SEL 0x00800000 | ||
1040 | #define FLD_MUX15_SEL 0x00400000 | ||
1041 | #define FLD_MUX14_SEL 0x00300000 | ||
1042 | #define FLD_MUX13_SEL 0x000C0000 | ||
1043 | #define FLD_MUX12_SEL 0x00020000 | ||
1044 | #define FLD_MUX11_SEL 0x00018000 | ||
1045 | #define FLD_MUX10_SEL 0x00004000 | ||
1046 | #define FLD_MUX9_SEL 0x00002000 | ||
1047 | #define FLD_MUX8_SEL 0x00001000 | ||
1048 | #define FLD_MUX7_SEL 0x00000800 | ||
1049 | #define FLD_MUX6_SEL 0x00000600 | ||
1050 | #define FLD_MUX5_SEL 0x00000100 | ||
1051 | #define FLD_MUX4_SEL 0x000000C0 | ||
1052 | #define FLD_MUX3_SEL 0x00000030 | ||
1053 | #define FLD_MUX2_SEL 0x0000000C | ||
1054 | #define FLD_MUX1_SEL 0x00000003 | ||
1055 | |||
1056 | /*****************************************************************************/ | ||
1057 | /* Cx231xx redefine */ | ||
1058 | #define DPLL_CTRL1 0x864 | ||
1059 | #define DIG_PLL_CTL1 0x864 | ||
1060 | |||
1061 | #define FLD_PLL_STATUS 0x07000000 | ||
1062 | #define FLD_BANDWIDTH_SELECT 0x00030000 | ||
1063 | #define FLD_PLL_SHIFT_REG 0x00007000 | ||
1064 | #define FLD_PHASE_SHIFT 0x000007FF | ||
1065 | |||
1066 | /*****************************************************************************/ | ||
1067 | /* Cx231xx redefine */ | ||
1068 | #define DPLL_CTRL2 0x868 | ||
1069 | #define DIG_PLL_CTL2 0x868 | ||
1070 | #define FLD_PLL_UNLOCK_THR 0xFF000000 | ||
1071 | #define FLD_PLL_LOCK_THR 0x00FF0000 | ||
1072 | /* Reserved [15:8] */ | ||
1073 | #define FLD_AM_PDF_SEL2 0x000000C0 | ||
1074 | #define FLD_AM_PDF_SEL1 0x00000030 | ||
1075 | #define FLD_DPLL_FSM_CTRL 0x0000000C | ||
1076 | /* Reserved [1] */ | ||
1077 | #define FLD_PLL_PILOT_DET 0x00000001 | ||
1078 | |||
1079 | /*****************************************************************************/ | ||
1080 | /* Cx231xx redefine */ | ||
1081 | #define DPLL_CTRL3 0x86C | ||
1082 | #define DIG_PLL_CTL3 0x86C | ||
1083 | #define FLD_DISABLE_LOOP 0x01000000 | ||
1084 | #define FLD_A1_DS1_SEL 0x000C0000 | ||
1085 | #define FLD_A1_DS2_SEL 0x00030000 | ||
1086 | #define FLD_A1_KI 0x0000FF00 | ||
1087 | #define FLD_A1_KD 0x000000FF | ||
1088 | |||
1089 | /*****************************************************************************/ | ||
1090 | /* Cx231xx redefine */ | ||
1091 | #define DPLL_CTRL4 0x870 | ||
1092 | #define DIG_PLL_CTL4 0x870 | ||
1093 | #define FLD_A2_DS1_SEL 0x000C0000 | ||
1094 | #define FLD_A2_DS2_SEL 0x00030000 | ||
1095 | #define FLD_A2_KI 0x0000FF00 | ||
1096 | #define FLD_A2_KD 0x000000FF | ||
1097 | |||
1098 | /*****************************************************************************/ | ||
1099 | /* Cx231xx redefine */ | ||
1100 | #define DPLL_CTRL5 0x874 | ||
1101 | #define DIG_PLL_CTL5 0x874 | ||
1102 | #define FLD_TRK_DS1_SEL 0x000C0000 | ||
1103 | #define FLD_TRK_DS2_SEL 0x00030000 | ||
1104 | #define FLD_TRK_KI 0x0000FF00 | ||
1105 | #define FLD_TRK_KD 0x000000FF | ||
1106 | |||
1107 | /*****************************************************************************/ | ||
1108 | #define DEEMPH_GAIN_CTL 0x878 | ||
1109 | #define FLD_DEEMPH2_GAIN 0xFFFF0000 | ||
1110 | #define FLD_DEEMPH1_GAIN 0x0000FFFF | ||
1111 | |||
1112 | /*****************************************************************************/ | ||
1113 | /* Cx231xx redefine */ | ||
1114 | #define DEEMPH_COEFF1 0x87C | ||
1115 | #define DEEMPH_COEF1 0x87C | ||
1116 | #define FLD_DEEMPH_B0 0xFFFF0000 | ||
1117 | #define FLD_DEEMPH_A0 0x0000FFFF | ||
1118 | |||
1119 | /*****************************************************************************/ | ||
1120 | /* Cx231xx redefine */ | ||
1121 | #define DEEMPH_COEFF2 0x880 | ||
1122 | #define DEEMPH_COEF2 0x880 | ||
1123 | #define FLD_DEEMPH_B1 0xFFFF0000 | ||
1124 | #define FLD_DEEMPH_A1 0x0000FFFF | ||
1125 | |||
1126 | /*****************************************************************************/ | ||
1127 | #define DBX1_CTL1 0x884 | ||
1128 | #define FLD_DBX1_WBE_GAIN 0xFFFF0000 | ||
1129 | #define FLD_DBX1_IN_GAIN 0x0000FFFF | ||
1130 | |||
1131 | /*****************************************************************************/ | ||
1132 | #define DBX1_CTL2 0x888 | ||
1133 | #define FLD_DBX1_SE_BYPASS 0xFFFF0000 | ||
1134 | #define FLD_DBX1_SE_GAIN 0x0000FFFF | ||
1135 | |||
1136 | /*****************************************************************************/ | ||
1137 | #define DBX1_RMS_SE 0x88C | ||
1138 | #define FLD_DBX1_RMS_WBE 0xFFFF0000 | ||
1139 | #define FLD_DBX1_RMS_SE_FLD 0x0000FFFF | ||
1140 | |||
1141 | /*****************************************************************************/ | ||
1142 | #define DBX2_CTL1 0x890 | ||
1143 | #define FLD_DBX2_WBE_GAIN 0xFFFF0000 | ||
1144 | #define FLD_DBX2_IN_GAIN 0x0000FFFF | ||
1145 | |||
1146 | /*****************************************************************************/ | ||
1147 | #define DBX2_CTL2 0x894 | ||
1148 | #define FLD_DBX2_SE_BYPASS 0xFFFF0000 | ||
1149 | #define FLD_DBX2_SE_GAIN 0x0000FFFF | ||
1150 | |||
1151 | /*****************************************************************************/ | ||
1152 | #define DBX2_RMS_SE 0x898 | ||
1153 | #define FLD_DBX2_RMS_WBE 0xFFFF0000 | ||
1154 | #define FLD_DBX2_RMS_SE_FLD 0x0000FFFF | ||
1155 | |||
1156 | /*****************************************************************************/ | ||
1157 | #define AM_FM_DIFF 0x89C | ||
1158 | /* Reserved [31] */ | ||
1159 | #define FLD_FM_DIFF_OUT 0x7FFF0000 | ||
1160 | /* Reserved [15] */ | ||
1161 | #define FLD_AM_DIFF_OUT 0x00007FFF | ||
1162 | |||
1163 | /*****************************************************************************/ | ||
1164 | #define NICAM_FAW 0x8A0 | ||
1165 | #define FLD_FAWDETWINEND 0xFC000000 | ||
1166 | #define FLD_FAWDETWINSTR 0x03FF0000 | ||
1167 | /* Reserved [15:12] */ | ||
1168 | #define FLD_FAWDETTHRSHLD3 0x00000F00 | ||
1169 | #define FLD_FAWDETTHRSHLD2 0x000000F0 | ||
1170 | #define FLD_FAWDETTHRSHLD1 0x0000000F | ||
1171 | |||
1172 | /*****************************************************************************/ | ||
1173 | /* Cx231xx redefine */ | ||
1174 | #define DEEMPH_GAIN 0x8A4 | ||
1175 | #define NICAM_DEEMPHGAIN 0x8A4 | ||
1176 | /* Reserved [31:18] */ | ||
1177 | #define FLD_DEEMPHGAIN 0x0003FFFF | ||
1178 | |||
1179 | /*****************************************************************************/ | ||
1180 | /* Cx231xx redefine */ | ||
1181 | #define DEEMPH_NUMER1 0x8A8 | ||
1182 | #define NICAM_DEEMPHNUMER1 0x8A8 | ||
1183 | /* Reserved [31:18] */ | ||
1184 | #define FLD_DEEMPHNUMER1 0x0003FFFF | ||
1185 | |||
1186 | /*****************************************************************************/ | ||
1187 | /* Cx231xx redefine */ | ||
1188 | #define DEEMPH_NUMER2 0x8AC | ||
1189 | #define NICAM_DEEMPHNUMER2 0x8AC | ||
1190 | /* Reserved [31:18] */ | ||
1191 | #define FLD_DEEMPHNUMER2 0x0003FFFF | ||
1192 | |||
1193 | /*****************************************************************************/ | ||
1194 | /* Cx231xx redefine */ | ||
1195 | #define DEEMPH_DENOM1 0x8B0 | ||
1196 | #define NICAM_DEEMPHDENOM1 0x8B0 | ||
1197 | /* Reserved [31:18] */ | ||
1198 | #define FLD_DEEMPHDENOM1 0x0003FFFF | ||
1199 | |||
1200 | /*****************************************************************************/ | ||
1201 | /* Cx231xx redefine */ | ||
1202 | #define DEEMPH_DENOM2 0x8B4 | ||
1203 | #define NICAM_DEEMPHDENOM2 0x8B4 | ||
1204 | /* Reserved [31:18] */ | ||
1205 | #define FLD_DEEMPHDENOM2 0x0003FFFF | ||
1206 | |||
1207 | /*****************************************************************************/ | ||
1208 | #define NICAM_ERRLOG_CTL1 0x8B8 | ||
1209 | /* Reserved [31:28] */ | ||
1210 | #define FLD_ERRINTRPTTHSHLD1 0x0FFF0000 | ||
1211 | /* Reserved [15:12] */ | ||
1212 | #define FLD_ERRLOGPERIOD 0x00000FFF | ||
1213 | |||
1214 | /*****************************************************************************/ | ||
1215 | #define NICAM_ERRLOG_CTL2 0x8BC | ||
1216 | /* Reserved [31:28] */ | ||
1217 | #define FLD_ERRINTRPTTHSHLD3 0x0FFF0000 | ||
1218 | /* Reserved [15:12] */ | ||
1219 | #define FLD_ERRINTRPTTHSHLD2 0x00000FFF | ||
1220 | |||
1221 | /*****************************************************************************/ | ||
1222 | #define NICAM_ERRLOG_STS1 0x8C0 | ||
1223 | /* Reserved [31:28] */ | ||
1224 | #define FLD_ERRLOG2 0x0FFF0000 | ||
1225 | /* Reserved [15:12] */ | ||
1226 | #define FLD_ERRLOG1 0x00000FFF | ||
1227 | |||
1228 | /*****************************************************************************/ | ||
1229 | #define NICAM_ERRLOG_STS2 0x8C4 | ||
1230 | /* Reserved [31:12] */ | ||
1231 | #define FLD_ERRLOG3 0x00000FFF | ||
1232 | |||
1233 | /*****************************************************************************/ | ||
1234 | #define NICAM_STATUS 0x8C8 | ||
1235 | /* Reserved [31:20] */ | ||
1236 | #define FLD_NICAM_CIB 0x000C0000 | ||
1237 | #define FLD_NICAM_LOCK_STAT 0x00020000 | ||
1238 | #define FLD_NICAM_MUTE 0x00010000 | ||
1239 | #define FLD_NICAMADDIT_DATA 0x0000FFE0 | ||
1240 | #define FLD_NICAMCNTRL 0x0000001F | ||
1241 | |||
1242 | /*****************************************************************************/ | ||
1243 | #define DEMATRIX_CTL 0x8CC | ||
1244 | #define FLD_AC97_IN_SHIFT 0xF0000000 | ||
1245 | #define FLD_I2S_IN_SHIFT 0x0F000000 | ||
1246 | #define FLD_DEMATRIX_SEL_CTL 0x00FF0000 | ||
1247 | /* Reserved [15:11] */ | ||
1248 | #define FLD_DMTRX_BYPASS 0x00000400 | ||
1249 | #define FLD_DEMATRIX_MODE 0x00000300 | ||
1250 | /* Reserved [7:6] */ | ||
1251 | #define FLD_PH_DBX_SEL 0x00000020 | ||
1252 | #define FLD_PH_CH_SEL 0x00000010 | ||
1253 | #define FLD_PHASE_FIX 0x0000000F | ||
1254 | |||
1255 | /*****************************************************************************/ | ||
1256 | #define PATH1_CTL1 0x8D0 | ||
1257 | /* Reserved [31:29] */ | ||
1258 | #define FLD_PATH1_MUTE_CTL 0x1F000000 | ||
1259 | /* Reserved [23:22] */ | ||
1260 | #define FLD_PATH1_AVC_CG 0x00300000 | ||
1261 | #define FLD_PATH1_AVC_RT 0x000F0000 | ||
1262 | #define FLD_PATH1_AVC_AT 0x0000F000 | ||
1263 | #define FLD_PATH1_AVC_STEREO 0x00000800 | ||
1264 | #define FLD_PATH1_AVC_CR 0x00000700 | ||
1265 | #define FLD_PATH1_AVC_RMS_CON 0x000000F0 | ||
1266 | #define FLD_PATH1_SEL_CTL 0x0000000F | ||
1267 | |||
1268 | /*****************************************************************************/ | ||
1269 | #define PATH1_VOL_CTL 0x8D4 | ||
1270 | #define FLD_PATH1_AVC_THRESHOLD 0x7FFF0000 | ||
1271 | #define FLD_PATH1_BAL_LEFT 0x00008000 | ||
1272 | #define FLD_PATH1_BAL_LEVEL 0x00007F00 | ||
1273 | #define FLD_PATH1_VOLUME 0x000000FF | ||
1274 | |||
1275 | /*****************************************************************************/ | ||
1276 | #define PATH1_EQ_CTL 0x8D8 | ||
1277 | /* Reserved [31:30] */ | ||
1278 | #define FLD_PATH1_EQ_TREBLE_VOL 0x3F000000 | ||
1279 | /* Reserved [23:22] */ | ||
1280 | #define FLD_PATH1_EQ_MID_VOL 0x003F0000 | ||
1281 | /* Reserved [15:14] */ | ||
1282 | #define FLD_PATH1_EQ_BASS_VOL 0x00003F00 | ||
1283 | /* Reserved [7:1] */ | ||
1284 | #define FLD_PATH1_EQ_BAND_SEL 0x00000001 | ||
1285 | |||
1286 | /*****************************************************************************/ | ||
1287 | #define PATH1_SC_CTL 0x8DC | ||
1288 | #define FLD_PATH1_SC_THRESHOLD 0x7FFF0000 | ||
1289 | #define FLD_PATH1_SC_RT 0x0000F000 | ||
1290 | #define FLD_PATH1_SC_AT 0x00000F00 | ||
1291 | #define FLD_PATH1_SC_STEREO 0x00000080 | ||
1292 | #define FLD_PATH1_SC_CR 0x00000070 | ||
1293 | #define FLD_PATH1_SC_RMS_CON 0x0000000F | ||
1294 | |||
1295 | /*****************************************************************************/ | ||
1296 | #define PATH2_CTL1 0x8E0 | ||
1297 | /* Reserved [31:26] */ | ||
1298 | #define FLD_PATH2_MUTE_CTL 0x03000000 | ||
1299 | /* Reserved [23:22] */ | ||
1300 | #define FLD_PATH2_AVC_CG 0x00300000 | ||
1301 | #define FLD_PATH2_AVC_RT 0x000F0000 | ||
1302 | #define FLD_PATH2_AVC_AT 0x0000F000 | ||
1303 | #define FLD_PATH2_AVC_STEREO 0x00000800 | ||
1304 | #define FLD_PATH2_AVC_CR 0x00000700 | ||
1305 | #define FLD_PATH2_AVC_RMS_CON 0x000000F0 | ||
1306 | #define FLD_PATH2_SEL_CTL 0x0000000F | ||
1307 | |||
1308 | /*****************************************************************************/ | ||
1309 | #define PATH2_VOL_CTL 0x8E4 | ||
1310 | #define FLD_PATH2_AVC_THRESHOLD 0xFFFF0000 | ||
1311 | #define FLD_PATH2_BAL_LEFT 0x00008000 | ||
1312 | #define FLD_PATH2_BAL_LEVEL 0x00007F00 | ||
1313 | #define FLD_PATH2_VOLUME 0x000000FF | ||
1314 | |||
1315 | /*****************************************************************************/ | ||
1316 | #define PATH2_EQ_CTL 0x8E8 | ||
1317 | /* Reserved [31:30] */ | ||
1318 | #define FLD_PATH2_EQ_TREBLE_VOL 0x3F000000 | ||
1319 | /* Reserved [23:22] */ | ||
1320 | #define FLD_PATH2_EQ_MID_VOL 0x003F0000 | ||
1321 | /* Reserved [15:14] */ | ||
1322 | #define FLD_PATH2_EQ_BASS_VOL 0x00003F00 | ||
1323 | /* Reserved [7:1] */ | ||
1324 | #define FLD_PATH2_EQ_BAND_SEL 0x00000001 | ||
1325 | |||
1326 | /*****************************************************************************/ | ||
1327 | #define PATH2_SC_CTL 0x8EC | ||
1328 | #define FLD_PATH2_SC_THRESHOLD 0xFFFF0000 | ||
1329 | #define FLD_PATH2_SC_RT 0x0000F000 | ||
1330 | #define FLD_PATH2_SC_AT 0x00000F00 | ||
1331 | #define FLD_PATH2_SC_STEREO 0x00000080 | ||
1332 | #define FLD_PATH2_SC_CR 0x00000070 | ||
1333 | #define FLD_PATH2_SC_RMS_CON 0x0000000F | ||
1334 | |||
1335 | /*****************************************************************************/ | ||
1336 | #define SRC_CTL 0x8F0 | ||
1337 | #define FLD_SRC_STATUS 0xFFFFFF00 | ||
1338 | #define FLD_FIFO_LF_EN 0x000000FC | ||
1339 | #define FLD_BYPASS_LI 0x00000002 | ||
1340 | #define FLD_BYPASS_PF 0x00000001 | ||
1341 | |||
1342 | /*****************************************************************************/ | ||
1343 | #define SRC_LF_COEF 0x8F4 | ||
1344 | #define FLD_LOOP_FILTER_COEF2 0xFFFF0000 | ||
1345 | #define FLD_LOOP_FILTER_COEF1 0x0000FFFF | ||
1346 | |||
1347 | /*****************************************************************************/ | ||
1348 | #define SRC1_CTL 0x8F8 | ||
1349 | /* Reserved [31:28] */ | ||
1350 | #define FLD_SRC1_FIFO_RD_TH 0x0F000000 | ||
1351 | /* Reserved [23:18] */ | ||
1352 | #define FLD_SRC1_PHASE_INC 0x0003FFFF | ||
1353 | |||
1354 | /*****************************************************************************/ | ||
1355 | #define SRC2_CTL 0x8FC | ||
1356 | /* Reserved [31:28] */ | ||
1357 | #define FLD_SRC2_FIFO_RD_TH 0x0F000000 | ||
1358 | /* Reserved [23:18] */ | ||
1359 | #define FLD_SRC2_PHASE_INC 0x0003FFFF | ||
1360 | |||
1361 | /*****************************************************************************/ | ||
1362 | #define SRC3_CTL 0x900 | ||
1363 | /* Reserved [31:28] */ | ||
1364 | #define FLD_SRC3_FIFO_RD_TH 0x0F000000 | ||
1365 | /* Reserved [23:18] */ | ||
1366 | #define FLD_SRC3_PHASE_INC 0x0003FFFF | ||
1367 | |||
1368 | /*****************************************************************************/ | ||
1369 | #define SRC4_CTL 0x904 | ||
1370 | /* Reserved [31:28] */ | ||
1371 | #define FLD_SRC4_FIFO_RD_TH 0x0F000000 | ||
1372 | /* Reserved [23:18] */ | ||
1373 | #define FLD_SRC4_PHASE_INC 0x0003FFFF | ||
1374 | |||
1375 | /*****************************************************************************/ | ||
1376 | #define SRC5_CTL 0x908 | ||
1377 | /* Reserved [31:28] */ | ||
1378 | #define FLD_SRC5_FIFO_RD_TH 0x0F000000 | ||
1379 | /* Reserved [23:18] */ | ||
1380 | #define FLD_SRC5_PHASE_INC 0x0003FFFF | ||
1381 | |||
1382 | /*****************************************************************************/ | ||
1383 | #define SRC6_CTL 0x90C | ||
1384 | /* Reserved [31:28] */ | ||
1385 | #define FLD_SRC6_FIFO_RD_TH 0x0F000000 | ||
1386 | /* Reserved [23:18] */ | ||
1387 | #define FLD_SRC6_PHASE_INC 0x0003FFFF | ||
1388 | |||
1389 | /*****************************************************************************/ | ||
1390 | #define BAND_OUT_SEL 0x910 | ||
1391 | #define FLD_SRC6_IN_SEL 0xC0000000 | ||
1392 | #define FLD_SRC6_CLK_SEL 0x30000000 | ||
1393 | #define FLD_SRC5_IN_SEL 0x0C000000 | ||
1394 | #define FLD_SRC5_CLK_SEL 0x03000000 | ||
1395 | #define FLD_SRC4_IN_SEL 0x00C00000 | ||
1396 | #define FLD_SRC4_CLK_SEL 0x00300000 | ||
1397 | #define FLD_SRC3_IN_SEL 0x000C0000 | ||
1398 | #define FLD_SRC3_CLK_SEL 0x00030000 | ||
1399 | #define FLD_BASEBAND_BYPASS_CTL 0x0000FF00 | ||
1400 | #define FLD_AC97_SRC_SEL 0x000000C0 | ||
1401 | #define FLD_I2S_SRC_SEL 0x00000030 | ||
1402 | #define FLD_PARALLEL2_SRC_SEL 0x0000000C | ||
1403 | #define FLD_PARALLEL1_SRC_SEL 0x00000003 | ||
1404 | |||
1405 | /*****************************************************************************/ | ||
1406 | #define I2S_IN_CTL 0x914 | ||
1407 | /* Reserved [31:11] */ | ||
1408 | #define FLD_I2S_UP2X_BW20K 0x00000400 | ||
1409 | #define FLD_I2S_UP2X_BYPASS 0x00000200 | ||
1410 | #define FLD_I2S_IN_MASTER_MODE 0x00000100 | ||
1411 | #define FLD_I2S_IN_SONY_MODE 0x00000080 | ||
1412 | #define FLD_I2S_IN_RIGHT_JUST 0x00000040 | ||
1413 | #define FLD_I2S_IN_WS_SEL 0x00000020 | ||
1414 | #define FLD_I2S_IN_BCN_DEL 0x0000001F | ||
1415 | |||
1416 | /*****************************************************************************/ | ||
1417 | #define I2S_OUT_CTL 0x918 | ||
1418 | /* Reserved [31:17] */ | ||
1419 | #define FLD_I2S_OUT_SOFT_RESET_EN 0x00010000 | ||
1420 | /* Reserved [15:9] */ | ||
1421 | #define FLD_I2S_OUT_MASTER_MODE 0x00000100 | ||
1422 | #define FLD_I2S_OUT_SONY_MODE 0x00000080 | ||
1423 | #define FLD_I2S_OUT_RIGHT_JUST 0x00000040 | ||
1424 | #define FLD_I2S_OUT_WS_SEL 0x00000020 | ||
1425 | #define FLD_I2S_OUT_BCN_DEL 0x0000001F | ||
1426 | |||
1427 | |||
1428 | /*****************************************************************************/ | ||
1429 | #define AC97_CTL 0x91C | ||
1430 | /* Reserved [31:26] */ | ||
1431 | #define FLD_AC97_UP2X_BW20K 0x02000000 | ||
1432 | #define FLD_AC97_UP2X_BYPASS 0x01000000 | ||
1433 | /* Reserved [23:17] */ | ||
1434 | #define FLD_AC97_RST_ACL 0x00010000 | ||
1435 | /* Reserved [15:9] */ | ||
1436 | #define FLD_AC97_WAKE_UP_SYNC 0x00000100 | ||
1437 | /* Reserved [7:1] */ | ||
1438 | #define FLD_AC97_SHUTDOWN 0x00000001 | ||
1439 | |||
1440 | |||
1441 | /* Cx231xx redefine */ | ||
1442 | #define QPSK_IAGC_CTL1 0x94c | ||
1443 | #define QPSK_IAGC_CTL2 0x950 | ||
1444 | #define QPSK_FEPR_FREQ 0x954 | ||
1445 | #define QPSK_BTL_CTL1 0x958 | ||
1446 | #define QPSK_BTL_CTL2 0x95c | ||
1447 | #define QPSK_CTL_CTL1 0x960 | ||
1448 | #define QPSK_CTL_CTL2 0x964 | ||
1449 | #define QPSK_MF_FAGC_CTL 0x968 | ||
1450 | #define QPSK_EQ_CTL 0x96c | ||
1451 | #define QPSK_LOCK_CTL 0x970 | ||
1452 | |||
1453 | |||
1454 | /*****************************************************************************/ | ||
1455 | #define FM1_DFT_CTL 0x9A8 | ||
1456 | #define FLD_FM1_DFT_THRESHOLD 0xFFFF0000 | ||
1457 | /* Reserved [15:8] */ | ||
1458 | #define FLD_FM1_DFT_CMP_CTL 0x00000080 | ||
1459 | #define FLD_FM1_DFT_AVG 0x00000070 | ||
1460 | /* Reserved [3:1] */ | ||
1461 | #define FLD_FM1_DFT_START 0x00000001 | ||
1462 | |||
1463 | /*****************************************************************************/ | ||
1464 | #define FM1_DFT_STATUS 0x9AC | ||
1465 | #define FLD_FM1_DFT_DONE 0x80000000 | ||
1466 | /* Reserved [30:19] */ | ||
1467 | #define FLD_FM_DFT_TH_CMP 0x00040000 | ||
1468 | #define FLD_FM1_DFT 0x0003FFFF | ||
1469 | |||
1470 | /*****************************************************************************/ | ||
1471 | #define FM2_DFT_CTL 0x9B0 | ||
1472 | #define FLD_FM2_DFT_THRESHOLD 0xFFFF0000 | ||
1473 | /* Reserved [15:8] */ | ||
1474 | #define FLD_FM2_DFT_CMP_CTL 0x00000080 | ||
1475 | #define FLD_FM2_DFT_AVG 0x00000070 | ||
1476 | /* Reserved [3:1] */ | ||
1477 | #define FLD_FM2_DFT_START 0x00000001 | ||
1478 | |||
1479 | /*****************************************************************************/ | ||
1480 | #define FM2_DFT_STATUS 0x9B4 | ||
1481 | #define FLD_FM2_DFT_DONE 0x80000000 | ||
1482 | /* Reserved [30:19] */ | ||
1483 | #define FLD_FM2_DFT_TH_CMP_STAT 0x00040000 | ||
1484 | #define FLD_FM2_DFT 0x0003FFFF | ||
1485 | |||
1486 | /*****************************************************************************/ | ||
1487 | /* Cx231xx redefine */ | ||
1488 | #define AAGC_STATUS_REG 0x9B8 | ||
1489 | #define AAGC_STATUS 0x9B8 | ||
1490 | /* Reserved [31:27] */ | ||
1491 | #define FLD_FM2_DAGC_OUT 0x07000000 | ||
1492 | /* Reserved [23:19] */ | ||
1493 | #define FLD_FM1_DAGC_OUT 0x00070000 | ||
1494 | /* Reserved [15:6] */ | ||
1495 | #define FLD_AFE_VGA_OUT 0x0000003F | ||
1496 | |||
1497 | |||
1498 | |||
1499 | /*****************************************************************************/ | ||
1500 | #define MTS_GAIN_STATUS 0x9BC | ||
1501 | /* Reserved [31:14] */ | ||
1502 | #define FLD_MTS_GAIN 0x00003FFF | ||
1503 | |||
1504 | #define RDS_OUT 0x9C0 | ||
1505 | #define FLD_RDS_Q 0xFFFF0000 | ||
1506 | #define FLD_RDS_I 0x0000FFFF | ||
1507 | |||
1508 | /*****************************************************************************/ | ||
1509 | #define AUTOCONFIG_REG 0x9C4 | ||
1510 | /* Reserved [31:4] */ | ||
1511 | #define FLD_AUTOCONFIG_MODE 0x0000000F | ||
1512 | |||
1513 | #define FM_AFC 0x9C8 | ||
1514 | #define FLD_FM2_AFC 0xFFFF0000 | ||
1515 | #define FLD_FM1_AFC 0x0000FFFF | ||
1516 | |||
1517 | /*****************************************************************************/ | ||
1518 | /* Cx231xx redefine */ | ||
1519 | #define NEW_SPARE 0x9CC | ||
1520 | #define NEW_SPARE_REG 0x9CC | ||
1521 | |||
1522 | /*****************************************************************************/ | ||
1523 | #define DBX_ADJ 0x9D0 | ||
1524 | /* Reserved [31:28] */ | ||
1525 | #define FLD_DBX2_ADJ 0x0FFF0000 | ||
1526 | /* Reserved [15:12] */ | ||
1527 | #define FLD_DBX1_ADJ 0x00000FFF | ||
1528 | |||
1529 | #define VID_FMT_AUTO 0 | ||
1530 | #define VID_FMT_NTSC_M 1 | ||
1531 | #define VID_FMT_NTSC_J 2 | ||
1532 | #define VID_FMT_NTSC_443 3 | ||
1533 | #define VID_FMT_PAL_BDGHI 4 | ||
1534 | #define VID_FMT_PAL_M 5 | ||
1535 | #define VID_FMT_PAL_N 6 | ||
1536 | #define VID_FMT_PAL_NC 7 | ||
1537 | #define VID_FMT_PAL_60 8 | ||
1538 | #define VID_FMT_SECAM 12 | ||
1539 | #define VID_FMT_SECAM_60 13 | ||
1540 | |||
1541 | #define INPUT_MODE_CVBS_0 0 /* INPUT_MODE_VALUE(0) */ | ||
1542 | #define INPUT_MODE_YC_1 1 /* INPUT_MODE_VALUE(1) */ | ||
1543 | #define INPUT_MODE_YC2_2 2 /* INPUT_MODE_VALUE(2) */ | ||
1544 | #define INPUT_MODE_YUV_3 3 /* INPUT_MODE_VALUE(3) */ | ||
1545 | |||
1546 | |||
1547 | #define LUMA_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ | ||
1548 | #define LUMA_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ | ||
1549 | #define LUMA_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ | ||
1550 | |||
1551 | #define UV_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ | ||
1552 | #define UV_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ | ||
1553 | #define UV_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ | ||
1554 | |||
1555 | #define TWO_TAP_FILT 0 | ||
1556 | #define THREE_TAP_FILT 1 | ||
1557 | #define FOUR_TAP_FILT 2 | ||
1558 | #define FIVE_TAP_FILT 3 | ||
1559 | |||
1560 | #define AUD_CHAN_SRC_PARALLEL 0 | ||
1561 | #define AUD_CHAN_SRC_I2S_INPUT 1 | ||
1562 | #define AUD_CHAN_SRC_FLATIRON 2 | ||
1563 | #define AUD_CHAN_SRC_PARALLEL3 3 | ||
1564 | |||
1565 | #define OUT_MODE_601 0 | ||
1566 | #define OUT_MODE_656 1 | ||
1567 | #define OUT_MODE_VIP11 2 | ||
1568 | #define OUT_MODE_VIP20 3 | ||
1569 | |||
1570 | #define PHASE_INC_49MHZ 0x0DF22 | ||
1571 | #define PHASE_INC_56MHZ 0x0FA5B | ||
1572 | #define PHASE_INC_28MHZ 0x010000 | ||
1573 | |||
1574 | #endif | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c new file mode 100644 index 000000000000..e370160973f4 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-vbi.c | |||
@@ -0,0 +1,693 @@ | |||
1 | /* | ||
2 | cx231xx_vbi.c - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on cx88 driver | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/bitmap.h> | ||
27 | #include <linux/usb.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/version.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/mutex.h> | ||
32 | |||
33 | #include <media/v4l2-common.h> | ||
34 | #include <media/v4l2-ioctl.h> | ||
35 | #include <media/v4l2-chip-ident.h> | ||
36 | #include <media/msp3400.h> | ||
37 | #include <media/tuner.h> | ||
38 | |||
39 | #include "cx231xx.h" | ||
40 | #include "cx231xx-vbi.h" | ||
41 | |||
42 | static inline void print_err_status(struct cx231xx *dev, | ||
43 | int packet, int status) | ||
44 | { | ||
45 | char *errmsg = "Unknown"; | ||
46 | |||
47 | switch (status) { | ||
48 | case -ENOENT: | ||
49 | errmsg = "unlinked synchronuously"; | ||
50 | break; | ||
51 | case -ECONNRESET: | ||
52 | errmsg = "unlinked asynchronuously"; | ||
53 | break; | ||
54 | case -ENOSR: | ||
55 | errmsg = "Buffer error (overrun)"; | ||
56 | break; | ||
57 | case -EPIPE: | ||
58 | errmsg = "Stalled (device not responding)"; | ||
59 | break; | ||
60 | case -EOVERFLOW: | ||
61 | errmsg = "Babble (bad cable?)"; | ||
62 | break; | ||
63 | case -EPROTO: | ||
64 | errmsg = "Bit-stuff error (bad cable?)"; | ||
65 | break; | ||
66 | case -EILSEQ: | ||
67 | errmsg = "CRC/Timeout (could be anything)"; | ||
68 | break; | ||
69 | case -ETIME: | ||
70 | errmsg = "Device does not respond"; | ||
71 | break; | ||
72 | } | ||
73 | if (packet < 0) { | ||
74 | cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status, errmsg); | ||
75 | } else { | ||
76 | cx231xx_err(DRIVER_NAME "URB packet %d, status %d [%s].\n", | ||
77 | packet, status, errmsg); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Controls the isoc copy of each urb packet | ||
83 | */ | ||
84 | static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) | ||
85 | { | ||
86 | struct cx231xx_buffer *buf; | ||
87 | struct cx231xx_dmaqueue *dma_q = urb->context; | ||
88 | int rc = 1; | ||
89 | unsigned char *p_buffer; | ||
90 | u32 bytes_parsed = 0, buffer_size = 0; | ||
91 | u8 sav_eav = 0; | ||
92 | |||
93 | if (!dev) | ||
94 | return 0; | ||
95 | |||
96 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | ||
97 | return 0; | ||
98 | |||
99 | if (urb->status < 0) { | ||
100 | print_err_status(dev, -1, urb->status); | ||
101 | if (urb->status == -ENOENT) | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | buf = dev->vbi_mode.isoc_ctl.buf; | ||
106 | |||
107 | /* get buffer pointer and length */ | ||
108 | p_buffer = urb->transfer_buffer; | ||
109 | buffer_size = urb->actual_length; | ||
110 | |||
111 | if (buffer_size > 0) { | ||
112 | |||
113 | bytes_parsed = 0; | ||
114 | |||
115 | if(dma_q->is_partial_line) { | ||
116 | /* Handle the case where we were working on a partial line */ | ||
117 | sav_eav = dma_q->last_sav; | ||
118 | } else { | ||
119 | /* Check for a SAV/EAV overlapping the buffer boundary */ | ||
120 | sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, dma_q->partial_buf, &bytes_parsed); | ||
121 | } | ||
122 | |||
123 | sav_eav &= 0xF0; | ||
124 | /* Get the first line if we have some portion of an SAV/EAV from the last buffer | ||
125 | or a partial line */ | ||
126 | if(sav_eav) { | ||
127 | bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, | ||
128 | sav_eav, /* SAV/EAV */ | ||
129 | p_buffer + bytes_parsed, /* p_buffer */ | ||
130 | buffer_size - bytes_parsed); /* buffer size */ | ||
131 | } | ||
132 | |||
133 | /* Now parse data that is completely in this buffer */ | ||
134 | dma_q->is_partial_line = 0; | ||
135 | |||
136 | while(bytes_parsed < buffer_size) | ||
137 | { | ||
138 | u32 bytes_used = 0; | ||
139 | |||
140 | sav_eav = cx231xx_find_next_SAV_EAV( | ||
141 | p_buffer + bytes_parsed, /* p_buffer */ | ||
142 | buffer_size - bytes_parsed, /* buffer size */ | ||
143 | &bytes_used); /* Receives bytes used to get SAV/EAV */ | ||
144 | |||
145 | bytes_parsed += bytes_used; | ||
146 | |||
147 | sav_eav &= 0xF0; | ||
148 | if(sav_eav && (bytes_parsed < buffer_size)) | ||
149 | { | ||
150 | bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, | ||
151 | sav_eav, /* SAV/EAV */ | ||
152 | p_buffer + bytes_parsed, /* p_buffer */ | ||
153 | buffer_size - bytes_parsed); /* buffer size */ | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /* Save the last four bytes of the buffer so we can check the buffer boundary | ||
158 | condition next time */ | ||
159 | memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); | ||
160 | bytes_parsed = 0; | ||
161 | } | ||
162 | |||
163 | return rc; | ||
164 | } | ||
165 | |||
166 | /* ------------------------------------------------------------------ | ||
167 | Vbi buf operations | ||
168 | ------------------------------------------------------------------*/ | ||
169 | |||
170 | static int | ||
171 | vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | ||
172 | { | ||
173 | struct cx231xx_fh *fh = vq->priv_data; | ||
174 | struct cx231xx *dev = fh->dev; | ||
175 | u32 height = 0; | ||
176 | |||
177 | height = ((dev->norm & V4L2_STD_625_50) ? | ||
178 | PAL_VBI_LINES : NTSC_VBI_LINES) ; | ||
179 | |||
180 | *size = ( dev->width * height * 2); | ||
181 | if (0 == *count) | ||
182 | *count = CX231XX_DEF_VBI_BUF; | ||
183 | |||
184 | if (*count < CX231XX_MIN_BUF) | ||
185 | *count = CX231XX_MIN_BUF; | ||
186 | |||
187 | /* call VBI setup if required */ | ||
188 | /* cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); | ||
189 | */ | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | /* This is called *without* dev->slock held; please keep it that way */ | ||
195 | static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) | ||
196 | { | ||
197 | struct cx231xx_fh *fh = vq->priv_data; | ||
198 | struct cx231xx *dev = fh->dev; | ||
199 | unsigned long flags = 0; | ||
200 | if (in_interrupt()) | ||
201 | BUG(); | ||
202 | |||
203 | /* We used to wait for the buffer to finish here, but this didn't work | ||
204 | because, as we were keeping the state as VIDEOBUF_QUEUED, | ||
205 | videobuf_queue_cancel marked it as finished for us. | ||
206 | (Also, it could wedge forever if the hardware was misconfigured.) | ||
207 | |||
208 | This should be safe; by the time we get here, the buffer isn't | ||
209 | queued anymore. If we ever start marking the buffers as | ||
210 | VIDEOBUF_ACTIVE, it won't be, though. | ||
211 | */ | ||
212 | spin_lock_irqsave(&dev->vbi_mode.slock, flags); | ||
213 | if (dev->vbi_mode.isoc_ctl.buf == buf) | ||
214 | dev->vbi_mode.isoc_ctl.buf = NULL; | ||
215 | spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); | ||
216 | |||
217 | videobuf_vmalloc_free(&buf->vb); | ||
218 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
219 | } | ||
220 | |||
221 | static int | ||
222 | vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | ||
223 | enum v4l2_field field) | ||
224 | { | ||
225 | struct cx231xx_fh *fh = vq->priv_data; | ||
226 | struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); | ||
227 | struct cx231xx *dev = fh->dev; | ||
228 | int rc = 0, urb_init = 0; | ||
229 | u32 height = 0; | ||
230 | |||
231 | height = ((dev->norm & V4L2_STD_625_50) ? | ||
232 | PAL_VBI_LINES : NTSC_VBI_LINES) ; | ||
233 | buf->vb.size = ( (dev->width << 1) * height ); | ||
234 | |||
235 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
236 | return -EINVAL; | ||
237 | |||
238 | buf->vb.width = dev->width; | ||
239 | buf->vb.height = height; | ||
240 | buf->vb.field = field; | ||
241 | buf->vb.field = V4L2_FIELD_SEQ_TB; | ||
242 | |||
243 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
244 | rc = videobuf_iolock(vq, &buf->vb, NULL); | ||
245 | if (rc < 0) | ||
246 | goto fail; | ||
247 | } | ||
248 | |||
249 | if (!dev->vbi_mode.isoc_ctl.num_bufs) | ||
250 | urb_init = 1; | ||
251 | |||
252 | if (urb_init) { | ||
253 | rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, | ||
254 | CX231XX_NUM_VBI_BUFS, dev->vbi_mode.alt_max_pkt_size[0], | ||
255 | cx231xx_isoc_vbi_copy); | ||
256 | if (rc < 0) | ||
257 | goto fail; | ||
258 | } | ||
259 | |||
260 | buf->vb.state = VIDEOBUF_PREPARED; | ||
261 | return 0; | ||
262 | |||
263 | fail: | ||
264 | free_buffer(vq, buf); | ||
265 | return rc; | ||
266 | } | ||
267 | |||
268 | static void | ||
269 | vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
270 | { | ||
271 | struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); | ||
272 | struct cx231xx_fh *fh = vq->priv_data; | ||
273 | struct cx231xx *dev = fh->dev; | ||
274 | struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; | ||
275 | |||
276 | buf->vb.state = VIDEOBUF_QUEUED; | ||
277 | list_add_tail(&buf->vb.queue, &vidq->active); | ||
278 | |||
279 | } | ||
280 | |||
281 | static void vbi_buffer_release(struct videobuf_queue *vq, | ||
282 | struct videobuf_buffer *vb) | ||
283 | { | ||
284 | struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); | ||
285 | /* | ||
286 | struct cx231xx_fh *fh = vq->priv_data; | ||
287 | struct cx231xx *dev = (struct cx231xx *)fh->dev; | ||
288 | |||
289 | cx231xx_info(DRIVER_NAME "cx231xx: called vbi_buffer_release\n"); | ||
290 | */ | ||
291 | |||
292 | free_buffer(vq, buf); | ||
293 | } | ||
294 | |||
295 | |||
296 | struct videobuf_queue_ops cx231xx_vbi_qops = { | ||
297 | .buf_setup = vbi_buffer_setup, | ||
298 | .buf_prepare = vbi_buffer_prepare, | ||
299 | .buf_queue = vbi_buffer_queue, | ||
300 | .buf_release = vbi_buffer_release, | ||
301 | }; | ||
302 | |||
303 | |||
304 | |||
305 | /* ------------------------------------------------------------------ | ||
306 | URB control | ||
307 | ------------------------------------------------------------------*/ | ||
308 | |||
309 | /* | ||
310 | * IRQ callback, called by URB callback | ||
311 | */ | ||
312 | static void cx231xx_irq_vbi_callback(struct urb *urb) | ||
313 | { | ||
314 | struct cx231xx_dmaqueue *dma_q = urb->context; | ||
315 | struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); | ||
316 | struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); | ||
317 | int rc; | ||
318 | |||
319 | |||
320 | switch (urb->status) { | ||
321 | case 0: /* success */ | ||
322 | case -ETIMEDOUT: /* NAK */ | ||
323 | break; | ||
324 | case -ECONNRESET: /* kill */ | ||
325 | case -ENOENT: | ||
326 | case -ESHUTDOWN: | ||
327 | return; | ||
328 | default: /* error */ | ||
329 | cx231xx_err(DRIVER_NAME "urb completition error %d.\n", urb->status); | ||
330 | break; | ||
331 | } | ||
332 | |||
333 | /* Copy data from URB */ | ||
334 | spin_lock(&dev->vbi_mode.slock); | ||
335 | rc = dev->vbi_mode.isoc_ctl.isoc_copy(dev, urb); | ||
336 | spin_unlock(&dev->vbi_mode.slock); | ||
337 | |||
338 | /* Reset status */ | ||
339 | urb->status = 0; | ||
340 | |||
341 | urb->status = usb_submit_urb(urb, GFP_ATOMIC); | ||
342 | if (urb->status) { | ||
343 | cx231xx_err(DRIVER_NAME "urb resubmit failed (error=%i)\n", | ||
344 | urb->status); | ||
345 | } | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * Stop and Deallocate URBs | ||
350 | */ | ||
351 | void cx231xx_uninit_vbi_isoc(struct cx231xx *dev) | ||
352 | { | ||
353 | struct urb *urb; | ||
354 | int i; | ||
355 | |||
356 | cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n"); | ||
357 | |||
358 | dev->vbi_mode.isoc_ctl.nfields = -1; | ||
359 | for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { | ||
360 | urb = dev->vbi_mode.isoc_ctl.urb[i]; | ||
361 | if (urb) { | ||
362 | if (!irqs_disabled()) | ||
363 | usb_kill_urb(urb); | ||
364 | else | ||
365 | usb_unlink_urb(urb); | ||
366 | |||
367 | if (dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { | ||
368 | |||
369 | kfree(dev->vbi_mode.isoc_ctl.transfer_buffer[i]); | ||
370 | dev->vbi_mode.isoc_ctl.transfer_buffer[i] = NULL; | ||
371 | } | ||
372 | usb_free_urb(urb); | ||
373 | dev->vbi_mode.isoc_ctl.urb[i] = NULL; | ||
374 | } | ||
375 | dev->vbi_mode.isoc_ctl.transfer_buffer[i] = NULL; | ||
376 | } | ||
377 | |||
378 | kfree(dev->vbi_mode.isoc_ctl.urb); | ||
379 | kfree(dev->vbi_mode.isoc_ctl.transfer_buffer); | ||
380 | |||
381 | dev->vbi_mode.isoc_ctl.urb = NULL; | ||
382 | dev->vbi_mode.isoc_ctl.transfer_buffer = NULL; | ||
383 | dev->vbi_mode.isoc_ctl.num_bufs = 0; | ||
384 | |||
385 | cx231xx_capture_start(dev, 0, Vbi); | ||
386 | } | ||
387 | EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc); | ||
388 | |||
389 | /* | ||
390 | * Allocate URBs and start IRQ | ||
391 | */ | ||
392 | int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, | ||
393 | int num_bufs, int max_pkt_size, | ||
394 | int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)) | ||
395 | { | ||
396 | struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq; | ||
397 | int i; | ||
398 | int sb_size, pipe; | ||
399 | struct urb *urb; | ||
400 | int rc; | ||
401 | |||
402 | cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_prepare_isoc\n"); | ||
403 | |||
404 | /* De-allocates all pending stuff */ | ||
405 | cx231xx_uninit_vbi_isoc(dev); | ||
406 | |||
407 | /* clear if any halt */ | ||
408 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr)); | ||
409 | |||
410 | |||
411 | dev->vbi_mode.isoc_ctl.isoc_copy = isoc_copy; | ||
412 | dev->vbi_mode.isoc_ctl.num_bufs = num_bufs; | ||
413 | dma_q->pos = 0; | ||
414 | dma_q->is_partial_line = 0; | ||
415 | dma_q->last_sav = 0; | ||
416 | dma_q->current_field = -1; | ||
417 | dma_q->bytes_left_in_line = dev->width << 1; | ||
418 | dma_q->lines_per_field = ((dev->norm & V4L2_STD_625_50) ? | ||
419 | PAL_VBI_LINES : NTSC_VBI_LINES) ; | ||
420 | dma_q->lines_completed = 0; | ||
421 | for(i = 0; i < 8 ; i++) | ||
422 | dma_q->partial_buf[i] = 0; | ||
423 | |||
424 | dev->vbi_mode.isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); | ||
425 | if (!dev->vbi_mode.isoc_ctl.urb) { | ||
426 | cx231xx_errdev("cannot alloc memory for usb buffers\n"); | ||
427 | return -ENOMEM; | ||
428 | } | ||
429 | |||
430 | dev->vbi_mode.isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, | ||
431 | GFP_KERNEL); | ||
432 | if (!dev->vbi_mode.isoc_ctl.transfer_buffer) { | ||
433 | cx231xx_errdev("cannot allocate memory for usbtransfer\n"); | ||
434 | kfree(dev->vbi_mode.isoc_ctl.urb); | ||
435 | return -ENOMEM; | ||
436 | } | ||
437 | |||
438 | dev->vbi_mode.isoc_ctl.max_pkt_size = max_pkt_size; | ||
439 | dev->vbi_mode.isoc_ctl.buf = NULL; | ||
440 | |||
441 | sb_size = max_packets * dev->vbi_mode.isoc_ctl.max_pkt_size; | ||
442 | |||
443 | /* allocate urbs and transfer buffers */ | ||
444 | for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { | ||
445 | |||
446 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
447 | if (!urb) { | ||
448 | cx231xx_err(DRIVER_NAME ": cannot alloc isoc_ctl.urb %i\n", i); | ||
449 | cx231xx_uninit_vbi_isoc(dev); | ||
450 | return -ENOMEM; | ||
451 | } | ||
452 | dev->vbi_mode.isoc_ctl.urb[i] = urb; | ||
453 | urb->transfer_flags = 0; | ||
454 | |||
455 | dev->vbi_mode.isoc_ctl.transfer_buffer[i] = kzalloc(sb_size, GFP_KERNEL); | ||
456 | if (!dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { | ||
457 | cx231xx_err(DRIVER_NAME ": unable to allocate %i bytes for transfer" | ||
458 | " buffer %i%s\n", | ||
459 | sb_size, i, | ||
460 | in_interrupt()?" while in int":""); | ||
461 | cx231xx_uninit_vbi_isoc(dev); | ||
462 | return -ENOMEM; | ||
463 | } | ||
464 | |||
465 | pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr); | ||
466 | usb_fill_bulk_urb(urb, dev->udev, pipe, | ||
467 | dev->vbi_mode.isoc_ctl.transfer_buffer[i], sb_size, | ||
468 | cx231xx_irq_vbi_callback, dma_q); | ||
469 | } | ||
470 | |||
471 | init_waitqueue_head(&dma_q->wq); | ||
472 | |||
473 | /* submit urbs and enables IRQ */ | ||
474 | for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { | ||
475 | rc = usb_submit_urb(dev->vbi_mode.isoc_ctl.urb[i], GFP_ATOMIC); | ||
476 | if (rc) { | ||
477 | cx231xx_err(DRIVER_NAME ": submit of urb %i failed (error=%i)\n", i, | ||
478 | rc); | ||
479 | cx231xx_uninit_vbi_isoc(dev); | ||
480 | return rc; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | cx231xx_capture_start(dev, 1, Vbi); | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc); | ||
489 | |||
490 | |||
491 | u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
492 | u8 sav_eav, u8 *p_buffer, u32 buffer_size) | ||
493 | { | ||
494 | u32 bytes_copied = 0; | ||
495 | int current_field = -1; | ||
496 | |||
497 | switch(sav_eav) { | ||
498 | |||
499 | case SAV_VBI_FIELD1: | ||
500 | current_field = 1; | ||
501 | break; | ||
502 | |||
503 | case SAV_VBI_FIELD2: | ||
504 | current_field = 2; | ||
505 | break; | ||
506 | default: | ||
507 | break; | ||
508 | } | ||
509 | |||
510 | if(current_field < 0 ) | ||
511 | return bytes_copied; | ||
512 | |||
513 | dma_q->last_sav = sav_eav; | ||
514 | |||
515 | bytes_copied = cx231xx_copy_vbi_line(dev, dma_q, p_buffer, buffer_size, current_field); | ||
516 | |||
517 | return bytes_copied; | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * Announces that a buffer were filled and request the next | ||
522 | */ | ||
523 | static inline void vbi_buffer_filled(struct cx231xx *dev, | ||
524 | struct cx231xx_dmaqueue *dma_q, | ||
525 | struct cx231xx_buffer *buf) | ||
526 | { | ||
527 | /* Advice that buffer was filled */ | ||
528 | /* cx231xx_info(DRIVER_NAME "[%p/%d] wakeup\n", buf, buf->vb.i); */ | ||
529 | |||
530 | buf->vb.state = VIDEOBUF_DONE; | ||
531 | buf->vb.field_count++; | ||
532 | do_gettimeofday(&buf->vb.ts); | ||
533 | |||
534 | dev->vbi_mode.isoc_ctl.buf = NULL; | ||
535 | |||
536 | list_del(&buf->vb.queue); | ||
537 | wake_up(&buf->vb.done); | ||
538 | } | ||
539 | |||
540 | u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
541 | u8 *p_line, u32 length, int field_number) | ||
542 | { | ||
543 | u32 bytes_to_copy; | ||
544 | struct cx231xx_buffer *buf; | ||
545 | u32 _line_size = dev->width * 2; | ||
546 | |||
547 | if( dma_q->current_field != field_number ) { | ||
548 | cx231xx_reset_vbi_buffer(dev, dma_q); | ||
549 | } | ||
550 | |||
551 | /* get the buffer pointer */ | ||
552 | buf = dev->vbi_mode.isoc_ctl.buf; | ||
553 | |||
554 | /* Remember the field number for next time */ | ||
555 | dma_q->current_field = field_number; | ||
556 | |||
557 | bytes_to_copy = dma_q->bytes_left_in_line; | ||
558 | if(bytes_to_copy > length) | ||
559 | bytes_to_copy = length; | ||
560 | |||
561 | if(dma_q->lines_completed >= dma_q->lines_per_field) { | ||
562 | dma_q->bytes_left_in_line -= bytes_to_copy; | ||
563 | dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | dma_q->is_partial_line = 1; | ||
568 | |||
569 | /* If we don't have a buffer, just return the number of bytes we would | ||
570 | have copied if we had a buffer. */ | ||
571 | if(!buf) { | ||
572 | dma_q->bytes_left_in_line -= bytes_to_copy; | ||
573 | dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; | ||
574 | return bytes_to_copy; | ||
575 | } | ||
576 | |||
577 | /* copy the data to video buffer */ | ||
578 | cx231xx_do_vbi_copy(dev, dma_q, p_line, bytes_to_copy); | ||
579 | |||
580 | dma_q->pos += bytes_to_copy; | ||
581 | dma_q->bytes_left_in_line -= bytes_to_copy; | ||
582 | |||
583 | if(dma_q->bytes_left_in_line == 0) { | ||
584 | |||
585 | dma_q->bytes_left_in_line = _line_size; | ||
586 | dma_q->lines_completed++; | ||
587 | dma_q->is_partial_line = 0; | ||
588 | |||
589 | if(cx231xx_is_vbi_buffer_done(dev, dma_q) && buf ) { | ||
590 | |||
591 | vbi_buffer_filled(dev, dma_q, buf); | ||
592 | |||
593 | dma_q->pos = 0; | ||
594 | buf = NULL; | ||
595 | dma_q->lines_completed = 0; | ||
596 | } | ||
597 | } | ||
598 | |||
599 | return bytes_to_copy; | ||
600 | } | ||
601 | |||
602 | /* | ||
603 | * video-buf generic routine to get the next available buffer | ||
604 | */ | ||
605 | static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, | ||
606 | struct cx231xx_buffer **buf) | ||
607 | { | ||
608 | struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); | ||
609 | struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); | ||
610 | char *outp; | ||
611 | |||
612 | if (list_empty(&dma_q->active)) { | ||
613 | cx231xx_err(DRIVER_NAME ": No active queue to serve\n"); | ||
614 | dev->vbi_mode.isoc_ctl.buf = NULL; | ||
615 | *buf = NULL; | ||
616 | return; | ||
617 | } | ||
618 | |||
619 | /* Get the next buffer */ | ||
620 | *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); | ||
621 | |||
622 | /* Cleans up buffer - Usefull for testing for frame/URB loss */ | ||
623 | outp = videobuf_to_vmalloc(&(*buf)->vb); | ||
624 | memset(outp, 0, (*buf)->vb.size); | ||
625 | |||
626 | dev->vbi_mode.isoc_ctl.buf = *buf; | ||
627 | |||
628 | return; | ||
629 | } | ||
630 | |||
631 | |||
632 | void cx231xx_reset_vbi_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) | ||
633 | { | ||
634 | struct cx231xx_buffer *buf; | ||
635 | |||
636 | buf = dev->vbi_mode.isoc_ctl.buf; | ||
637 | |||
638 | if(buf == NULL) { | ||
639 | |||
640 | /* first try to get the buffer */ | ||
641 | get_next_vbi_buf(dma_q, &buf); | ||
642 | |||
643 | dma_q->pos = 0; | ||
644 | dma_q->current_field = -1; | ||
645 | } | ||
646 | |||
647 | dma_q->bytes_left_in_line = dev->width << 1; | ||
648 | dma_q->lines_completed = 0; | ||
649 | } | ||
650 | |||
651 | int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
652 | u8 *p_buffer, u32 bytes_to_copy) | ||
653 | { | ||
654 | u8 *p_out_buffer = NULL; | ||
655 | u32 current_line_bytes_copied = 0; | ||
656 | struct cx231xx_buffer *buf; | ||
657 | u32 _line_size = dev->width << 1; | ||
658 | void *startwrite; | ||
659 | int offset, lencopy; | ||
660 | |||
661 | buf = dev->vbi_mode.isoc_ctl.buf; | ||
662 | |||
663 | if (buf == NULL) { | ||
664 | return -1; | ||
665 | } | ||
666 | |||
667 | p_out_buffer = videobuf_to_vmalloc(&buf->vb); | ||
668 | |||
669 | if(dma_q->bytes_left_in_line != _line_size ) { | ||
670 | current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; | ||
671 | } | ||
672 | |||
673 | offset = ( dma_q->lines_completed * _line_size ) + current_line_bytes_copied; | ||
674 | |||
675 | /* prepare destination address */ | ||
676 | startwrite = p_out_buffer + offset; | ||
677 | |||
678 | lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; | ||
679 | |||
680 | memcpy(startwrite, p_buffer, lencopy); | ||
681 | |||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | |||
686 | u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q) | ||
687 | { | ||
688 | u32 height = 0; | ||
689 | |||
690 | height = ((dev->norm & V4L2_STD_625_50) ? | ||
691 | PAL_VBI_LINES : NTSC_VBI_LINES) ; | ||
692 | return (dma_q->lines_completed == height)?1:0; | ||
693 | } | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.h b/drivers/media/video/cx231xx/cx231xx-vbi.h new file mode 100644 index 000000000000..2a9e4a1668bf --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-vbi.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | cx231xx_vbi.h - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on cx88 driver | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef _CX231XX_VBI_H | ||
23 | #define _CX231XX_VBI_H | ||
24 | |||
25 | extern struct videobuf_queue_ops cx231xx_vbi_qops; | ||
26 | |||
27 | |||
28 | #define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ | ||
29 | #define NTSC_VBI_END_LINE 21 | ||
30 | #define NTSC_VBI_LINES (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1) | ||
31 | |||
32 | #define PAL_VBI_START_LINE 6 | ||
33 | #define PAL_VBI_END_LINE 23 | ||
34 | #define PAL_VBI_LINES (PAL_VBI_END_LINE - PAL_VBI_START_LINE + 1) | ||
35 | |||
36 | #define VBI_STRIDE 1440 | ||
37 | #define VBI_SAMPLES_PER_LINE 1440 | ||
38 | |||
39 | #define CX231XX_NUM_VBI_PACKETS 4 | ||
40 | #define CX231XX_NUM_VBI_BUFS 5 | ||
41 | |||
42 | /* stream functions */ | ||
43 | int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, | ||
44 | int num_bufs, int max_pkt_size, | ||
45 | int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)); | ||
46 | |||
47 | void cx231xx_uninit_vbi_isoc(struct cx231xx *dev); | ||
48 | |||
49 | /* vbi data copy functions */ | ||
50 | u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
51 | u8 sav_eav, u8 *p_buffer, u32 buffer_size); | ||
52 | u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
53 | u8 *p_line, u32 length, int field_number); | ||
54 | void cx231xx_reset_vbi_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); | ||
55 | |||
56 | int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
57 | u8 *p_buffer, u32 bytes_to_copy); | ||
58 | |||
59 | u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q); | ||
60 | |||
61 | #endif | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c new file mode 100644 index 000000000000..3eb5626ead1d --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-video.c | |||
@@ -0,0 +1,2440 @@ | |||
1 | /* | ||
2 | cx231xx-video.c - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on em28xx driver | ||
6 | Based on cx23885 driver | ||
7 | Based on cx88 driver | ||
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/init.h> | ||
26 | #include <linux/list.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/bitmap.h> | ||
30 | #include <linux/usb.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/version.h> | ||
33 | #include <linux/mm.h> | ||
34 | #include <linux/mutex.h> | ||
35 | |||
36 | #include <media/v4l2-common.h> | ||
37 | #include <media/v4l2-ioctl.h> | ||
38 | #include <media/v4l2-chip-ident.h> | ||
39 | #include <media/msp3400.h> | ||
40 | #include <media/tuner.h> | ||
41 | |||
42 | #include "dvb_frontend.h" | ||
43 | |||
44 | #include "cx231xx.h" | ||
45 | #include "cx231xx-vbi.h" | ||
46 | |||
47 | |||
48 | #define DRIVER_AUTHOR "Srinivasa Deevi <srinivasa.deevi@conexant.com>" | ||
49 | #define DRIVER_DESC "Conexant cx231xx based USB video device driver" | ||
50 | |||
51 | |||
52 | #define cx231xx_videodbg(fmt, arg...) do {\ | ||
53 | if (video_debug) \ | ||
54 | printk(KERN_INFO "%s %s :"fmt, \ | ||
55 | dev->name, __func__ , ##arg); } while (0) | ||
56 | |||
57 | static unsigned int isoc_debug; | ||
58 | module_param(isoc_debug, int, 0644); | ||
59 | MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); | ||
60 | |||
61 | #define cx231xx_isocdbg(fmt, arg...) \ | ||
62 | do {\ | ||
63 | if (isoc_debug) { \ | ||
64 | printk(KERN_INFO "%s %s :"fmt, \ | ||
65 | dev->name, __func__ , ##arg); \ | ||
66 | } \ | ||
67 | } while (0) | ||
68 | |||
69 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
70 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
71 | MODULE_LICENSE("GPL"); | ||
72 | |||
73 | |||
74 | |||
75 | static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; | ||
76 | static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; | ||
77 | static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; | ||
78 | static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; | ||
79 | |||
80 | module_param_array(card, int, NULL, 0444); | ||
81 | module_param_array(video_nr, int, NULL, 0444); | ||
82 | module_param_array(vbi_nr, int, NULL, 0444); | ||
83 | module_param_array(radio_nr, int, NULL, 0444); | ||
84 | |||
85 | MODULE_PARM_DESC(card, "card type"); | ||
86 | MODULE_PARM_DESC(video_nr, "video device numbers"); | ||
87 | MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); | ||
88 | MODULE_PARM_DESC(radio_nr, "radio device numbers"); | ||
89 | |||
90 | static unsigned int video_debug; | ||
91 | module_param(video_debug, int, 0644); | ||
92 | MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); | ||
93 | |||
94 | |||
95 | |||
96 | /* supported video standards */ | ||
97 | static struct cx231xx_fmt format[] = { | ||
98 | { | ||
99 | .name = "16bpp YUY2, 4:2:2, packed", | ||
100 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
101 | .depth = 16, | ||
102 | .reg = 0, | ||
103 | }, | ||
104 | }; | ||
105 | |||
106 | |||
107 | /* supported controls */ | ||
108 | /* Common to all boards */ | ||
109 | |||
110 | /* ------------------------------------------------------------------- */ | ||
111 | |||
112 | static const struct v4l2_queryctrl no_ctl = { | ||
113 | .name = "42", | ||
114 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
115 | }; | ||
116 | |||
117 | static struct cx231xx_ctrl cx231xx_ctls[] = { | ||
118 | /* --- video --- */ | ||
119 | { | ||
120 | .v = { | ||
121 | .id = V4L2_CID_BRIGHTNESS, | ||
122 | .name = "Brightness", | ||
123 | .minimum = 0x00, | ||
124 | .maximum = 0xff, | ||
125 | .step = 1, | ||
126 | .default_value = 0x7f, | ||
127 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
128 | }, | ||
129 | .off = 128, | ||
130 | .reg = LUMA_CTRL, | ||
131 | .mask = 0x00ff, | ||
132 | .shift = 0, | ||
133 | }, { | ||
134 | .v = { | ||
135 | .id = V4L2_CID_CONTRAST, | ||
136 | .name = "Contrast", | ||
137 | .minimum = 0, | ||
138 | .maximum = 0xff, | ||
139 | .step = 1, | ||
140 | .default_value = 0x3f, | ||
141 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
142 | }, | ||
143 | .off = 0, | ||
144 | .reg = LUMA_CTRL, | ||
145 | .mask = 0xff00, | ||
146 | .shift = 8, | ||
147 | }, { | ||
148 | .v = { | ||
149 | .id = V4L2_CID_HUE, | ||
150 | .name = "Hue", | ||
151 | .minimum = 0, | ||
152 | .maximum = 0xff, | ||
153 | .step = 1, | ||
154 | .default_value = 0x7f, | ||
155 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
156 | }, | ||
157 | .off = 128, | ||
158 | .reg = CHROMA_CTRL, | ||
159 | .mask = 0xff0000, | ||
160 | .shift = 16, | ||
161 | }, { | ||
162 | /* strictly, this only describes only U saturation. | ||
163 | * V saturation is handled specially through code. | ||
164 | */ | ||
165 | .v = { | ||
166 | .id = V4L2_CID_SATURATION, | ||
167 | .name = "Saturation", | ||
168 | .minimum = 0, | ||
169 | .maximum = 0xff, | ||
170 | .step = 1, | ||
171 | .default_value = 0x7f, | ||
172 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
173 | }, | ||
174 | .off = 0, | ||
175 | .reg = CHROMA_CTRL, | ||
176 | .mask = 0x00ff, | ||
177 | .shift = 0, | ||
178 | }, { | ||
179 | /* --- audio --- */ | ||
180 | .v = { | ||
181 | .id = V4L2_CID_AUDIO_MUTE, | ||
182 | .name = "Mute", | ||
183 | .minimum = 0, | ||
184 | .maximum = 1, | ||
185 | .default_value = 1, | ||
186 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
187 | }, | ||
188 | .reg = PATH1_CTL1, | ||
189 | .mask = (0x1f << 24), | ||
190 | .shift = 24, | ||
191 | }, { | ||
192 | .v = { | ||
193 | .id = V4L2_CID_AUDIO_VOLUME, | ||
194 | .name = "Volume", | ||
195 | .minimum = 0, | ||
196 | .maximum = 0x3f, | ||
197 | .step = 1, | ||
198 | .default_value = 0x3f, | ||
199 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
200 | }, | ||
201 | .reg = PATH1_VOL_CTL, | ||
202 | .mask = 0xff, | ||
203 | .shift = 0, | ||
204 | } | ||
205 | }; | ||
206 | static const int CX231XX_CTLS = ARRAY_SIZE(cx231xx_ctls); | ||
207 | |||
208 | static const u32 cx231xx_user_ctrls[] = { | ||
209 | V4L2_CID_USER_CLASS, | ||
210 | V4L2_CID_BRIGHTNESS, | ||
211 | V4L2_CID_CONTRAST, | ||
212 | V4L2_CID_SATURATION, | ||
213 | V4L2_CID_HUE, | ||
214 | V4L2_CID_AUDIO_VOLUME, | ||
215 | #if 0 | ||
216 | V4L2_CID_AUDIO_BALANCE, | ||
217 | #endif | ||
218 | V4L2_CID_AUDIO_MUTE, | ||
219 | 0 | ||
220 | }; | ||
221 | |||
222 | static const u32 *ctrl_classes[] = { | ||
223 | cx231xx_user_ctrls, | ||
224 | NULL | ||
225 | }; | ||
226 | |||
227 | |||
228 | /* ------------------------------------------------------------------ | ||
229 | Video buffer and parser functions | ||
230 | ------------------------------------------------------------------*/ | ||
231 | |||
232 | /* | ||
233 | * Announces that a buffer were filled and request the next | ||
234 | */ | ||
235 | static inline void buffer_filled(struct cx231xx *dev, | ||
236 | struct cx231xx_dmaqueue *dma_q, | ||
237 | struct cx231xx_buffer *buf) | ||
238 | { | ||
239 | /* Advice that buffer was filled */ | ||
240 | cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); | ||
241 | buf->vb.state = VIDEOBUF_DONE; | ||
242 | buf->vb.field_count++; | ||
243 | do_gettimeofday(&buf->vb.ts); | ||
244 | |||
245 | dev->video_mode.isoc_ctl.buf = NULL; | ||
246 | |||
247 | list_del(&buf->vb.queue); | ||
248 | wake_up(&buf->vb.done); | ||
249 | } | ||
250 | |||
251 | |||
252 | static inline void print_err_status(struct cx231xx *dev, | ||
253 | int packet, int status) | ||
254 | { | ||
255 | char *errmsg = "Unknown"; | ||
256 | |||
257 | switch (status) { | ||
258 | case -ENOENT: | ||
259 | errmsg = "unlinked synchronuously"; | ||
260 | break; | ||
261 | case -ECONNRESET: | ||
262 | errmsg = "unlinked asynchronuously"; | ||
263 | break; | ||
264 | case -ENOSR: | ||
265 | errmsg = "Buffer error (overrun)"; | ||
266 | break; | ||
267 | case -EPIPE: | ||
268 | errmsg = "Stalled (device not responding)"; | ||
269 | break; | ||
270 | case -EOVERFLOW: | ||
271 | errmsg = "Babble (bad cable?)"; | ||
272 | break; | ||
273 | case -EPROTO: | ||
274 | errmsg = "Bit-stuff error (bad cable?)"; | ||
275 | break; | ||
276 | case -EILSEQ: | ||
277 | errmsg = "CRC/Timeout (could be anything)"; | ||
278 | break; | ||
279 | case -ETIME: | ||
280 | errmsg = "Device does not respond"; | ||
281 | break; | ||
282 | } | ||
283 | if (packet < 0) { | ||
284 | cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg); | ||
285 | } else { | ||
286 | cx231xx_isocdbg("URB packet %d, status %d [%s].\n", | ||
287 | packet, status, errmsg); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * video-buf generic routine to get the next available buffer | ||
293 | */ | ||
294 | static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, | ||
295 | struct cx231xx_buffer **buf) | ||
296 | { | ||
297 | struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); | ||
298 | struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); | ||
299 | |||
300 | char *outp; | ||
301 | |||
302 | |||
303 | if (list_empty(&dma_q->active)) { | ||
304 | cx231xx_isocdbg("No active queue to serve\n"); | ||
305 | dev->video_mode.isoc_ctl.buf = NULL; | ||
306 | *buf = NULL; | ||
307 | return; | ||
308 | } | ||
309 | |||
310 | /* Get the next buffer */ | ||
311 | *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); | ||
312 | |||
313 | /* Cleans up buffer - Usefull for testing for frame/URB loss */ | ||
314 | outp = videobuf_to_vmalloc(&(*buf)->vb); | ||
315 | memset(outp, 0, (*buf)->vb.size); | ||
316 | |||
317 | dev->video_mode.isoc_ctl.buf = *buf; | ||
318 | |||
319 | return; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * Controls the isoc copy of each urb packet | ||
324 | */ | ||
325 | static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) | ||
326 | { | ||
327 | struct cx231xx_buffer *buf; | ||
328 | struct cx231xx_dmaqueue *dma_q = urb->context; | ||
329 | unsigned char *outp = NULL; | ||
330 | int i, rc = 1; | ||
331 | unsigned char *p_buffer; | ||
332 | u32 bytes_parsed = 0, buffer_size = 0; | ||
333 | u8 sav_eav = 0; | ||
334 | |||
335 | if (!dev) | ||
336 | return 0; | ||
337 | |||
338 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | ||
339 | return 0; | ||
340 | |||
341 | if (urb->status < 0) { | ||
342 | print_err_status(dev, -1, urb->status); | ||
343 | if (urb->status == -ENOENT) | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | buf = dev->video_mode.isoc_ctl.buf; | ||
348 | if (buf != NULL) | ||
349 | outp = videobuf_to_vmalloc(&buf->vb); | ||
350 | |||
351 | for (i = 0; i < urb->number_of_packets; i++) { | ||
352 | int status = urb->iso_frame_desc[i].status; | ||
353 | |||
354 | if (status < 0) { | ||
355 | print_err_status(dev, i, status); | ||
356 | if (urb->iso_frame_desc[i].status != -EPROTO) | ||
357 | continue; | ||
358 | } | ||
359 | |||
360 | if (urb->iso_frame_desc[i].actual_length <= 0) { | ||
361 | /* cx231xx_isocdbg("packet %d is empty",i); - spammy */ | ||
362 | continue; | ||
363 | } | ||
364 | if (urb->iso_frame_desc[i].actual_length > | ||
365 | dev->video_mode.max_pkt_size) { | ||
366 | cx231xx_isocdbg("packet bigger than packet size"); | ||
367 | continue; | ||
368 | } | ||
369 | |||
370 | /* get buffer pointer and length */ | ||
371 | p_buffer = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | ||
372 | buffer_size = urb->iso_frame_desc[i].actual_length; | ||
373 | bytes_parsed = 0; | ||
374 | |||
375 | if(dma_q->is_partial_line) | ||
376 | { | ||
377 | /* Handle the case where we were working on a partial line */ | ||
378 | sav_eav = dma_q->last_sav; | ||
379 | } else { | ||
380 | /* Check for a SAV/EAV overlapping the buffer boundary */ | ||
381 | sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, dma_q->partial_buf, &bytes_parsed); | ||
382 | } | ||
383 | |||
384 | sav_eav &= 0xF0; | ||
385 | /* Get the first line if we have some portion of an SAV/EAV from the last buffer | ||
386 | or a partial line */ | ||
387 | if(sav_eav) { | ||
388 | bytes_parsed += cx231xx_get_video_line(dev, dma_q, | ||
389 | sav_eav, /* SAV/EAV */ | ||
390 | p_buffer + bytes_parsed, /* p_buffer */ | ||
391 | buffer_size - bytes_parsed); /* buffer size */ | ||
392 | } | ||
393 | |||
394 | /* Now parse data that is completely in this buffer */ | ||
395 | /* dma_q->is_partial_line = 0; */ | ||
396 | |||
397 | while(bytes_parsed < buffer_size) | ||
398 | { | ||
399 | u32 bytes_used = 0; | ||
400 | |||
401 | sav_eav = cx231xx_find_next_SAV_EAV( | ||
402 | p_buffer + bytes_parsed, /* p_buffer */ | ||
403 | buffer_size - bytes_parsed, /* buffer size */ | ||
404 | &bytes_used); /* Receives bytes used to get SAV/EAV */ | ||
405 | |||
406 | bytes_parsed += bytes_used; | ||
407 | |||
408 | sav_eav &= 0xF0; | ||
409 | if(sav_eav && (bytes_parsed < buffer_size)) | ||
410 | { | ||
411 | bytes_parsed += cx231xx_get_video_line(dev, dma_q, | ||
412 | sav_eav, /* SAV/EAV */ | ||
413 | p_buffer + bytes_parsed, /* p_buffer */ | ||
414 | buffer_size - bytes_parsed); /* buffer size */ | ||
415 | } | ||
416 | } | ||
417 | |||
418 | /* Save the last four bytes of the buffer so we can check the buffer boundary | ||
419 | condition next time */ | ||
420 | memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); | ||
421 | bytes_parsed = 0; | ||
422 | |||
423 | } | ||
424 | return rc; | ||
425 | } | ||
426 | |||
427 | u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, u32 *p_bytes_used) | ||
428 | { | ||
429 | u32 bytes_used; | ||
430 | u8 boundary_bytes[8]; | ||
431 | u8 sav_eav = 0; | ||
432 | |||
433 | *p_bytes_used = 0; | ||
434 | |||
435 | /* Create an array of the last 4 bytes of the last buffer and the first | ||
436 | 4 bytes of the current buffer. */ | ||
437 | |||
438 | memcpy(boundary_bytes, partial_buf, 4); | ||
439 | memcpy(boundary_bytes + 4, p_buffer, 4); | ||
440 | |||
441 | /* Check for the SAV/EAV in the boundary buffer */ | ||
442 | sav_eav = cx231xx_find_next_SAV_EAV((u8*)&boundary_bytes, 8, &bytes_used); | ||
443 | |||
444 | if(sav_eav) { | ||
445 | /* found a boundary SAV/EAV. Updates the bytes used to reflect | ||
446 | only those used in the new buffer */ | ||
447 | *p_bytes_used = bytes_used - 4; | ||
448 | } | ||
449 | |||
450 | return sav_eav; | ||
451 | } | ||
452 | |||
453 | u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used) | ||
454 | { | ||
455 | u32 i; | ||
456 | u8 sav_eav = 0; | ||
457 | |||
458 | /* Don't search if the buffer size is less than 4. It causes a page fault since | ||
459 | buffer_size - 4 evaluates to a large number in that case. */ | ||
460 | if(buffer_size < 4) { | ||
461 | *p_bytes_used = buffer_size; | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | for(i = 0;i < (buffer_size - 3); i++) { | ||
466 | |||
467 | if((p_buffer[i] == 0xFF) && | ||
468 | (p_buffer[i+1] == 0x00) && | ||
469 | (p_buffer[i+2] == 0x00)) { | ||
470 | |||
471 | *p_bytes_used = i+4; | ||
472 | sav_eav = p_buffer[i+3]; | ||
473 | return sav_eav; | ||
474 | } | ||
475 | } | ||
476 | |||
477 | *p_bytes_used = buffer_size; | ||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | |||
482 | |||
483 | |||
484 | u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
485 | u8 sav_eav, u8 *p_buffer, u32 buffer_size) | ||
486 | { | ||
487 | u32 bytes_copied = 0; | ||
488 | int current_field = -1; | ||
489 | |||
490 | |||
491 | switch(sav_eav) { | ||
492 | case SAV_ACTIVE_VIDEO_FIELD1: | ||
493 | /* looking for skipped line which occurred in PAL 720x480 mode. In this case, | ||
494 | there will be no active data contained between the SAV and EAV */ | ||
495 | if ( (buffer_size > 3) && | ||
496 | (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && | ||
497 | ( (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || | ||
498 | (p_buffer[3] == EAV_VBLANK_FIELD1) || (p_buffer[3] == EAV_VBLANK_FIELD2) | ||
499 | ) | ||
500 | ) | ||
501 | { | ||
502 | return bytes_copied; | ||
503 | } | ||
504 | current_field = 1; | ||
505 | break; | ||
506 | |||
507 | case SAV_ACTIVE_VIDEO_FIELD2: | ||
508 | /* looking for skipped line which occurred in PAL 720x480 mode. In this case, | ||
509 | there will be no active data contained between the SAV and EAV */ | ||
510 | if ( (buffer_size > 3) && | ||
511 | (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && | ||
512 | ( (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || | ||
513 | (p_buffer[3] == EAV_VBLANK_FIELD1) || (p_buffer[3] == EAV_VBLANK_FIELD2) | ||
514 | ) | ||
515 | ) | ||
516 | { | ||
517 | return bytes_copied; | ||
518 | } | ||
519 | current_field = 2; | ||
520 | break; | ||
521 | } | ||
522 | |||
523 | dma_q->last_sav = sav_eav; | ||
524 | |||
525 | bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer, buffer_size, current_field); | ||
526 | |||
527 | return bytes_copied; | ||
528 | } | ||
529 | |||
530 | u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
531 | u8 *p_line, u32 length, int field_number) | ||
532 | { | ||
533 | u32 bytes_to_copy; | ||
534 | struct cx231xx_buffer *buf; | ||
535 | u32 _line_size = dev->width * 2; | ||
536 | |||
537 | if( dma_q->current_field != field_number ) { | ||
538 | cx231xx_reset_video_buffer(dev, dma_q); | ||
539 | } | ||
540 | |||
541 | /* get the buffer pointer */ | ||
542 | buf = dev->video_mode.isoc_ctl.buf; | ||
543 | |||
544 | /* Remember the field number for next time */ | ||
545 | dma_q->current_field = field_number; | ||
546 | |||
547 | bytes_to_copy = dma_q->bytes_left_in_line; | ||
548 | if(bytes_to_copy > length) | ||
549 | bytes_to_copy = length; | ||
550 | |||
551 | |||
552 | if(dma_q->lines_completed >= dma_q->lines_per_field) { | ||
553 | dma_q->bytes_left_in_line -= bytes_to_copy; | ||
554 | dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | dma_q->is_partial_line = 1; | ||
559 | |||
560 | /* If we don't have a buffer, just return the number of bytes we would | ||
561 | have copied if we had a buffer. */ | ||
562 | if(!buf) | ||
563 | { | ||
564 | dma_q->bytes_left_in_line -= bytes_to_copy; | ||
565 | dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; | ||
566 | return bytes_to_copy; | ||
567 | } | ||
568 | |||
569 | /* copy the data to video buffer */ | ||
570 | cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy); | ||
571 | |||
572 | dma_q->pos += bytes_to_copy; | ||
573 | dma_q->bytes_left_in_line -= bytes_to_copy; | ||
574 | |||
575 | if(dma_q->bytes_left_in_line == 0) { | ||
576 | |||
577 | dma_q->bytes_left_in_line = _line_size; | ||
578 | dma_q->lines_completed++; | ||
579 | dma_q->is_partial_line = 0; | ||
580 | |||
581 | if(cx231xx_is_buffer_done(dev, dma_q) && buf) { | ||
582 | |||
583 | buffer_filled(dev, dma_q, buf); | ||
584 | |||
585 | dma_q->pos = 0; | ||
586 | buf = NULL; | ||
587 | dma_q->lines_completed = 0; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | return bytes_to_copy; | ||
592 | } | ||
593 | |||
594 | void cx231xx_reset_video_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) | ||
595 | { | ||
596 | struct cx231xx_buffer *buf; | ||
597 | |||
598 | /* handle the switch from field 1 to field 2 */ | ||
599 | if(dma_q->current_field == 1) { | ||
600 | if(dma_q->lines_completed >= dma_q->lines_per_field ) { | ||
601 | dma_q->field1_done = 1; | ||
602 | } else { | ||
603 | dma_q->field1_done = 0; | ||
604 | } | ||
605 | } | ||
606 | |||
607 | buf = dev->video_mode.isoc_ctl.buf; | ||
608 | |||
609 | if(buf == NULL) { | ||
610 | u8* outp = NULL; | ||
611 | /* first try to get the buffer */ | ||
612 | get_next_buf(dma_q, &buf); | ||
613 | |||
614 | if(buf) | ||
615 | outp = videobuf_to_vmalloc(&buf->vb); | ||
616 | |||
617 | dma_q->pos = 0; | ||
618 | dma_q->field1_done = 0; | ||
619 | dma_q->current_field = -1; | ||
620 | } | ||
621 | |||
622 | /* reset the counters */ | ||
623 | dma_q->bytes_left_in_line = dev->width << 1; | ||
624 | dma_q->lines_completed = 0; | ||
625 | } | ||
626 | |||
627 | int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
628 | u8 *p_buffer, u32 bytes_to_copy) | ||
629 | { | ||
630 | u8 *p_out_buffer = NULL; | ||
631 | u32 current_line_bytes_copied = 0; | ||
632 | struct cx231xx_buffer *buf; | ||
633 | u32 _line_size = dev->width << 1; | ||
634 | void *startwrite; | ||
635 | int offset, lencopy; | ||
636 | |||
637 | buf = dev->video_mode.isoc_ctl.buf; | ||
638 | |||
639 | if (buf == NULL) | ||
640 | return -1; | ||
641 | |||
642 | p_out_buffer = videobuf_to_vmalloc(&buf->vb); | ||
643 | |||
644 | current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; | ||
645 | |||
646 | /* Offset field 2 one line from the top of the buffer */ | ||
647 | offset = (dma_q->current_field == 1)? 0: _line_size; | ||
648 | |||
649 | /* Offset for field 2 */ | ||
650 | startwrite = p_out_buffer + offset; | ||
651 | |||
652 | /* lines already completed in the current field */ | ||
653 | startwrite += (dma_q->lines_completed * _line_size * 2); | ||
654 | |||
655 | /* bytes already completed in the current line */ | ||
656 | startwrite += current_line_bytes_copied; | ||
657 | |||
658 | lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; | ||
659 | |||
660 | if( (u8*)(startwrite +lencopy) > (u8*)(p_out_buffer+ buf->vb.size) ) { | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | /* The below copies the UYVY data straight into video buffer */ | ||
665 | cx231xx_swab( (u16*)p_buffer, (u16*)startwrite, (u16)lencopy); | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | void cx231xx_swab(u16 *from, u16 *to, u16 len) | ||
671 | { | ||
672 | u16 i; | ||
673 | |||
674 | if( len <= 0) | ||
675 | return; | ||
676 | |||
677 | for(i = 0; i < len/2; i++) { | ||
678 | to[i] = (from[i] << 8) | (from[i] >> 8); | ||
679 | } | ||
680 | } | ||
681 | |||
682 | u8 cx231xx_is_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q) | ||
683 | { | ||
684 | u8 buffer_complete = 0; | ||
685 | |||
686 | /* Dual field stream */ | ||
687 | buffer_complete = | ||
688 | ((dma_q->current_field == 2) && | ||
689 | (dma_q->lines_completed >= dma_q->lines_per_field) && | ||
690 | dma_q->field1_done); | ||
691 | |||
692 | return buffer_complete; | ||
693 | } | ||
694 | |||
695 | |||
696 | /* ------------------------------------------------------------------ | ||
697 | Videobuf operations | ||
698 | ------------------------------------------------------------------*/ | ||
699 | |||
700 | static int | ||
701 | buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | ||
702 | { | ||
703 | struct cx231xx_fh *fh = vq->priv_data; | ||
704 | struct cx231xx *dev = fh->dev; | ||
705 | struct v4l2_frequency f; | ||
706 | |||
707 | *size = ( fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; | ||
708 | if (0 == *count) | ||
709 | *count = CX231XX_DEF_BUF; | ||
710 | |||
711 | if (*count < CX231XX_MIN_BUF) | ||
712 | *count = CX231XX_MIN_BUF; | ||
713 | |||
714 | /* Ask tuner to go to analog mode */ | ||
715 | memset(&f, 0, sizeof(f)); | ||
716 | f.frequency = dev->ctl_freq; | ||
717 | f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | ||
718 | |||
719 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); | ||
720 | |||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | /* This is called *without* dev->slock held; please keep it that way */ | ||
725 | static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) | ||
726 | { | ||
727 | struct cx231xx_fh *fh = vq->priv_data; | ||
728 | struct cx231xx *dev = fh->dev; | ||
729 | unsigned long flags = 0; | ||
730 | if (in_interrupt()) | ||
731 | BUG(); | ||
732 | |||
733 | /* We used to wait for the buffer to finish here, but this didn't work | ||
734 | because, as we were keeping the state as VIDEOBUF_QUEUED, | ||
735 | videobuf_queue_cancel marked it as finished for us. | ||
736 | (Also, it could wedge forever if the hardware was misconfigured.) | ||
737 | |||
738 | This should be safe; by the time we get here, the buffer isn't | ||
739 | queued anymore. If we ever start marking the buffers as | ||
740 | VIDEOBUF_ACTIVE, it won't be, though. | ||
741 | */ | ||
742 | spin_lock_irqsave(&dev->video_mode.slock, flags); | ||
743 | if (dev->video_mode.isoc_ctl.buf == buf) | ||
744 | dev->video_mode.isoc_ctl.buf = NULL; | ||
745 | spin_unlock_irqrestore(&dev->video_mode.slock, flags); | ||
746 | |||
747 | videobuf_vmalloc_free(&buf->vb); | ||
748 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
749 | } | ||
750 | |||
751 | static int | ||
752 | buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | ||
753 | enum v4l2_field field) | ||
754 | { | ||
755 | struct cx231xx_fh *fh = vq->priv_data; | ||
756 | struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); | ||
757 | struct cx231xx *dev = fh->dev; | ||
758 | int rc = 0, urb_init = 0; | ||
759 | |||
760 | /* The only currently supported format is 16 bits/pixel */ | ||
761 | buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; | ||
762 | |||
763 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
764 | return -EINVAL; | ||
765 | |||
766 | buf->vb.width = dev->width; | ||
767 | buf->vb.height = dev->height; | ||
768 | buf->vb.field = field; | ||
769 | |||
770 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
771 | rc = videobuf_iolock(vq, &buf->vb, NULL); | ||
772 | if (rc < 0) | ||
773 | goto fail; | ||
774 | } | ||
775 | |||
776 | if (!dev->video_mode.isoc_ctl.num_bufs) | ||
777 | urb_init = 1; | ||
778 | |||
779 | if (urb_init) { | ||
780 | rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, | ||
781 | CX231XX_NUM_BUFS, dev->video_mode.max_pkt_size, | ||
782 | cx231xx_isoc_copy); | ||
783 | if (rc < 0) | ||
784 | goto fail; | ||
785 | } | ||
786 | |||
787 | buf->vb.state = VIDEOBUF_PREPARED; | ||
788 | return 0; | ||
789 | |||
790 | fail: | ||
791 | free_buffer(vq, buf); | ||
792 | return rc; | ||
793 | } | ||
794 | |||
795 | static void | ||
796 | buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
797 | { | ||
798 | struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); | ||
799 | struct cx231xx_fh *fh = vq->priv_data; | ||
800 | struct cx231xx *dev = fh->dev; | ||
801 | struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; | ||
802 | |||
803 | buf->vb.state = VIDEOBUF_QUEUED; | ||
804 | list_add_tail(&buf->vb.queue, &vidq->active); | ||
805 | |||
806 | } | ||
807 | |||
808 | static void buffer_release(struct videobuf_queue *vq, | ||
809 | struct videobuf_buffer *vb) | ||
810 | { | ||
811 | struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); | ||
812 | struct cx231xx_fh *fh = vq->priv_data; | ||
813 | struct cx231xx *dev = (struct cx231xx *)fh->dev; | ||
814 | |||
815 | cx231xx_isocdbg("cx231xx: called buffer_release\n"); | ||
816 | |||
817 | free_buffer(vq, buf); | ||
818 | } | ||
819 | |||
820 | static struct videobuf_queue_ops cx231xx_video_qops = { | ||
821 | .buf_setup = buffer_setup, | ||
822 | .buf_prepare = buffer_prepare, | ||
823 | .buf_queue = buffer_queue, | ||
824 | .buf_release = buffer_release, | ||
825 | }; | ||
826 | |||
827 | /********************* v4l2 interface **************************************/ | ||
828 | |||
829 | |||
830 | void video_mux(struct cx231xx *dev, int index) | ||
831 | { | ||
832 | |||
833 | struct v4l2_routing route; | ||
834 | |||
835 | route.input = INPUT(index)->vmux; | ||
836 | route.output = 0; | ||
837 | dev->video_input = index; | ||
838 | dev->ctl_ainput = INPUT(index)->amux; | ||
839 | |||
840 | cx231xx_set_video_input_mux(dev,index); | ||
841 | |||
842 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_INT_S_VIDEO_ROUTING, &route); | ||
843 | |||
844 | cx231xx_set_audio_input(dev, dev->ctl_ainput ); | ||
845 | |||
846 | cx231xx_info("video_mux : %d\n", index); | ||
847 | |||
848 | /* do mode control overrides if required */ | ||
849 | cx231xx_do_mode_ctrl_overrides(dev); | ||
850 | } | ||
851 | |||
852 | /* Usage lock check functions */ | ||
853 | static int res_get(struct cx231xx_fh *fh) | ||
854 | { | ||
855 | struct cx231xx *dev = fh->dev; | ||
856 | int rc = 0; | ||
857 | |||
858 | /* This instance already has stream_on */ | ||
859 | if (fh->stream_on) | ||
860 | return rc; | ||
861 | |||
862 | if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
863 | if (dev->stream_on) | ||
864 | return -EBUSY; | ||
865 | dev->stream_on = 1; | ||
866 | } else if(fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
867 | if (dev->vbi_stream_on) | ||
868 | return -EBUSY; | ||
869 | dev->vbi_stream_on = 1; | ||
870 | } else | ||
871 | return -EINVAL; | ||
872 | |||
873 | fh->stream_on = 1; | ||
874 | |||
875 | return rc; | ||
876 | } | ||
877 | |||
878 | static int res_check(struct cx231xx_fh *fh) | ||
879 | { | ||
880 | return (fh->stream_on); | ||
881 | } | ||
882 | |||
883 | static void res_free(struct cx231xx_fh *fh) | ||
884 | { | ||
885 | struct cx231xx *dev = fh->dev; | ||
886 | |||
887 | fh->stream_on = 0; | ||
888 | |||
889 | if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
890 | dev->stream_on = 0; | ||
891 | if(fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) | ||
892 | dev->vbi_stream_on = 0; | ||
893 | } | ||
894 | |||
895 | static int check_dev(struct cx231xx *dev) | ||
896 | { | ||
897 | if (dev->state & DEV_DISCONNECTED) { | ||
898 | cx231xx_errdev("v4l2 ioctl: device not present\n"); | ||
899 | return -ENODEV; | ||
900 | } | ||
901 | |||
902 | if (dev->state & DEV_MISCONFIGURED) { | ||
903 | cx231xx_errdev("v4l2 ioctl: device is misconfigured; " | ||
904 | "close and open it again\n"); | ||
905 | return -EIO; | ||
906 | } | ||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | void get_scale(struct cx231xx *dev, | ||
911 | unsigned int width, unsigned int height, | ||
912 | unsigned int *hscale, unsigned int *vscale) | ||
913 | { | ||
914 | unsigned int maxw = norm_maxw(dev); | ||
915 | unsigned int maxh = norm_maxh(dev); | ||
916 | |||
917 | *hscale = (((unsigned long)maxw) << 12) / width - 4096L; | ||
918 | if (*hscale >= 0x4000) | ||
919 | *hscale = 0x3fff; | ||
920 | |||
921 | *vscale = (((unsigned long)maxh) << 12) / height - 4096L; | ||
922 | if (*vscale >= 0x4000) | ||
923 | *vscale = 0x3fff; | ||
924 | |||
925 | dev->hscale = *hscale; | ||
926 | dev->vscale = *vscale; | ||
927 | |||
928 | } | ||
929 | |||
930 | /* ------------------------------------------------------------------ | ||
931 | IOCTL vidioc handling | ||
932 | ------------------------------------------------------------------*/ | ||
933 | |||
934 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||
935 | struct v4l2_format *f) | ||
936 | { | ||
937 | struct cx231xx_fh *fh = priv; | ||
938 | struct cx231xx *dev = fh->dev; | ||
939 | |||
940 | mutex_lock(&dev->lock); | ||
941 | |||
942 | f->fmt.pix.width = dev->width; | ||
943 | f->fmt.pix.height = dev->height; | ||
944 | f->fmt.pix.pixelformat = dev->format->fourcc;; | ||
945 | f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;; | ||
946 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; | ||
947 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
948 | |||
949 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
950 | |||
951 | mutex_unlock(&dev->lock); | ||
952 | return 0; | ||
953 | } | ||
954 | |||
955 | static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc) | ||
956 | { | ||
957 | unsigned int i; | ||
958 | |||
959 | for (i = 0; i < ARRAY_SIZE(format); i++) | ||
960 | if (format[i].fourcc == fourcc) | ||
961 | return &format[i]; | ||
962 | |||
963 | return NULL; | ||
964 | } | ||
965 | |||
966 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | ||
967 | struct v4l2_format *f) | ||
968 | { | ||
969 | struct cx231xx_fh *fh = priv; | ||
970 | struct cx231xx *dev = fh->dev; | ||
971 | int width = f->fmt.pix.width; | ||
972 | int height = f->fmt.pix.height; | ||
973 | unsigned int maxw = norm_maxw(dev); | ||
974 | unsigned int maxh = norm_maxh(dev); | ||
975 | unsigned int hscale, vscale; | ||
976 | struct cx231xx_fmt *fmt; | ||
977 | |||
978 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
979 | if (!fmt) { | ||
980 | cx231xx_videodbg("Fourcc format (%08x) invalid.\n", | ||
981 | f->fmt.pix.pixelformat); | ||
982 | return -EINVAL; | ||
983 | } | ||
984 | |||
985 | /* width must even because of the YUYV format | ||
986 | height must be even because of interlacing */ | ||
987 | height &= 0xfffe; | ||
988 | width &= 0xfffe; | ||
989 | |||
990 | if (unlikely(height < 32)) | ||
991 | height = 32; | ||
992 | if (unlikely(height > maxh)) | ||
993 | height = maxh; | ||
994 | if (unlikely(width < 48)) | ||
995 | width = 48; | ||
996 | if (unlikely(width > maxw)) | ||
997 | width = maxw; | ||
998 | |||
999 | get_scale(dev, width, height, &hscale, &vscale); | ||
1000 | |||
1001 | width = (((unsigned long)maxw) << 12) / (hscale + 4096L); | ||
1002 | height = (((unsigned long)maxh) << 12) / (vscale + 4096L); | ||
1003 | |||
1004 | f->fmt.pix.width = width; | ||
1005 | f->fmt.pix.height = height; | ||
1006 | f->fmt.pix.pixelformat = fmt->fourcc; | ||
1007 | f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; | ||
1008 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; | ||
1009 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
1010 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
1011 | |||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
1016 | struct v4l2_format *f) | ||
1017 | { | ||
1018 | struct cx231xx_fh *fh = priv; | ||
1019 | struct cx231xx *dev = fh->dev; | ||
1020 | int rc; | ||
1021 | struct cx231xx_fmt *fmt; | ||
1022 | |||
1023 | rc = check_dev(dev); | ||
1024 | if (rc < 0) | ||
1025 | return rc; | ||
1026 | |||
1027 | |||
1028 | mutex_lock(&dev->lock); | ||
1029 | |||
1030 | vidioc_try_fmt_vid_cap(file, priv, f); | ||
1031 | |||
1032 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
1033 | if (!fmt) { | ||
1034 | rc = -EINVAL; | ||
1035 | goto out; | ||
1036 | } | ||
1037 | |||
1038 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | ||
1039 | cx231xx_errdev("%s queue busy\n", __func__); | ||
1040 | rc = -EBUSY; | ||
1041 | goto out; | ||
1042 | } | ||
1043 | |||
1044 | if (dev->stream_on && !fh->stream_on) { | ||
1045 | cx231xx_errdev("%s device in use by another fh\n", __func__); | ||
1046 | rc = -EBUSY; | ||
1047 | goto out; | ||
1048 | } | ||
1049 | |||
1050 | /* set new image size */ | ||
1051 | dev->width = f->fmt.pix.width; | ||
1052 | dev->height = f->fmt.pix.height; | ||
1053 | dev->format = fmt; | ||
1054 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
1055 | |||
1056 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_FMT, f); | ||
1057 | |||
1058 | /* Set the correct alternate setting for this resolution */ | ||
1059 | cx231xx_resolution_set(dev); | ||
1060 | |||
1061 | out: | ||
1062 | mutex_unlock(&dev->lock); | ||
1063 | return rc; | ||
1064 | } | ||
1065 | |||
1066 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||
1067 | { | ||
1068 | struct cx231xx_fh *fh = priv; | ||
1069 | struct cx231xx *dev = fh->dev; | ||
1070 | |||
1071 | *id = dev->norm; | ||
1072 | return 0; | ||
1073 | } | ||
1074 | |||
1075 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) | ||
1076 | { | ||
1077 | struct cx231xx_fh *fh = priv; | ||
1078 | struct cx231xx *dev = fh->dev; | ||
1079 | struct v4l2_format f; | ||
1080 | int rc; | ||
1081 | |||
1082 | rc = check_dev(dev); | ||
1083 | if (rc < 0) | ||
1084 | return rc; | ||
1085 | |||
1086 | cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm); | ||
1087 | |||
1088 | mutex_lock(&dev->lock); | ||
1089 | dev->norm = *norm; | ||
1090 | |||
1091 | |||
1092 | /* Adjusts width/height, if needed */ | ||
1093 | f.fmt.pix.width = dev->width; | ||
1094 | f.fmt.pix.height = dev->height; | ||
1095 | vidioc_try_fmt_vid_cap(file, priv, &f); | ||
1096 | |||
1097 | /* set new image size */ | ||
1098 | dev->width = f.fmt.pix.width; | ||
1099 | dev->height = f.fmt.pix.height; | ||
1100 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
1101 | |||
1102 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_STD, &dev->norm); | ||
1103 | |||
1104 | mutex_unlock(&dev->lock); | ||
1105 | |||
1106 | cx231xx_resolution_set(dev); | ||
1107 | |||
1108 | /* do mode control overrides */ | ||
1109 | cx231xx_do_mode_ctrl_overrides(dev); | ||
1110 | |||
1111 | return 0; | ||
1112 | } | ||
1113 | |||
1114 | static const char *iname[] = { | ||
1115 | [CX231XX_VMUX_COMPOSITE1] = "Composite1", | ||
1116 | [CX231XX_VMUX_SVIDEO] = "S-Video", | ||
1117 | [CX231XX_VMUX_TELEVISION] = "Television", | ||
1118 | [CX231XX_VMUX_CABLE] = "Cable TV", | ||
1119 | [CX231XX_VMUX_DVB] = "DVB", | ||
1120 | [CX231XX_VMUX_DEBUG] = "for debug only", | ||
1121 | }; | ||
1122 | |||
1123 | static int vidioc_enum_input(struct file *file, void *priv, | ||
1124 | struct v4l2_input *i) | ||
1125 | { | ||
1126 | struct cx231xx_fh *fh = priv; | ||
1127 | struct cx231xx *dev = fh->dev; | ||
1128 | unsigned int n; | ||
1129 | |||
1130 | n = i->index; | ||
1131 | if (n >= MAX_CX231XX_INPUT) | ||
1132 | return -EINVAL; | ||
1133 | if (0 == INPUT(n)->type) | ||
1134 | return -EINVAL; | ||
1135 | |||
1136 | i->index = n; | ||
1137 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
1138 | |||
1139 | strcpy(i->name, iname[INPUT(n)->type]); | ||
1140 | |||
1141 | if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) || | ||
1142 | (CX231XX_VMUX_CABLE == INPUT(n)->type)) | ||
1143 | i->type = V4L2_INPUT_TYPE_TUNER; | ||
1144 | |||
1145 | i->std = dev->vdev->tvnorms; | ||
1146 | |||
1147 | return 0; | ||
1148 | } | ||
1149 | |||
1150 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | ||
1151 | { | ||
1152 | struct cx231xx_fh *fh = priv; | ||
1153 | struct cx231xx *dev = fh->dev; | ||
1154 | |||
1155 | *i = dev->video_input; | ||
1156 | |||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||
1161 | { | ||
1162 | struct cx231xx_fh *fh = priv; | ||
1163 | struct cx231xx *dev = fh->dev; | ||
1164 | int rc; | ||
1165 | |||
1166 | rc = check_dev(dev); | ||
1167 | if (rc < 0) | ||
1168 | return rc; | ||
1169 | |||
1170 | if (i >= MAX_CX231XX_INPUT) | ||
1171 | return -EINVAL; | ||
1172 | if (0 == INPUT(i)->type) | ||
1173 | return -EINVAL; | ||
1174 | |||
1175 | mutex_lock(&dev->lock); | ||
1176 | |||
1177 | video_mux(dev, i); | ||
1178 | |||
1179 | mutex_unlock(&dev->lock); | ||
1180 | return 0; | ||
1181 | } | ||
1182 | |||
1183 | static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) | ||
1184 | { | ||
1185 | struct cx231xx_fh *fh = priv; | ||
1186 | struct cx231xx *dev = fh->dev; | ||
1187 | |||
1188 | switch (a->index) { | ||
1189 | case CX231XX_AMUX_VIDEO: | ||
1190 | strcpy(a->name, "Television"); | ||
1191 | break; | ||
1192 | case CX231XX_AMUX_LINE_IN: | ||
1193 | strcpy(a->name, "Line In"); | ||
1194 | break; | ||
1195 | default: | ||
1196 | return -EINVAL; | ||
1197 | } | ||
1198 | |||
1199 | a->index = dev->ctl_ainput; | ||
1200 | a->capability = V4L2_AUDCAP_STEREO; | ||
1201 | |||
1202 | return 0; | ||
1203 | } | ||
1204 | |||
1205 | static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) | ||
1206 | { | ||
1207 | struct cx231xx_fh *fh = priv; | ||
1208 | struct cx231xx *dev = fh->dev; | ||
1209 | int status = 0; | ||
1210 | |||
1211 | |||
1212 | /* Doesn't allow manual routing */ | ||
1213 | if (a->index != dev->ctl_ainput) | ||
1214 | return -EINVAL; | ||
1215 | |||
1216 | dev->ctl_ainput = INPUT(a->index)->amux; | ||
1217 | status = cx231xx_set_audio_input(dev, dev->ctl_ainput); | ||
1218 | |||
1219 | return status; | ||
1220 | } | ||
1221 | |||
1222 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
1223 | struct v4l2_queryctrl *qc) | ||
1224 | { | ||
1225 | struct cx231xx_fh *fh = priv; | ||
1226 | struct cx231xx *dev = fh->dev; | ||
1227 | int id = qc->id; | ||
1228 | int i; | ||
1229 | int rc; | ||
1230 | |||
1231 | rc = check_dev(dev); | ||
1232 | if (rc < 0) | ||
1233 | return rc; | ||
1234 | |||
1235 | qc->id = v4l2_ctrl_next(ctrl_classes, qc->id); | ||
1236 | if (unlikely(qc->id == 0)) | ||
1237 | return -EINVAL; | ||
1238 | |||
1239 | memset(qc, 0, sizeof(*qc)); | ||
1240 | |||
1241 | qc->id = id; | ||
1242 | |||
1243 | if (qc->id < V4L2_CID_BASE || | ||
1244 | qc->id >= V4L2_CID_LASTP1) | ||
1245 | return -EINVAL; | ||
1246 | |||
1247 | for (i = 0; i < CX231XX_CTLS; i++) | ||
1248 | if (cx231xx_ctls[i].v.id == qc->id) | ||
1249 | break; | ||
1250 | |||
1251 | if (i == CX231XX_CTLS) { | ||
1252 | *qc = no_ctl; | ||
1253 | return 0; | ||
1254 | } | ||
1255 | *qc = cx231xx_ctls[i].v; | ||
1256 | |||
1257 | mutex_lock(&dev->lock); | ||
1258 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_QUERYCTRL, qc); | ||
1259 | mutex_unlock(&dev->lock); | ||
1260 | |||
1261 | if (qc->type) | ||
1262 | return 0; | ||
1263 | else | ||
1264 | return -EINVAL; | ||
1265 | } | ||
1266 | |||
1267 | static int vidioc_g_ctrl(struct file *file, void *priv, | ||
1268 | struct v4l2_control *ctrl) | ||
1269 | { | ||
1270 | struct cx231xx_fh *fh = priv; | ||
1271 | struct cx231xx *dev = fh->dev; | ||
1272 | int rc; | ||
1273 | |||
1274 | rc = check_dev(dev); | ||
1275 | if (rc < 0) | ||
1276 | return rc; | ||
1277 | |||
1278 | mutex_lock(&dev->lock); | ||
1279 | |||
1280 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_CTRL, ctrl); | ||
1281 | |||
1282 | mutex_unlock(&dev->lock); | ||
1283 | return rc; | ||
1284 | } | ||
1285 | |||
1286 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
1287 | struct v4l2_control *ctrl) | ||
1288 | { | ||
1289 | struct cx231xx_fh *fh = priv; | ||
1290 | struct cx231xx *dev = fh->dev; | ||
1291 | int rc; | ||
1292 | |||
1293 | rc = check_dev(dev); | ||
1294 | if (rc < 0) | ||
1295 | return rc; | ||
1296 | |||
1297 | mutex_lock(&dev->lock); | ||
1298 | |||
1299 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_CTRL, ctrl); | ||
1300 | |||
1301 | mutex_unlock(&dev->lock); | ||
1302 | return rc; | ||
1303 | } | ||
1304 | |||
1305 | static int vidioc_g_tuner(struct file *file, void *priv, | ||
1306 | struct v4l2_tuner *t) | ||
1307 | { | ||
1308 | struct cx231xx_fh *fh = priv; | ||
1309 | struct cx231xx *dev = fh->dev; | ||
1310 | int rc; | ||
1311 | |||
1312 | rc = check_dev(dev); | ||
1313 | if (rc < 0) | ||
1314 | return rc; | ||
1315 | |||
1316 | if (0 != t->index) | ||
1317 | return -EINVAL; | ||
1318 | |||
1319 | strcpy(t->name, "Tuner"); | ||
1320 | |||
1321 | t->type = V4L2_TUNER_ANALOG_TV; | ||
1322 | t->capability = V4L2_TUNER_CAP_NORM; | ||
1323 | t->rangehigh = 0xffffffffUL; | ||
1324 | t->signal = 0xffff ; /* LOCKED */ | ||
1325 | |||
1326 | return 0; | ||
1327 | } | ||
1328 | |||
1329 | static int vidioc_s_tuner(struct file *file, void *priv, | ||
1330 | struct v4l2_tuner *t) | ||
1331 | { | ||
1332 | struct cx231xx_fh *fh = priv; | ||
1333 | struct cx231xx *dev = fh->dev; | ||
1334 | int rc; | ||
1335 | |||
1336 | rc = check_dev(dev); | ||
1337 | if (rc < 0) | ||
1338 | return rc; | ||
1339 | |||
1340 | if (0 != t->index) | ||
1341 | return -EINVAL; | ||
1342 | #if 0 | ||
1343 | mutex_lock(&dev->lock); | ||
1344 | |||
1345 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); | ||
1346 | |||
1347 | mutex_unlock(&dev->lock); | ||
1348 | #endif | ||
1349 | return 0; | ||
1350 | } | ||
1351 | |||
1352 | static int vidioc_g_frequency(struct file *file, void *priv, | ||
1353 | struct v4l2_frequency *f) | ||
1354 | { | ||
1355 | struct cx231xx_fh *fh = priv; | ||
1356 | struct cx231xx *dev = fh->dev; | ||
1357 | |||
1358 | mutex_lock(&dev->lock); | ||
1359 | f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | ||
1360 | f->frequency = dev->ctl_freq; | ||
1361 | |||
1362 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); | ||
1363 | |||
1364 | mutex_unlock(&dev->lock); | ||
1365 | |||
1366 | return 0; | ||
1367 | } | ||
1368 | |||
1369 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
1370 | struct v4l2_frequency *f) | ||
1371 | { | ||
1372 | struct cx231xx_fh *fh = priv; | ||
1373 | struct cx231xx *dev = fh->dev; | ||
1374 | int rc; | ||
1375 | |||
1376 | rc = check_dev(dev); | ||
1377 | if (rc < 0) | ||
1378 | return rc; | ||
1379 | |||
1380 | if (0 != f->tuner) | ||
1381 | return -EINVAL; | ||
1382 | |||
1383 | if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) | ||
1384 | return -EINVAL; | ||
1385 | if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) | ||
1386 | return -EINVAL; | ||
1387 | |||
1388 | /* set pre channel change settings in DIF first */ | ||
1389 | rc = cx231xx_tuner_pre_channel_change(dev); | ||
1390 | |||
1391 | mutex_lock(&dev->lock); | ||
1392 | |||
1393 | dev->ctl_freq = f->frequency; | ||
1394 | |||
1395 | if(dev->tuner_type == TUNER_XC5000) { | ||
1396 | if( dev->cx231xx_set_analog_freq != NULL ) { | ||
1397 | dev->cx231xx_set_analog_freq(dev, f->frequency ); | ||
1398 | } | ||
1399 | } else { | ||
1400 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f); | ||
1401 | } | ||
1402 | |||
1403 | mutex_unlock(&dev->lock); | ||
1404 | |||
1405 | /* set post channel change settings in DIF first */ | ||
1406 | rc = cx231xx_tuner_post_channel_change(dev); | ||
1407 | |||
1408 | cx231xx_info("Set New FREQUENCY to %d\n",f->frequency); | ||
1409 | |||
1410 | return rc; | ||
1411 | } | ||
1412 | |||
1413 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1414 | |||
1415 | |||
1416 | /* | ||
1417 | -R, --list-registers=type=<host/i2cdrv/i2caddr>,chip=<chip>[,min=<addr>,max=<addr>] | ||
1418 | dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER] | ||
1419 | -r, --set-register=type=<host/i2cdrv/i2caddr>,chip=<chip>,reg=<addr>,val=<val> | ||
1420 | set the register [VIDIOC_DBG_S_REGISTER] | ||
1421 | |||
1422 | if type == host, then <chip> is the hosts chip ID (default 0) | ||
1423 | if type == i2cdrv (default), then <chip> is the I2C driver name or ID | ||
1424 | if type == i2caddr, then <chip> is the 7-bit I2C address | ||
1425 | */ | ||
1426 | |||
1427 | |||
1428 | static int vidioc_g_register(struct file *file, void *priv, | ||
1429 | struct v4l2_dbg_register *reg) | ||
1430 | { | ||
1431 | struct cx231xx_fh *fh = priv; | ||
1432 | struct cx231xx *dev = fh->dev; | ||
1433 | int ret = 0; | ||
1434 | u8 value[4] ={0,0,0,0}; | ||
1435 | u32 data = 0; | ||
1436 | |||
1437 | switch (reg->match.type) { | ||
1438 | case V4L2_CHIP_MATCH_HOST: | ||
1439 | switch(reg->match.addr) { | ||
1440 | case 0: /* Cx231xx - internal registers */ | ||
1441 | ret = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, (u16) reg->reg, value, 4); | ||
1442 | reg->val = value[0] | value[1] << 8 | value[2] << 16 | value[3] << 24; | ||
1443 | break; | ||
1444 | case 1: /* Colibri - read byte */ | ||
1445 | ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, &data, 1); | ||
1446 | reg->val = le32_to_cpu(data & 0xff); | ||
1447 | break; | ||
1448 | case 14: /* Colibri - read dword */ | ||
1449 | ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, &data, 4); | ||
1450 | reg->val = le32_to_cpu(data); | ||
1451 | break; | ||
1452 | case 2: /* Hammerhead - read byte */ | ||
1453 | ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, &data, 1); | ||
1454 | reg->val = le32_to_cpu(data & 0xff); | ||
1455 | break; | ||
1456 | case 24: /* Hammerhead - read dword */ | ||
1457 | ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, &data, 4); | ||
1458 | reg->val = le32_to_cpu(data); | ||
1459 | break; | ||
1460 | case 3: /* flatiron - read byte */ | ||
1461 | ret = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, &data, 1); | ||
1462 | reg->val = le32_to_cpu(data & 0xff); | ||
1463 | break; | ||
1464 | case 34: /* flatiron - read dword */ | ||
1465 | ret = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, &data, 4); | ||
1466 | reg->val = le32_to_cpu(data); | ||
1467 | break; | ||
1468 | } | ||
1469 | return ret < 0?ret:0; | ||
1470 | |||
1471 | case V4L2_CHIP_MATCH_I2C_DRIVER: | ||
1472 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_G_REGISTER, reg); | ||
1473 | return 0; | ||
1474 | case V4L2_CHIP_MATCH_I2C_ADDR: | ||
1475 | /* Not supported yet */ | ||
1476 | return -EINVAL; | ||
1477 | default: | ||
1478 | if (!v4l2_chip_match_host(®->match)) | ||
1479 | return -EINVAL; | ||
1480 | } | ||
1481 | |||
1482 | |||
1483 | mutex_lock(&dev->lock); | ||
1484 | |||
1485 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_G_REGISTER, reg); | ||
1486 | |||
1487 | mutex_unlock(&dev->lock); | ||
1488 | |||
1489 | return ret; | ||
1490 | } | ||
1491 | |||
1492 | static int vidioc_s_register(struct file *file, void *priv, | ||
1493 | struct v4l2_dbg_register *reg) | ||
1494 | { | ||
1495 | struct cx231xx_fh *fh = priv; | ||
1496 | struct cx231xx *dev = fh->dev; | ||
1497 | int ret = 0; | ||
1498 | __le64 buf; | ||
1499 | u32 value; | ||
1500 | u8 data[4] ={0,0,0,0}; | ||
1501 | |||
1502 | buf = cpu_to_le64(reg->val); | ||
1503 | |||
1504 | switch (reg->match.type) { | ||
1505 | case V4L2_CHIP_MATCH_HOST: | ||
1506 | { | ||
1507 | value = (u32) buf & 0xffffffff; | ||
1508 | |||
1509 | switch(reg->match.addr) { | ||
1510 | case 0: /* cx231xx internal registers */ | ||
1511 | data[0]=(u8)value; | ||
1512 | data[1]=(u8)(value>>8); | ||
1513 | data[2]=(u8)(value>>16); | ||
1514 | data[3]=(u8)(value>>24); | ||
1515 | ret = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, (u16) reg->reg, data, 4); | ||
1516 | break; | ||
1517 | case 1: /* Colibri - read byte */ | ||
1518 | ret = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, value, 1); | ||
1519 | break; | ||
1520 | case 14: /* Colibri - read dword */ | ||
1521 | ret = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, value, 4); | ||
1522 | break; | ||
1523 | case 2: /* Hammerhead - read byte */ | ||
1524 | ret = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, value, 1); | ||
1525 | break; | ||
1526 | case 24: /* Hammerhead - read dword */ | ||
1527 | ret = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, value, 4); | ||
1528 | break; | ||
1529 | case 3: /* flatiron - read byte */ | ||
1530 | ret = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, value, 1); | ||
1531 | break; | ||
1532 | case 34: /* flatiron - read dword */ | ||
1533 | ret = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, value, 4); | ||
1534 | break; | ||
1535 | } | ||
1536 | } | ||
1537 | return ret < 0?ret:0; | ||
1538 | |||
1539 | default: | ||
1540 | break; | ||
1541 | } | ||
1542 | |||
1543 | mutex_lock(&dev->lock); | ||
1544 | |||
1545 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_S_REGISTER, reg); | ||
1546 | |||
1547 | mutex_unlock(&dev->lock); | ||
1548 | |||
1549 | return ret; | ||
1550 | } | ||
1551 | #endif | ||
1552 | |||
1553 | |||
1554 | static int vidioc_cropcap(struct file *file, void *priv, | ||
1555 | struct v4l2_cropcap *cc) | ||
1556 | { | ||
1557 | struct cx231xx_fh *fh = priv; | ||
1558 | struct cx231xx *dev = fh->dev; | ||
1559 | |||
1560 | if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1561 | return -EINVAL; | ||
1562 | |||
1563 | cc->bounds.left = 0; | ||
1564 | cc->bounds.top = 0; | ||
1565 | cc->bounds.width = dev->width; | ||
1566 | cc->bounds.height = dev->height; | ||
1567 | cc->defrect = cc->bounds; | ||
1568 | cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ | ||
1569 | cc->pixelaspect.denominator = 59; | ||
1570 | |||
1571 | return 0; | ||
1572 | } | ||
1573 | |||
1574 | static int vidioc_streamon(struct file *file, void *priv, | ||
1575 | enum v4l2_buf_type type) | ||
1576 | { | ||
1577 | struct cx231xx_fh *fh = priv; | ||
1578 | struct cx231xx *dev = fh->dev; | ||
1579 | int rc; | ||
1580 | |||
1581 | rc = check_dev(dev); | ||
1582 | if (rc < 0) | ||
1583 | return rc; | ||
1584 | |||
1585 | mutex_lock(&dev->lock); | ||
1586 | rc = res_get(fh); | ||
1587 | |||
1588 | if (likely(rc >= 0)) | ||
1589 | rc = videobuf_streamon(&fh->vb_vidq); | ||
1590 | |||
1591 | mutex_unlock(&dev->lock); | ||
1592 | |||
1593 | return rc; | ||
1594 | } | ||
1595 | |||
1596 | static int vidioc_streamoff(struct file *file, void *priv, | ||
1597 | enum v4l2_buf_type type) | ||
1598 | { | ||
1599 | struct cx231xx_fh *fh = priv; | ||
1600 | struct cx231xx *dev = fh->dev; | ||
1601 | int rc; | ||
1602 | |||
1603 | rc = check_dev(dev); | ||
1604 | if (rc < 0) | ||
1605 | return rc; | ||
1606 | |||
1607 | if ( (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
1608 | (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) ) | ||
1609 | return -EINVAL; | ||
1610 | if (type != fh->type) | ||
1611 | return -EINVAL; | ||
1612 | |||
1613 | mutex_lock(&dev->lock); | ||
1614 | |||
1615 | videobuf_streamoff(&fh->vb_vidq); | ||
1616 | res_free(fh); | ||
1617 | |||
1618 | mutex_unlock(&dev->lock); | ||
1619 | |||
1620 | return 0; | ||
1621 | } | ||
1622 | |||
1623 | static int vidioc_querycap(struct file *file, void *priv, | ||
1624 | struct v4l2_capability *cap) | ||
1625 | { | ||
1626 | struct cx231xx_fh *fh = priv; | ||
1627 | struct cx231xx *dev = fh->dev; | ||
1628 | |||
1629 | strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); | ||
1630 | strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); | ||
1631 | strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info)); | ||
1632 | |||
1633 | cap->version = CX231XX_VERSION_CODE; | ||
1634 | |||
1635 | cap->capabilities = | ||
1636 | V4L2_CAP_VBI_CAPTURE | | ||
1637 | #if 0 | ||
1638 | V4L2_CAP_SLICED_VBI_CAPTURE | | ||
1639 | #endif | ||
1640 | V4L2_CAP_VIDEO_CAPTURE | | ||
1641 | V4L2_CAP_AUDIO | | ||
1642 | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | ||
1643 | |||
1644 | if (dev->tuner_type != TUNER_ABSENT) | ||
1645 | cap->capabilities |= V4L2_CAP_TUNER; | ||
1646 | |||
1647 | return 0; | ||
1648 | } | ||
1649 | |||
1650 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | ||
1651 | struct v4l2_fmtdesc *f) | ||
1652 | { | ||
1653 | if (unlikely(f->index >= ARRAY_SIZE(format))) | ||
1654 | return -EINVAL; | ||
1655 | |||
1656 | strlcpy(f->description, format[f->index].name, sizeof(f->description)); | ||
1657 | f->pixelformat = format[f->index].fourcc; | ||
1658 | |||
1659 | return 0; | ||
1660 | } | ||
1661 | |||
1662 | /* Sliced VBI ioctls */ | ||
1663 | static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, | ||
1664 | struct v4l2_format *f) | ||
1665 | { | ||
1666 | struct cx231xx_fh *fh = priv; | ||
1667 | struct cx231xx *dev = fh->dev; | ||
1668 | int rc; | ||
1669 | |||
1670 | rc = check_dev(dev); | ||
1671 | if (rc < 0) | ||
1672 | return rc; | ||
1673 | |||
1674 | mutex_lock(&dev->lock); | ||
1675 | |||
1676 | f->fmt.sliced.service_set = 0; | ||
1677 | |||
1678 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_FMT, f); | ||
1679 | |||
1680 | if (f->fmt.sliced.service_set == 0) | ||
1681 | rc = -EINVAL; | ||
1682 | |||
1683 | mutex_unlock(&dev->lock); | ||
1684 | return rc; | ||
1685 | } | ||
1686 | |||
1687 | static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, | ||
1688 | struct v4l2_format *f) | ||
1689 | { | ||
1690 | struct cx231xx_fh *fh = priv; | ||
1691 | struct cx231xx *dev = fh->dev; | ||
1692 | int rc; | ||
1693 | |||
1694 | rc = check_dev(dev); | ||
1695 | if (rc < 0) | ||
1696 | return rc; | ||
1697 | |||
1698 | mutex_lock(&dev->lock); | ||
1699 | cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_FMT, f); | ||
1700 | mutex_unlock(&dev->lock); | ||
1701 | |||
1702 | if (f->fmt.sliced.service_set == 0) | ||
1703 | return -EINVAL; | ||
1704 | |||
1705 | return 0; | ||
1706 | } | ||
1707 | |||
1708 | |||
1709 | /* RAW VBI ioctls */ | ||
1710 | |||
1711 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, | ||
1712 | struct v4l2_format *f) | ||
1713 | { | ||
1714 | struct cx231xx_fh *fh = priv; | ||
1715 | struct cx231xx *dev = fh->dev; | ||
1716 | |||
1717 | f->fmt.vbi.sampling_rate = (dev->norm & V4L2_STD_625_50) ? | ||
1718 | 35468950:28636363; | ||
1719 | f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; | ||
1720 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | ||
1721 | f->fmt.vbi.offset = 64 * 4; | ||
1722 | f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? | ||
1723 | PAL_VBI_START_LINE : NTSC_VBI_START_LINE; | ||
1724 | f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? | ||
1725 | PAL_VBI_LINES : NTSC_VBI_LINES; | ||
1726 | f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? | ||
1727 | PAL_VBI_START_LINE+312 : NTSC_VBI_START_LINE + 263; | ||
1728 | f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; | ||
1729 | |||
1730 | return 0; | ||
1731 | |||
1732 | } | ||
1733 | |||
1734 | static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv, | ||
1735 | struct v4l2_format *f) | ||
1736 | { | ||
1737 | struct cx231xx_fh *fh = priv; | ||
1738 | struct cx231xx *dev = fh->dev; | ||
1739 | |||
1740 | if (dev->vbi_stream_on && !fh->stream_on) { | ||
1741 | cx231xx_errdev("%s device in use by another fh\n", __func__); | ||
1742 | return -EBUSY; | ||
1743 | } | ||
1744 | |||
1745 | f->type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1746 | f->fmt.vbi.sampling_rate = (dev->norm & V4L2_STD_625_50) ? | ||
1747 | 35468950:28636363; | ||
1748 | f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; | ||
1749 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | ||
1750 | f->fmt.vbi.offset = 244; | ||
1751 | f->fmt.vbi.flags = 0; | ||
1752 | f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? | ||
1753 | PAL_VBI_START_LINE : NTSC_VBI_START_LINE; | ||
1754 | f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? | ||
1755 | PAL_VBI_LINES : NTSC_VBI_LINES; | ||
1756 | f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? | ||
1757 | PAL_VBI_START_LINE+312 : NTSC_VBI_START_LINE + 263; | ||
1758 | f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; | ||
1759 | |||
1760 | return 0; | ||
1761 | |||
1762 | } | ||
1763 | |||
1764 | static int vidioc_reqbufs(struct file *file, void *priv, | ||
1765 | struct v4l2_requestbuffers *rb) | ||
1766 | { | ||
1767 | struct cx231xx_fh *fh = priv; | ||
1768 | struct cx231xx *dev = fh->dev; | ||
1769 | int rc; | ||
1770 | |||
1771 | rc = check_dev(dev); | ||
1772 | if (rc < 0) | ||
1773 | return rc; | ||
1774 | |||
1775 | return (videobuf_reqbufs(&fh->vb_vidq, rb)); | ||
1776 | } | ||
1777 | |||
1778 | static int vidioc_querybuf(struct file *file, void *priv, | ||
1779 | struct v4l2_buffer *b) | ||
1780 | { | ||
1781 | struct cx231xx_fh *fh = priv; | ||
1782 | struct cx231xx *dev = fh->dev; | ||
1783 | int rc; | ||
1784 | |||
1785 | rc = check_dev(dev); | ||
1786 | if (rc < 0) | ||
1787 | return rc; | ||
1788 | |||
1789 | return (videobuf_querybuf(&fh->vb_vidq, b)); | ||
1790 | } | ||
1791 | |||
1792 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) | ||
1793 | { | ||
1794 | struct cx231xx_fh *fh = priv; | ||
1795 | struct cx231xx *dev = fh->dev; | ||
1796 | int rc; | ||
1797 | |||
1798 | rc = check_dev(dev); | ||
1799 | if (rc < 0) | ||
1800 | return rc; | ||
1801 | |||
1802 | return (videobuf_qbuf(&fh->vb_vidq, b)); | ||
1803 | } | ||
1804 | |||
1805 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | ||
1806 | { | ||
1807 | struct cx231xx_fh *fh = priv; | ||
1808 | struct cx231xx *dev = fh->dev; | ||
1809 | int rc; | ||
1810 | |||
1811 | rc = check_dev(dev); | ||
1812 | if (rc < 0) | ||
1813 | return rc; | ||
1814 | |||
1815 | return (videobuf_dqbuf(&fh->vb_vidq, b, | ||
1816 | file->f_flags & O_NONBLOCK)); | ||
1817 | } | ||
1818 | |||
1819 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1820 | static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) | ||
1821 | { | ||
1822 | struct cx231xx_fh *fh = priv; | ||
1823 | |||
1824 | return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); | ||
1825 | } | ||
1826 | #endif | ||
1827 | |||
1828 | |||
1829 | /* ----------------------------------------------------------- */ | ||
1830 | /* RADIO ESPECIFIC IOCTLS */ | ||
1831 | /* ----------------------------------------------------------- */ | ||
1832 | |||
1833 | static int radio_querycap(struct file *file, void *priv, | ||
1834 | struct v4l2_capability *cap) | ||
1835 | { | ||
1836 | struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; | ||
1837 | |||
1838 | strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); | ||
1839 | strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); | ||
1840 | usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); | ||
1841 | |||
1842 | cap->version = CX231XX_VERSION_CODE; | ||
1843 | cap->capabilities = V4L2_CAP_TUNER; | ||
1844 | return 0; | ||
1845 | } | ||
1846 | |||
1847 | static int radio_g_tuner(struct file *file, void *priv, | ||
1848 | struct v4l2_tuner *t) | ||
1849 | { | ||
1850 | struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; | ||
1851 | |||
1852 | if (unlikely(t->index > 0)) | ||
1853 | return -EINVAL; | ||
1854 | |||
1855 | strcpy(t->name, "Radio"); | ||
1856 | t->type = V4L2_TUNER_RADIO; | ||
1857 | |||
1858 | mutex_lock(&dev->lock); | ||
1859 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); | ||
1860 | mutex_unlock(&dev->lock); | ||
1861 | |||
1862 | return 0; | ||
1863 | } | ||
1864 | |||
1865 | static int radio_enum_input(struct file *file, void *priv, | ||
1866 | struct v4l2_input *i) | ||
1867 | { | ||
1868 | if (i->index != 0) | ||
1869 | return -EINVAL; | ||
1870 | strcpy(i->name, "Radio"); | ||
1871 | i->type = V4L2_INPUT_TYPE_TUNER; | ||
1872 | |||
1873 | return 0; | ||
1874 | } | ||
1875 | |||
1876 | static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) | ||
1877 | { | ||
1878 | if (unlikely(a->index)) | ||
1879 | return -EINVAL; | ||
1880 | |||
1881 | strcpy(a->name, "Radio"); | ||
1882 | return 0; | ||
1883 | } | ||
1884 | |||
1885 | static int radio_s_tuner(struct file *file, void *priv, | ||
1886 | struct v4l2_tuner *t) | ||
1887 | { | ||
1888 | struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; | ||
1889 | |||
1890 | if (0 != t->index) | ||
1891 | return -EINVAL; | ||
1892 | |||
1893 | mutex_lock(&dev->lock); | ||
1894 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); | ||
1895 | mutex_unlock(&dev->lock); | ||
1896 | |||
1897 | return 0; | ||
1898 | } | ||
1899 | |||
1900 | static int radio_s_audio(struct file *file, void *fh, | ||
1901 | struct v4l2_audio *a) | ||
1902 | { | ||
1903 | return 0; | ||
1904 | } | ||
1905 | |||
1906 | static int radio_s_input(struct file *file, void *fh, unsigned int i) | ||
1907 | { | ||
1908 | return 0; | ||
1909 | } | ||
1910 | |||
1911 | static int radio_queryctrl(struct file *file, void *priv, | ||
1912 | struct v4l2_queryctrl *c) | ||
1913 | { | ||
1914 | int i; | ||
1915 | |||
1916 | if (c->id < V4L2_CID_BASE || | ||
1917 | c->id >= V4L2_CID_LASTP1) | ||
1918 | return -EINVAL; | ||
1919 | if (c->id == V4L2_CID_AUDIO_MUTE) { | ||
1920 | for (i = 0; i < CX231XX_CTLS; i++) | ||
1921 | if (cx231xx_ctls[i].v.id == c->id) | ||
1922 | break; | ||
1923 | *c = cx231xx_ctls[i].v; | ||
1924 | } else | ||
1925 | *c = no_ctl; | ||
1926 | return 0; | ||
1927 | } | ||
1928 | |||
1929 | /* | ||
1930 | * cx231xx_v4l2_open() | ||
1931 | * inits the device and starts isoc transfer | ||
1932 | */ | ||
1933 | static int cx231xx_v4l2_open(struct file *filp) | ||
1934 | { | ||
1935 | int minor = video_devdata(filp)->minor; | ||
1936 | int errCode = 0, radio = 0; | ||
1937 | struct cx231xx *dev = NULL; | ||
1938 | struct cx231xx_fh *fh; | ||
1939 | enum v4l2_buf_type fh_type = 0; | ||
1940 | |||
1941 | dev = cx231xx_get_device(minor, &fh_type, &radio); | ||
1942 | if (NULL == dev) | ||
1943 | return -ENODEV; | ||
1944 | |||
1945 | mutex_lock(&dev->lock); | ||
1946 | |||
1947 | cx231xx_videodbg("open minor=%d type=%s users=%d\n", | ||
1948 | minor, v4l2_type_names[fh_type], dev->users); | ||
1949 | |||
1950 | #if 0 | ||
1951 | errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); | ||
1952 | if (errCode < 0) { | ||
1953 | cx231xx_errdev("Device locked on digital mode. Can't open analog\n"); | ||
1954 | mutex_unlock(&dev->lock); | ||
1955 | return -EBUSY; | ||
1956 | } | ||
1957 | #endif | ||
1958 | |||
1959 | fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL); | ||
1960 | if (!fh) { | ||
1961 | cx231xx_errdev("cx231xx-video.c: Out of memory?!\n"); | ||
1962 | mutex_unlock(&dev->lock); | ||
1963 | return -ENOMEM; | ||
1964 | } | ||
1965 | fh->dev = dev; | ||
1966 | fh->radio = radio; | ||
1967 | fh->type = fh_type; | ||
1968 | filp->private_data = fh; | ||
1969 | |||
1970 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { | ||
1971 | dev->width = norm_maxw(dev); | ||
1972 | dev->height = norm_maxh(dev); | ||
1973 | dev->hscale = 0; | ||
1974 | dev->vscale = 0; | ||
1975 | |||
1976 | |||
1977 | /* Power up in Analog TV mode */ | ||
1978 | cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); | ||
1979 | |||
1980 | #if 0 | ||
1981 | cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); | ||
1982 | #endif | ||
1983 | cx231xx_resolution_set(dev); | ||
1984 | |||
1985 | /* set video alternate setting */ | ||
1986 | cx231xx_set_video_alternate(dev); | ||
1987 | |||
1988 | /* Needed, since GPIO might have disabled power of | ||
1989 | some i2c device */ | ||
1990 | cx231xx_config_i2c(dev); | ||
1991 | |||
1992 | /* device needs to be initialized before isoc transfer */ | ||
1993 | dev->video_input = dev->video_input > 2 ? 2: dev->video_input; | ||
1994 | video_mux(dev, dev->video_input ); | ||
1995 | |||
1996 | } | ||
1997 | if (fh->radio) { | ||
1998 | cx231xx_videodbg("video_open: setting radio device\n"); | ||
1999 | |||
2000 | /* cx231xx_start_radio(dev); */ | ||
2001 | |||
2002 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], AUDC_SET_RADIO, NULL); | ||
2003 | } | ||
2004 | |||
2005 | dev->users++; | ||
2006 | |||
2007 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
2008 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops, | ||
2009 | NULL, &dev->video_mode.slock, fh->type, V4L2_FIELD_INTERLACED, /* V4L2_FIELD_SEQ_TB, */ | ||
2010 | sizeof(struct cx231xx_buffer), fh); | ||
2011 | } | ||
2012 | |||
2013 | if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
2014 | |||
2015 | /* Set the required alternate setting VBI interface works in Bulk mode only */ | ||
2016 | cx231xx_set_alt_setting(dev, INDEX_VANC, 0); | ||
2017 | |||
2018 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, | ||
2019 | NULL, &dev->vbi_mode.slock, fh->type, V4L2_FIELD_SEQ_TB, /* V4L2_FIELD_INTERLACED, */ | ||
2020 | sizeof(struct cx231xx_buffer), fh); | ||
2021 | } | ||
2022 | |||
2023 | mutex_unlock(&dev->lock); | ||
2024 | |||
2025 | return errCode; | ||
2026 | } | ||
2027 | |||
2028 | /* | ||
2029 | * cx231xx_realease_resources() | ||
2030 | * unregisters the v4l2,i2c and usb devices | ||
2031 | * called when the device gets disconected or at module unload | ||
2032 | */ | ||
2033 | void cx231xx_release_analog_resources(struct cx231xx *dev) | ||
2034 | { | ||
2035 | |||
2036 | /*FIXME: I2C IR should be disconnected */ | ||
2037 | |||
2038 | if (dev->radio_dev) { | ||
2039 | if (-1 != dev->radio_dev->minor) | ||
2040 | video_unregister_device(dev->radio_dev); | ||
2041 | else | ||
2042 | video_device_release(dev->radio_dev); | ||
2043 | dev->radio_dev = NULL; | ||
2044 | } | ||
2045 | if (dev->vbi_dev) { | ||
2046 | cx231xx_info("V4L2 device /dev/vbi%d deregistered\n", | ||
2047 | dev->vbi_dev->num); | ||
2048 | if (-1 != dev->vbi_dev->minor) | ||
2049 | video_unregister_device(dev->vbi_dev); | ||
2050 | else | ||
2051 | video_device_release(dev->vbi_dev); | ||
2052 | dev->vbi_dev = NULL; | ||
2053 | } | ||
2054 | if (dev->vdev) { | ||
2055 | cx231xx_info("V4L2 device /dev/video%d deregistered\n", | ||
2056 | dev->vdev->num); | ||
2057 | if (-1 != dev->vdev->minor) | ||
2058 | video_unregister_device(dev->vdev); | ||
2059 | else | ||
2060 | video_device_release(dev->vdev); | ||
2061 | dev->vdev = NULL; | ||
2062 | } | ||
2063 | } | ||
2064 | |||
2065 | /* | ||
2066 | * cx231xx_v4l2_close() | ||
2067 | * stops streaming and deallocates all resources allocated by the v4l2 | ||
2068 | * calls and ioctls | ||
2069 | */ | ||
2070 | static int cx231xx_v4l2_close(struct file *filp) | ||
2071 | { | ||
2072 | struct cx231xx_fh *fh = filp->private_data; | ||
2073 | struct cx231xx *dev = fh->dev; | ||
2074 | |||
2075 | cx231xx_videodbg("users=%d\n", dev->users); | ||
2076 | |||
2077 | mutex_lock(&dev->lock); | ||
2078 | |||
2079 | if (res_check(fh)) | ||
2080 | res_free(fh); | ||
2081 | |||
2082 | if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
2083 | videobuf_stop(&fh->vb_vidq); | ||
2084 | videobuf_mmap_free(&fh->vb_vidq); | ||
2085 | |||
2086 | /* the device is already disconnect, | ||
2087 | free the remaining resources */ | ||
2088 | if (dev->state & DEV_DISCONNECTED) { | ||
2089 | cx231xx_release_resources(dev); | ||
2090 | mutex_unlock(&dev->lock); | ||
2091 | kfree(dev); | ||
2092 | return 0; | ||
2093 | } | ||
2094 | |||
2095 | /* do this before setting alternate! */ | ||
2096 | cx231xx_uninit_vbi_isoc(dev); | ||
2097 | |||
2098 | /* set alternate 0 */ | ||
2099 | if( !dev->vbi_or_sliced_cc_mode) { | ||
2100 | cx231xx_set_alt_setting(dev, INDEX_VANC, 0); | ||
2101 | } else { | ||
2102 | cx231xx_set_alt_setting(dev, INDEX_HANC, 0); | ||
2103 | } | ||
2104 | |||
2105 | kfree(fh); | ||
2106 | dev->users--; | ||
2107 | wake_up_interruptible_nr(&dev->open, 1); | ||
2108 | mutex_unlock(&dev->lock); | ||
2109 | return 0; | ||
2110 | } | ||
2111 | |||
2112 | if (dev->users == 1) { | ||
2113 | videobuf_stop(&fh->vb_vidq); | ||
2114 | videobuf_mmap_free(&fh->vb_vidq); | ||
2115 | |||
2116 | /* the device is already disconnect, | ||
2117 | free the remaining resources */ | ||
2118 | if (dev->state & DEV_DISCONNECTED) { | ||
2119 | cx231xx_release_resources(dev); | ||
2120 | mutex_unlock(&dev->lock); | ||
2121 | kfree(dev); | ||
2122 | return 0; | ||
2123 | } | ||
2124 | |||
2125 | /* Save some power by putting tuner to sleep */ | ||
2126 | cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, NULL); | ||
2127 | |||
2128 | /* do this before setting alternate! */ | ||
2129 | cx231xx_uninit_isoc(dev); | ||
2130 | cx231xx_set_mode(dev, CX231XX_SUSPEND); | ||
2131 | |||
2132 | /* set alternate 0 */ | ||
2133 | cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); | ||
2134 | } | ||
2135 | kfree(fh); | ||
2136 | dev->users--; | ||
2137 | wake_up_interruptible_nr(&dev->open, 1); | ||
2138 | mutex_unlock(&dev->lock); | ||
2139 | return 0; | ||
2140 | } | ||
2141 | |||
2142 | /* | ||
2143 | * cx231xx_v4l2_read() | ||
2144 | * will allocate buffers when called for the first time | ||
2145 | */ | ||
2146 | static ssize_t | ||
2147 | cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, | ||
2148 | loff_t *pos) | ||
2149 | { | ||
2150 | struct cx231xx_fh *fh = filp->private_data; | ||
2151 | struct cx231xx *dev = fh->dev; | ||
2152 | int rc; | ||
2153 | |||
2154 | rc = check_dev(dev); | ||
2155 | if (rc < 0) | ||
2156 | return rc; | ||
2157 | |||
2158 | if ( (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
2159 | (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) ) { | ||
2160 | mutex_lock(&dev->lock); | ||
2161 | rc = res_get(fh); | ||
2162 | mutex_unlock(&dev->lock); | ||
2163 | |||
2164 | if (unlikely(rc < 0)) | ||
2165 | return rc; | ||
2166 | |||
2167 | return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, | ||
2168 | filp->f_flags & O_NONBLOCK); | ||
2169 | } | ||
2170 | return 0; | ||
2171 | } | ||
2172 | |||
2173 | /* | ||
2174 | * cx231xx_v4l2_poll() | ||
2175 | * will allocate buffers when called for the first time | ||
2176 | */ | ||
2177 | static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table * wait) | ||
2178 | { | ||
2179 | struct cx231xx_fh *fh = filp->private_data; | ||
2180 | struct cx231xx *dev = fh->dev; | ||
2181 | int rc; | ||
2182 | |||
2183 | rc = check_dev(dev); | ||
2184 | if (rc < 0) | ||
2185 | return rc; | ||
2186 | |||
2187 | mutex_lock(&dev->lock); | ||
2188 | rc = res_get(fh); | ||
2189 | mutex_unlock(&dev->lock); | ||
2190 | |||
2191 | if (unlikely(rc < 0)) | ||
2192 | return POLLERR; | ||
2193 | |||
2194 | if ( (V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) || | ||
2195 | (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) ) | ||
2196 | return videobuf_poll_stream(filp, &fh->vb_vidq, wait); | ||
2197 | else | ||
2198 | return POLLERR; | ||
2199 | } | ||
2200 | |||
2201 | /* | ||
2202 | * cx231xx_v4l2_mmap() | ||
2203 | */ | ||
2204 | static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) | ||
2205 | { | ||
2206 | struct cx231xx_fh *fh = filp->private_data; | ||
2207 | struct cx231xx *dev = fh->dev; | ||
2208 | int rc; | ||
2209 | |||
2210 | rc = check_dev(dev); | ||
2211 | if (rc < 0) | ||
2212 | return rc; | ||
2213 | |||
2214 | mutex_lock(&dev->lock); | ||
2215 | rc = res_get(fh); | ||
2216 | mutex_unlock(&dev->lock); | ||
2217 | |||
2218 | if (unlikely(rc < 0)) | ||
2219 | return rc; | ||
2220 | |||
2221 | rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); | ||
2222 | |||
2223 | cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", | ||
2224 | (unsigned long)vma->vm_start, | ||
2225 | (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, | ||
2226 | rc); | ||
2227 | |||
2228 | return rc; | ||
2229 | } | ||
2230 | |||
2231 | static const struct v4l2_file_operations cx231xx_v4l_fops = { | ||
2232 | .owner = THIS_MODULE, | ||
2233 | .open = cx231xx_v4l2_open, | ||
2234 | .release = cx231xx_v4l2_close, | ||
2235 | .read = cx231xx_v4l2_read, | ||
2236 | .poll = cx231xx_v4l2_poll, | ||
2237 | .mmap = cx231xx_v4l2_mmap, | ||
2238 | .ioctl = video_ioctl2, | ||
2239 | }; | ||
2240 | |||
2241 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
2242 | .vidioc_querycap = vidioc_querycap, | ||
2243 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
2244 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
2245 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
2246 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
2247 | .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, | ||
2248 | .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, | ||
2249 | .vidioc_s_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, | ||
2250 | .vidioc_g_audio = vidioc_g_audio, | ||
2251 | .vidioc_s_audio = vidioc_s_audio, | ||
2252 | .vidioc_cropcap = vidioc_cropcap, | ||
2253 | .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, | ||
2254 | .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, | ||
2255 | .vidioc_reqbufs = vidioc_reqbufs, | ||
2256 | .vidioc_querybuf = vidioc_querybuf, | ||
2257 | .vidioc_qbuf = vidioc_qbuf, | ||
2258 | .vidioc_dqbuf = vidioc_dqbuf, | ||
2259 | .vidioc_s_std = vidioc_s_std, | ||
2260 | .vidioc_g_std = vidioc_g_std, | ||
2261 | .vidioc_enum_input = vidioc_enum_input, | ||
2262 | .vidioc_g_input = vidioc_g_input, | ||
2263 | .vidioc_s_input = vidioc_s_input, | ||
2264 | .vidioc_queryctrl = vidioc_queryctrl, | ||
2265 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
2266 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
2267 | .vidioc_streamon = vidioc_streamon, | ||
2268 | .vidioc_streamoff = vidioc_streamoff, | ||
2269 | .vidioc_g_tuner = vidioc_g_tuner, | ||
2270 | .vidioc_s_tuner = vidioc_s_tuner, | ||
2271 | .vidioc_g_frequency = vidioc_g_frequency, | ||
2272 | .vidioc_s_frequency = vidioc_s_frequency, | ||
2273 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
2274 | .vidioc_g_register = vidioc_g_register, | ||
2275 | .vidioc_s_register = vidioc_s_register, | ||
2276 | #endif | ||
2277 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
2278 | .vidiocgmbuf = vidiocgmbuf, | ||
2279 | #endif | ||
2280 | }; | ||
2281 | |||
2282 | static struct video_device cx231xx_vbi_template; | ||
2283 | |||
2284 | static const struct video_device cx231xx_video_template = { | ||
2285 | .fops = &cx231xx_v4l_fops, | ||
2286 | .release = video_device_release, | ||
2287 | .ioctl_ops = &video_ioctl_ops, | ||
2288 | .minor = -1, | ||
2289 | .tvnorms = V4L2_STD_ALL, | ||
2290 | .current_norm = V4L2_STD_PAL, | ||
2291 | }; | ||
2292 | |||
2293 | static const struct v4l2_file_operations radio_fops = { | ||
2294 | .owner = THIS_MODULE, | ||
2295 | .open = cx231xx_v4l2_open, | ||
2296 | .release = cx231xx_v4l2_close, | ||
2297 | .ioctl = video_ioctl2, | ||
2298 | }; | ||
2299 | |||
2300 | static const struct v4l2_ioctl_ops radio_ioctl_ops = { | ||
2301 | .vidioc_querycap = radio_querycap, | ||
2302 | .vidioc_g_tuner = radio_g_tuner, | ||
2303 | .vidioc_enum_input = radio_enum_input, | ||
2304 | .vidioc_g_audio = radio_g_audio, | ||
2305 | .vidioc_s_tuner = radio_s_tuner, | ||
2306 | .vidioc_s_audio = radio_s_audio, | ||
2307 | .vidioc_s_input = radio_s_input, | ||
2308 | .vidioc_queryctrl = radio_queryctrl, | ||
2309 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
2310 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
2311 | .vidioc_g_frequency = vidioc_g_frequency, | ||
2312 | .vidioc_s_frequency = vidioc_s_frequency, | ||
2313 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
2314 | .vidioc_g_register = vidioc_g_register, | ||
2315 | .vidioc_s_register = vidioc_s_register, | ||
2316 | #endif | ||
2317 | }; | ||
2318 | |||
2319 | static struct video_device cx231xx_radio_template = { | ||
2320 | .name = "cx231xx-radio", | ||
2321 | .fops = &radio_fops, | ||
2322 | .ioctl_ops = &radio_ioctl_ops, | ||
2323 | .minor = -1, | ||
2324 | }; | ||
2325 | |||
2326 | /******************************** usb interface ******************************/ | ||
2327 | |||
2328 | |||
2329 | static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, | ||
2330 | const struct video_device *template, | ||
2331 | const char *type_name) | ||
2332 | { | ||
2333 | struct video_device *vfd; | ||
2334 | |||
2335 | vfd = video_device_alloc(); | ||
2336 | if (NULL == vfd) | ||
2337 | return NULL; | ||
2338 | *vfd = *template; | ||
2339 | vfd->minor = -1; | ||
2340 | vfd->parent = &dev->udev->dev; | ||
2341 | vfd->release = video_device_release; | ||
2342 | vfd->debug = video_debug; | ||
2343 | |||
2344 | snprintf(vfd->name, sizeof(vfd->name), "%s %s", | ||
2345 | dev->name, type_name); | ||
2346 | |||
2347 | return vfd; | ||
2348 | } | ||
2349 | |||
2350 | int cx231xx_register_analog_devices(struct cx231xx *dev) | ||
2351 | { | ||
2352 | int ret; | ||
2353 | |||
2354 | cx231xx_info("%s()\n", __func__); | ||
2355 | |||
2356 | cx231xx_info("%s: v4l2 driver version %d.%d.%d\n", | ||
2357 | dev->name, | ||
2358 | (CX231XX_VERSION_CODE >> 16) & 0xff, | ||
2359 | (CX231XX_VERSION_CODE >> 8) & 0xff, CX231XX_VERSION_CODE & 0xff); | ||
2360 | |||
2361 | /* set default norm */ | ||
2362 | /*dev->norm = cx231xx_video_template.current_norm;*/ | ||
2363 | dev->width = norm_maxw(dev); | ||
2364 | dev->height = norm_maxh(dev); | ||
2365 | dev->interlaced = 0; | ||
2366 | dev->hscale = 0; | ||
2367 | dev->vscale = 0; | ||
2368 | |||
2369 | /* Analog specific initialization */ | ||
2370 | dev->format = &format[0]; | ||
2371 | /* video_mux(dev, dev->video_input); */ | ||
2372 | |||
2373 | /* Audio defaults */ | ||
2374 | dev->mute = 1; | ||
2375 | dev->volume = 0x1f; | ||
2376 | |||
2377 | /* enable vbi capturing */ | ||
2378 | /* write code here... */ | ||
2379 | |||
2380 | /* allocate and fill video video_device struct */ | ||
2381 | dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video"); | ||
2382 | if (!dev->vdev) { | ||
2383 | cx231xx_errdev("cannot allocate video_device.\n"); | ||
2384 | return -ENODEV; | ||
2385 | } | ||
2386 | |||
2387 | /* register v4l2 video video_device */ | ||
2388 | ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, | ||
2389 | video_nr[dev->devno]); | ||
2390 | if (ret) { | ||
2391 | cx231xx_errdev("unable to register video device (error=%i).\n", ret); | ||
2392 | return ret; | ||
2393 | } | ||
2394 | |||
2395 | cx231xx_info("%s/0: registered device video%d [v4l2]\n", | ||
2396 | dev->name, dev->vdev->num); | ||
2397 | |||
2398 | /* Initialize VBI template */ | ||
2399 | memcpy( &cx231xx_vbi_template, &cx231xx_video_template, | ||
2400 | sizeof(cx231xx_vbi_template) ); | ||
2401 | strcpy(cx231xx_vbi_template.name,"cx231xx-vbi"); | ||
2402 | |||
2403 | |||
2404 | /* Allocate and fill vbi video_device struct */ | ||
2405 | dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi"); | ||
2406 | |||
2407 | /* register v4l2 vbi video_device */ | ||
2408 | ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, | ||
2409 | vbi_nr[dev->devno]); | ||
2410 | if (ret < 0) { | ||
2411 | cx231xx_errdev("unable to register vbi device\n"); | ||
2412 | return ret; | ||
2413 | } | ||
2414 | |||
2415 | cx231xx_info("%s/0: registered device vbi%d\n", | ||
2416 | dev->name, dev->vbi_dev->num); | ||
2417 | |||
2418 | if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) { | ||
2419 | dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template, "radio"); | ||
2420 | if (!dev->radio_dev) { | ||
2421 | cx231xx_errdev("cannot allocate video_device.\n"); | ||
2422 | return -ENODEV; | ||
2423 | } | ||
2424 | ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, | ||
2425 | radio_nr[dev->devno]); | ||
2426 | if (ret < 0) { | ||
2427 | cx231xx_errdev("can't register radio device\n"); | ||
2428 | return ret; | ||
2429 | } | ||
2430 | cx231xx_info("Registered radio device as /dev/radio%d\n", | ||
2431 | dev->radio_dev->num); | ||
2432 | } | ||
2433 | |||
2434 | cx231xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", | ||
2435 | dev->vdev->num, dev->vbi_dev->num); | ||
2436 | |||
2437 | return 0; | ||
2438 | } | ||
2439 | |||
2440 | |||
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h new file mode 100644 index 000000000000..5fef87fbbcec --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx.h | |||
@@ -0,0 +1,762 @@ | |||
1 | /* | ||
2 | cx231xx.h - driver for Conexant Cx23100/101/102 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
5 | Based on em28xx driver | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef _CX231XX_H | ||
23 | #define _CX231XX_H | ||
24 | |||
25 | #include <linux/videodev2.h> | ||
26 | #include <media/videobuf-vmalloc.h> | ||
27 | |||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/i2c-algo-bit.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <media/ir-kbd-i2c.h> | ||
32 | #if defined(CONFIG_VIDEO_CX231XX_DVB) || defined(CONFIG_VIDEO_CX231XX_DVB_MODULE) | ||
33 | #include <media/videobuf-dvb.h> | ||
34 | #endif | ||
35 | |||
36 | #include "cx231xx-reg.h" | ||
37 | #include "cx231xx-pcb-config.h" | ||
38 | #include "cx231xx-conf-reg.h" | ||
39 | |||
40 | #define CX231XX_VERSION_CODE KERNEL_VERSION(0, 1, 0) | ||
41 | #define DRIVER_NAME "cx231xx" | ||
42 | #define PWR_SLEEP_INTERVAL 5 | ||
43 | |||
44 | /* I2C addresses for control block in Cx231xx */ | ||
45 | #define Colibri_DEVICE_ADDRESS 0x60 | ||
46 | #define Flatrion_DEVICE_ADDRESS 0x98 | ||
47 | #define HAMMERHEAD_I2C_ADDRESS 0x88 | ||
48 | #define DIF_USE_BASEBAND 0xFFFFFFFF | ||
49 | |||
50 | /* Boards supported by driver */ | ||
51 | #define CX231XX_BOARD_UNKNOWN 0 | ||
52 | #define CX231XX_BOARD_CNXT_RDE_250 1 | ||
53 | #define CX231XX_BOARD_CNXT_RDU_250 2 | ||
54 | |||
55 | /* Limits minimum and default number of buffers */ | ||
56 | #define CX231XX_MIN_BUF 4 | ||
57 | #define CX231XX_DEF_BUF 12 | ||
58 | #define CX231XX_DEF_VBI_BUF 6 | ||
59 | |||
60 | #define VBI_LINE_COUNT 17 | ||
61 | #define VBI_LINE_LENGTH 1440 | ||
62 | |||
63 | /*Limits the max URB message size */ | ||
64 | #define URB_MAX_CTRL_SIZE 80 | ||
65 | |||
66 | /* Params for validated field */ | ||
67 | #define CX231XX_BOARD_NOT_VALIDATED 1 | ||
68 | #define CX231XX_BOARD_VALIDATED 0 | ||
69 | |||
70 | /* maximum number of cx231xx boards */ | ||
71 | #define CX231XX_MAXBOARDS 8 | ||
72 | |||
73 | /* maximum number of frames that can be queued */ | ||
74 | #define CX231XX_NUM_FRAMES 5 | ||
75 | |||
76 | /* number of buffers for isoc transfers */ | ||
77 | #define CX231XX_NUM_BUFS 8 | ||
78 | |||
79 | /* number of packets for each buffer | ||
80 | windows requests only 40 packets .. so we better do the same | ||
81 | this is what I found out for all alternate numbers there! | ||
82 | */ | ||
83 | #define CX231XX_NUM_PACKETS 40 | ||
84 | |||
85 | |||
86 | /* default alternate; 0 means choose the best */ | ||
87 | #define CX231XX_PINOUT 0 | ||
88 | |||
89 | #define CX231XX_INTERLACED_DEFAULT 1 | ||
90 | |||
91 | |||
92 | /* time to wait when stopping the isoc transfer */ | ||
93 | #define CX231XX_URB_TIMEOUT msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS) | ||
94 | |||
95 | |||
96 | enum cx231xx_mode { | ||
97 | CX231XX_SUSPEND, | ||
98 | CX231XX_ANALOG_MODE, | ||
99 | CX231XX_DIGITAL_MODE, | ||
100 | }; | ||
101 | |||
102 | enum cx231xx_std_mode { | ||
103 | CX231XX_TV_AIR = 0, | ||
104 | CX231XX_TV_CABLE | ||
105 | }; | ||
106 | |||
107 | enum cx231xx_stream_state { | ||
108 | STREAM_OFF, | ||
109 | STREAM_INTERRUPT, | ||
110 | STREAM_ON, | ||
111 | }; | ||
112 | |||
113 | struct cx231xx; | ||
114 | |||
115 | struct cx231xx_usb_isoc_ctl { | ||
116 | /* max packet size of isoc transaction */ | ||
117 | int max_pkt_size; | ||
118 | |||
119 | /* number of allocated urbs */ | ||
120 | int num_bufs; | ||
121 | |||
122 | /* urb for isoc transfers */ | ||
123 | struct urb **urb; | ||
124 | |||
125 | /* transfer buffers for isoc transfer */ | ||
126 | char **transfer_buffer; | ||
127 | |||
128 | /* Last buffer command and region */ | ||
129 | u8 cmd; | ||
130 | int pos, size, pktsize; | ||
131 | |||
132 | /* Last field: ODD or EVEN? */ | ||
133 | int field; | ||
134 | |||
135 | /* Stores incomplete commands */ | ||
136 | u32 tmp_buf; | ||
137 | int tmp_buf_len; | ||
138 | |||
139 | /* Stores already requested buffers */ | ||
140 | struct cx231xx_buffer *buf; | ||
141 | |||
142 | /* Stores the number of received fields */ | ||
143 | int nfields; | ||
144 | |||
145 | /* isoc urb callback */ | ||
146 | int (*isoc_copy) (struct cx231xx *dev, struct urb *urb); | ||
147 | |||
148 | }; | ||
149 | |||
150 | |||
151 | |||
152 | struct cx231xx_fmt { | ||
153 | char *name; | ||
154 | u32 fourcc; /* v4l2 format id */ | ||
155 | int depth; | ||
156 | int reg; | ||
157 | }; | ||
158 | |||
159 | /* buffer for one video frame */ | ||
160 | struct cx231xx_buffer { | ||
161 | /* common v4l buffer stuff -- must be first */ | ||
162 | struct videobuf_buffer vb; | ||
163 | |||
164 | struct list_head frame; | ||
165 | int top_field; | ||
166 | int receiving; | ||
167 | }; | ||
168 | |||
169 | struct cx231xx_dmaqueue { | ||
170 | struct list_head active; | ||
171 | struct list_head queued; | ||
172 | |||
173 | wait_queue_head_t wq; | ||
174 | |||
175 | /* Counters to control buffer fill */ | ||
176 | int pos; | ||
177 | u8 is_partial_line; | ||
178 | u8 partial_buf[8]; | ||
179 | u8 last_sav; | ||
180 | int current_field; | ||
181 | u32 bytes_left_in_line; | ||
182 | u32 lines_completed; | ||
183 | u8 field1_done; | ||
184 | u32 lines_per_field; | ||
185 | }; | ||
186 | |||
187 | |||
188 | /* inputs */ | ||
189 | |||
190 | #define MAX_CX231XX_INPUT 4 | ||
191 | |||
192 | enum cx231xx_itype { | ||
193 | CX231XX_VMUX_COMPOSITE1 = 1, | ||
194 | CX231XX_VMUX_SVIDEO, | ||
195 | CX231XX_VMUX_TELEVISION, | ||
196 | CX231XX_VMUX_CABLE, | ||
197 | CX231XX_RADIO, | ||
198 | CX231XX_VMUX_DVB, | ||
199 | CX231XX_VMUX_DEBUG | ||
200 | }; | ||
201 | |||
202 | enum cx231xx_v_input { | ||
203 | CX231XX_VIN_1_1 = 0x1, | ||
204 | CX231XX_VIN_2_1, | ||
205 | CX231XX_VIN_3_1, | ||
206 | CX231XX_VIN_4_1, | ||
207 | CX231XX_VIN_1_2 = 0x01, | ||
208 | CX231XX_VIN_2_2, | ||
209 | CX231XX_VIN_3_2, | ||
210 | CX231XX_VIN_1_3 = 0x1, | ||
211 | CX231XX_VIN_2_3, | ||
212 | CX231XX_VIN_3_3, | ||
213 | }; | ||
214 | |||
215 | /* cx231xx has two audio inputs: tuner and line in */ | ||
216 | enum cx231xx_amux { | ||
217 | /* This is the only entry for cx231xx tuner input */ | ||
218 | CX231XX_AMUX_VIDEO, /* cx231xx tuner*/ | ||
219 | CX231XX_AMUX_LINE_IN, /* Line In */ | ||
220 | }; | ||
221 | |||
222 | struct cx231xx_reg_seq { | ||
223 | unsigned char bit; | ||
224 | unsigned char val; | ||
225 | int sleep; | ||
226 | }; | ||
227 | |||
228 | struct cx231xx_input { | ||
229 | enum cx231xx_itype type; | ||
230 | unsigned int vmux; | ||
231 | enum cx231xx_amux amux; | ||
232 | struct cx231xx_reg_seq *gpio; | ||
233 | }; | ||
234 | |||
235 | #define INPUT(nr) (&cx231xx_boards[dev->model].input[nr]) | ||
236 | |||
237 | enum cx231xx_decoder { | ||
238 | CX231XX_NODECODER, | ||
239 | CX231XX_AVDECODER | ||
240 | }; | ||
241 | |||
242 | typedef enum _I2C_MASTER_PORT | ||
243 | { | ||
244 | I2C_0 =0, | ||
245 | I2C_1 =1, | ||
246 | I2C_2 =2, | ||
247 | I2C_3 =3 | ||
248 | }CX231XX_I2C_MASTER_PORT; | ||
249 | |||
250 | struct cx231xx_board { | ||
251 | char *name; | ||
252 | int vchannels; | ||
253 | int tuner_type; | ||
254 | int tuner_addr; | ||
255 | v4l2_std_id norm; /* tv norm */ | ||
256 | |||
257 | /* demod related */ | ||
258 | int demod_addr; | ||
259 | u8 demod_xfer_mode; /* 0 - Serial; 1 - parallel */ | ||
260 | |||
261 | /* GPIO Pins */ | ||
262 | struct cx231xx_reg_seq *dvb_gpio; | ||
263 | struct cx231xx_reg_seq *suspend_gpio; | ||
264 | struct cx231xx_reg_seq *tuner_gpio; | ||
265 | u8 tuner_sif_gpio; | ||
266 | u8 tuner_scl_gpio; | ||
267 | u8 tuner_sda_gpio; | ||
268 | |||
269 | /* PIN ctrl */ | ||
270 | u32 ctl_pin_status_mask; | ||
271 | u8 agc_analog_digital_select_gpio; | ||
272 | u32 gpio_pin_status_mask; | ||
273 | |||
274 | /* i2c masters */ | ||
275 | u8 tuner_i2c_master; | ||
276 | u8 demod_i2c_master; | ||
277 | |||
278 | unsigned int max_range_640_480:1; | ||
279 | unsigned int has_dvb:1; | ||
280 | unsigned int valid:1; | ||
281 | |||
282 | unsigned char xclk, i2c_speed; | ||
283 | |||
284 | enum cx231xx_decoder decoder; | ||
285 | |||
286 | struct cx231xx_input input[MAX_CX231XX_INPUT]; | ||
287 | struct cx231xx_input radio; | ||
288 | IR_KEYTAB_TYPE *ir_codes; | ||
289 | }; | ||
290 | |||
291 | /* device states */ | ||
292 | enum cx231xx_dev_state { | ||
293 | DEV_INITIALIZED = 0x01, | ||
294 | DEV_DISCONNECTED = 0x02, | ||
295 | DEV_MISCONFIGURED = 0x04, | ||
296 | }; | ||
297 | |||
298 | enum AFE_MODE | ||
299 | { | ||
300 | AFE_MODE_LOW_IF, | ||
301 | AFE_MODE_BASEBAND, | ||
302 | AFE_MODE_EU_HI_IF, | ||
303 | AFE_MODE_US_HI_IF, | ||
304 | AFE_MODE_JAPAN_HI_IF | ||
305 | }; | ||
306 | |||
307 | enum AUDIO_INPUT | ||
308 | { | ||
309 | AUDIO_INPUT_MUTE, | ||
310 | AUDIO_INPUT_LINE, | ||
311 | AUDIO_INPUT_TUNER_TV, | ||
312 | AUDIO_INPUT_SPDIF, | ||
313 | AUDIO_INPUT_TUNER_FM | ||
314 | }; | ||
315 | |||
316 | #define CX231XX_AUDIO_BUFS 5 | ||
317 | #define CX231XX_NUM_AUDIO_PACKETS 64 | ||
318 | #define CX231XX_CAPTURE_STREAM_EN 1 | ||
319 | #define CX231XX_STOP_AUDIO 0 | ||
320 | #define CX231XX_START_AUDIO 1 | ||
321 | |||
322 | |||
323 | /* cx231xx extensions */ | ||
324 | #define CX231XX_AUDIO 0x10 | ||
325 | #define CX231XX_DVB 0x20 | ||
326 | |||
327 | struct cx231xx_audio { | ||
328 | char name[50]; | ||
329 | char *transfer_buffer[CX231XX_AUDIO_BUFS]; | ||
330 | struct urb *urb[CX231XX_AUDIO_BUFS]; | ||
331 | struct usb_device *udev; | ||
332 | unsigned int capture_transfer_done; | ||
333 | struct snd_pcm_substream *capture_pcm_substream; | ||
334 | |||
335 | unsigned int hwptr_done_capture; | ||
336 | struct snd_card *sndcard; | ||
337 | |||
338 | int users, shutdown; | ||
339 | enum cx231xx_stream_state capture_stream; | ||
340 | spinlock_t slock; | ||
341 | |||
342 | int alt; /* alternate */ | ||
343 | int max_pkt_size; /* max packet size of isoc transaction */ | ||
344 | int num_alt; /* Number of alternative settings */ | ||
345 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ | ||
346 | u16 end_point_addr; | ||
347 | }; | ||
348 | |||
349 | struct cx231xx; | ||
350 | |||
351 | struct cx231xx_fh { | ||
352 | struct cx231xx *dev; | ||
353 | unsigned int stream_on:1; /* Locks streams */ | ||
354 | int radio; | ||
355 | |||
356 | struct videobuf_queue vb_vidq; | ||
357 | |||
358 | enum v4l2_buf_type type; | ||
359 | }; | ||
360 | |||
361 | /**********************************************************************************/ | ||
362 | /* set/get i2c */ | ||
363 | #define I2C_SPEED_1M 0x0 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ | ||
364 | #define I2C_SPEED_400K 0x1 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ | ||
365 | #define I2C_SPEED_100K 0x2 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ | ||
366 | #define I2C_SPEED_5M 0x3 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ | ||
367 | |||
368 | #define I2C_STOP 0x0 /* 0-- STOP transaction */ | ||
369 | #define I2C_NOSTOP 0x1 /* 1-- do not transmit STOP at end of transaction */ | ||
370 | #define I2C_SYNC 0x1 /* 1--alllow slave to insert clock wait states */ | ||
371 | |||
372 | struct cx231xx_i2c { | ||
373 | struct cx231xx *dev; | ||
374 | |||
375 | int nr; | ||
376 | |||
377 | /* i2c i/o */ | ||
378 | struct i2c_adapter i2c_adap; | ||
379 | struct i2c_algo_bit_data i2c_algo; | ||
380 | struct i2c_client i2c_client; | ||
381 | u32 i2c_rc; | ||
382 | |||
383 | /* different settings for each bus */ | ||
384 | u8 i2c_period; | ||
385 | u8 i2c_nostop; | ||
386 | u8 i2c_reserve; | ||
387 | }; | ||
388 | |||
389 | struct cx231xx_i2c_xfer_data{ | ||
390 | u8 dev_addr; | ||
391 | u8 direction; /* 1 - IN, 0 - OUT */ | ||
392 | u8 saddr_len; /* sub address len */ | ||
393 | u16 saddr_dat; /* sub addr data */ | ||
394 | u8 buf_size; /* buffer size */ | ||
395 | u8* p_buffer; /* pointer to the buffer */ | ||
396 | }; | ||
397 | |||
398 | typedef struct _VENDOR_REQUEST_IN | ||
399 | { | ||
400 | u8 bRequest; | ||
401 | u16 wValue; | ||
402 | u16 wIndex; | ||
403 | u16 wLength; | ||
404 | u8 direction; | ||
405 | u8 bData; | ||
406 | u8 *pBuff; | ||
407 | } VENDOR_REQUEST_IN, *PVENDOR_REQUEST_IN; | ||
408 | |||
409 | struct cx231xx_ctrl { | ||
410 | struct v4l2_queryctrl v; | ||
411 | u32 off; | ||
412 | u32 reg; | ||
413 | u32 mask; | ||
414 | u32 shift; | ||
415 | }; | ||
416 | |||
417 | typedef enum{ | ||
418 | Raw_Video = 0, | ||
419 | Audio, | ||
420 | Vbi, /* VANC */ | ||
421 | Sliced_cc, /* HANC */ | ||
422 | TS1_serial_mode, | ||
423 | TS2, | ||
424 | TS1_parallel_mode | ||
425 | }TRANSFER_TYPE; | ||
426 | |||
427 | struct cx231xx_video_mode { | ||
428 | /* Isoc control struct */ | ||
429 | struct cx231xx_dmaqueue vidq; | ||
430 | struct cx231xx_usb_isoc_ctl isoc_ctl; | ||
431 | spinlock_t slock; | ||
432 | |||
433 | /* usb transfer */ | ||
434 | int alt; /* alternate */ | ||
435 | int max_pkt_size; /* max packet size of isoc transaction */ | ||
436 | int num_alt; /* Number of alternative settings */ | ||
437 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ | ||
438 | u16 end_point_addr; | ||
439 | }; | ||
440 | |||
441 | |||
442 | /* main device struct */ | ||
443 | struct cx231xx { | ||
444 | /* generic device properties */ | ||
445 | char name[30]; /* name (including minor) of the device */ | ||
446 | int model; /* index in the device_data struct */ | ||
447 | int devno; /* marks the number of this device */ | ||
448 | |||
449 | struct cx231xx_board board; | ||
450 | |||
451 | unsigned int stream_on:1; /* Locks streams */ | ||
452 | unsigned int vbi_stream_on:1; /* Locks streams for VBI */ | ||
453 | unsigned int has_audio_class:1; | ||
454 | unsigned int has_alsa_audio:1; | ||
455 | |||
456 | struct cx231xx_fmt *format; | ||
457 | |||
458 | struct cx231xx_IR *ir; | ||
459 | |||
460 | struct list_head devlist; | ||
461 | |||
462 | int tuner_type; /* type of the tuner */ | ||
463 | int tuner_addr; /* tuner address */ | ||
464 | |||
465 | /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ | ||
466 | struct cx231xx_i2c i2c_bus[3]; | ||
467 | unsigned int xc_fw_load_done:1; | ||
468 | struct mutex gpio_i2c_lock; | ||
469 | |||
470 | /* video for linux */ | ||
471 | int users; /* user count for exclusive use */ | ||
472 | struct video_device *vdev; /* video for linux device struct */ | ||
473 | v4l2_std_id norm; /* selected tv norm */ | ||
474 | int ctl_freq; /* selected frequency */ | ||
475 | unsigned int ctl_ainput; /* selected audio input */ | ||
476 | int mute; | ||
477 | int volume; | ||
478 | |||
479 | /* frame properties */ | ||
480 | int width; /* current frame width */ | ||
481 | int height; /* current frame height */ | ||
482 | unsigned hscale; /* horizontal scale factor (see datasheet) */ | ||
483 | unsigned vscale; /* vertical scale factor (see datasheet) */ | ||
484 | int interlaced; /* 1=interlace fileds, 0=just top fileds */ | ||
485 | |||
486 | struct cx231xx_audio adev; | ||
487 | |||
488 | /* states */ | ||
489 | enum cx231xx_dev_state state; | ||
490 | |||
491 | struct work_struct request_module_wk; | ||
492 | |||
493 | /* locks */ | ||
494 | struct mutex lock; | ||
495 | struct mutex ctrl_urb_lock; /* protects urb_buf */ | ||
496 | struct list_head inqueue, outqueue; | ||
497 | wait_queue_head_t open, wait_frame, wait_stream; | ||
498 | struct video_device *vbi_dev; | ||
499 | struct video_device *radio_dev; | ||
500 | |||
501 | unsigned char eedata[256]; | ||
502 | |||
503 | struct cx231xx_video_mode video_mode; | ||
504 | struct cx231xx_video_mode vbi_mode; | ||
505 | struct cx231xx_video_mode sliced_cc_mode; | ||
506 | struct cx231xx_video_mode ts1_mode; | ||
507 | |||
508 | struct usb_device *udev; /* the usb device */ | ||
509 | char urb_buf[URB_MAX_CTRL_SIZE];/* urb control msg buffer */ | ||
510 | |||
511 | |||
512 | /* helper funcs that call usb_control_msg */ | ||
513 | int (*cx231xx_read_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg, | ||
514 | char *buf, int len); | ||
515 | int (*cx231xx_write_ctrl_reg)(struct cx231xx *dev, u8 req, u16 reg, | ||
516 | char *buf, int len); | ||
517 | int (*cx231xx_send_usb_command)(struct cx231xx_i2c *i2c_bus, | ||
518 | struct cx231xx_i2c_xfer_data *req_data); | ||
519 | int (*cx231xx_gpio_i2c_read)(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); | ||
520 | int (*cx231xx_gpio_i2c_write)(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); | ||
521 | |||
522 | int (*cx231xx_set_analog_freq)(struct cx231xx *dev, u32 freq ) ; | ||
523 | int (*cx231xx_reset_analog_tuner)(struct cx231xx *dev) ; | ||
524 | |||
525 | enum cx231xx_mode mode; | ||
526 | |||
527 | struct cx231xx_dvb *dvb; | ||
528 | |||
529 | /* Cx231xx supported PCB config's */ | ||
530 | struct pcb_config current_pcb_config; | ||
531 | u8 current_scenario_idx; | ||
532 | u8 interface_count; | ||
533 | u8 max_iad_interface_count; | ||
534 | |||
535 | /* GPIO related register direction and values */ | ||
536 | u32 gpio_dir; | ||
537 | u32 gpio_val; | ||
538 | |||
539 | /* Power Modes */ | ||
540 | int power_mode; | ||
541 | |||
542 | /* colibri parameters */ | ||
543 | enum AFE_MODE colibri_mode; | ||
544 | u32 colibri_ref_count; | ||
545 | |||
546 | /* video related parameters */ | ||
547 | u32 video_input; | ||
548 | u32 active_mode; | ||
549 | u8 vbi_or_sliced_cc_mode; /* 0 - vbi ; 1 - sliced cc mode */ | ||
550 | enum cx231xx_std_mode std_mode; /* 0 - Air; 1 - cable */ | ||
551 | |||
552 | }; | ||
553 | |||
554 | struct cx231xx_ops { | ||
555 | struct list_head next; | ||
556 | char *name; | ||
557 | int id; | ||
558 | int (*init)(struct cx231xx *); | ||
559 | int (*fini)(struct cx231xx *); | ||
560 | }; | ||
561 | |||
562 | /* call back functions in dvb module */ | ||
563 | int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq ) ; | ||
564 | int cx231xx_reset_analog_tuner(struct cx231xx *dev) ; | ||
565 | |||
566 | /* Provided by cx231xx-i2c.c */ | ||
567 | void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, void *arg); | ||
568 | void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c); | ||
569 | int cx231xx_i2c_register(struct cx231xx_i2c *bus); | ||
570 | int cx231xx_i2c_unregister(struct cx231xx_i2c *bus); | ||
571 | |||
572 | /* Internal block control functions */ | ||
573 | int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, | ||
574 | u16 saddr, u8 saddr_len, u32 *data, u8 data_len); | ||
575 | int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, | ||
576 | u16 saddr, u8 saddr_len, u32 data, u8 data_len); | ||
577 | int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, u16 register_address, | ||
578 | u8 bit_start,u8 bit_end, u32 value); | ||
579 | int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, | ||
580 | u16 saddr, u32 mask, u32 value); | ||
581 | u32 cx231xx_set_field(u32 field_mask, u32 data); | ||
582 | |||
583 | /* Colibri related functions */ | ||
584 | int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count); | ||
585 | int cx231xx_colibri_init_channels(struct cx231xx *dev); | ||
586 | int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev); | ||
587 | int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux); | ||
588 | int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode); | ||
589 | int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode); | ||
590 | int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input); | ||
591 | |||
592 | /* flatiron related functions */ | ||
593 | int cx231xx_flatiron_initialize(struct cx231xx *dev); | ||
594 | int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode); | ||
595 | int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input); | ||
596 | |||
597 | /* DIF related functions */ | ||
598 | int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, | ||
599 | u32 function_mode, u32 standard); | ||
600 | int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard); | ||
601 | int cx231xx_tuner_pre_channel_change(struct cx231xx *dev); | ||
602 | int cx231xx_tuner_post_channel_change(struct cx231xx *dev); | ||
603 | |||
604 | /* video parser functions */ | ||
605 | u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used); | ||
606 | u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, u32 *p_bytes_used); | ||
607 | int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
608 | u8 *p_buffer, u32 bytes_to_copy); | ||
609 | void cx231xx_reset_video_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); | ||
610 | u8 cx231xx_is_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q); | ||
611 | u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
612 | u8 *p_line, u32 length, int field_number); | ||
613 | u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, | ||
614 | u8 sav_eav, u8 *p_buffer, u32 buffer_size); | ||
615 | void cx231xx_swab(u16 *from, u16 *to, u16 len); | ||
616 | |||
617 | /* Provided by cx231xx-core.c */ | ||
618 | |||
619 | u32 cx231xx_request_buffers(struct cx231xx *dev, u32 count); | ||
620 | void cx231xx_queue_unusedframes(struct cx231xx *dev); | ||
621 | void cx231xx_release_buffers(struct cx231xx *dev); | ||
622 | |||
623 | /* read from control pipe */ | ||
624 | int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, | ||
625 | char *buf, int len); | ||
626 | |||
627 | /* write to control pipe */ | ||
628 | int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, | ||
629 | char *buf, int len); | ||
630 | int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode); | ||
631 | |||
632 | int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req); | ||
633 | int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, | ||
634 | struct cx231xx_i2c_xfer_data *req_data); | ||
635 | |||
636 | /* Gpio related functions */ | ||
637 | int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val, | ||
638 | u8 len, u8 request, u8 direction); | ||
639 | int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val); | ||
640 | int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val); | ||
641 | int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value); | ||
642 | int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number, int pin_value); | ||
643 | |||
644 | int cx231xx_gpio_i2c_start(struct cx231xx *dev); | ||
645 | int cx231xx_gpio_i2c_end(struct cx231xx *dev); | ||
646 | int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data); | ||
647 | int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf); | ||
648 | int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev); | ||
649 | int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev); | ||
650 | int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev); | ||
651 | |||
652 | int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); | ||
653 | int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); | ||
654 | |||
655 | /* audio related functions */ | ||
656 | int cx231xx_set_audio_decoder_input(struct cx231xx *dev, enum AUDIO_INPUT audio_input); | ||
657 | |||
658 | int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type); | ||
659 | int cx231xx_resolution_set(struct cx231xx *dev); | ||
660 | int cx231xx_set_video_alternate(struct cx231xx *dev); | ||
661 | int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt); | ||
662 | int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, | ||
663 | int num_bufs, int max_pkt_size, | ||
664 | int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)); | ||
665 | void cx231xx_uninit_isoc(struct cx231xx *dev); | ||
666 | int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode); | ||
667 | int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio); | ||
668 | |||
669 | /* Device list functions */ | ||
670 | void cx231xx_release_resources(struct cx231xx *dev); | ||
671 | void cx231xx_release_analog_resources(struct cx231xx *dev); | ||
672 | int cx231xx_register_analog_devices(struct cx231xx *dev); | ||
673 | void cx231xx_remove_from_devlist(struct cx231xx *dev); | ||
674 | void cx231xx_add_into_devlist(struct cx231xx *dev); | ||
675 | struct cx231xx *cx231xx_get_device(int minor, | ||
676 | enum v4l2_buf_type *fh_type, int *has_radio); | ||
677 | void cx231xx_init_extension(struct cx231xx *dev); | ||
678 | void cx231xx_close_extension(struct cx231xx *dev); | ||
679 | |||
680 | /* hardware init functions */ | ||
681 | int cx231xx_dev_init(struct cx231xx *dev); | ||
682 | void cx231xx_dev_uninit(struct cx231xx *dev); | ||
683 | void cx231xx_config_i2c(struct cx231xx *dev); | ||
684 | int cx231xx_config(struct cx231xx *dev); | ||
685 | |||
686 | /* Stream control functions */ | ||
687 | int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask); | ||
688 | int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask); | ||
689 | |||
690 | int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type); | ||
691 | |||
692 | /* Power control functions */ | ||
693 | int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode); | ||
694 | int cx231xx_power_suspend(struct cx231xx *dev); | ||
695 | |||
696 | /* chip specific control functions */ | ||
697 | int cx231xx_init_ctrl_pin_status(struct cx231xx *dev); | ||
698 | int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, u8 analog_or_digital); | ||
699 | int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex); | ||
700 | |||
701 | /* video audio decoder related functions */ | ||
702 | void video_mux(struct cx231xx *dev, int index); | ||
703 | int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input); | ||
704 | int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input); | ||
705 | int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev); | ||
706 | int cx231xx_set_audio_input(struct cx231xx *dev, u8 input); | ||
707 | void get_scale(struct cx231xx *dev, | ||
708 | unsigned int width, unsigned int height, | ||
709 | unsigned int *hscale, unsigned int *vscale); | ||
710 | |||
711 | /* Provided by cx231xx-video.c */ | ||
712 | int cx231xx_register_extension(struct cx231xx_ops *dev); | ||
713 | void cx231xx_unregister_extension(struct cx231xx_ops *dev); | ||
714 | void cx231xx_init_extension(struct cx231xx *dev); | ||
715 | void cx231xx_close_extension(struct cx231xx *dev); | ||
716 | |||
717 | /* Provided by cx231xx-cards.c */ | ||
718 | extern void cx231xx_pre_card_setup(struct cx231xx *dev); | ||
719 | extern void cx231xx_card_setup(struct cx231xx *dev); | ||
720 | extern struct cx231xx_board cx231xx_boards[]; | ||
721 | extern struct usb_device_id cx231xx_id_table[]; | ||
722 | extern const unsigned int cx231xx_bcount; | ||
723 | void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir); | ||
724 | int cx231xx_tuner_callback(void *ptr, int component, int command, int arg); | ||
725 | |||
726 | /* Provided by cx231xx-input.c */ | ||
727 | int cx231xx_ir_init(struct cx231xx *dev); | ||
728 | int cx231xx_ir_fini(struct cx231xx *dev); | ||
729 | |||
730 | /* printk macros */ | ||
731 | |||
732 | #define cx231xx_err(fmt, arg...) do {\ | ||
733 | printk(KERN_ERR fmt , ##arg); } while (0) | ||
734 | |||
735 | #define cx231xx_errdev(fmt, arg...) do {\ | ||
736 | printk(KERN_ERR "%s: "fmt,\ | ||
737 | dev->name , ##arg); } while (0) | ||
738 | |||
739 | #define cx231xx_info(fmt, arg...) do {\ | ||
740 | printk(KERN_INFO "%s: "fmt,\ | ||
741 | dev->name , ##arg); } while (0) | ||
742 | #define cx231xx_warn(fmt, arg...) do {\ | ||
743 | printk(KERN_WARNING "%s: "fmt,\ | ||
744 | dev->name , ##arg); } while (0) | ||
745 | |||
746 | |||
747 | static inline unsigned int norm_maxw(struct cx231xx *dev) | ||
748 | { | ||
749 | if (dev->board.max_range_640_480) | ||
750 | return 640; | ||
751 | else | ||
752 | return 720; | ||
753 | } | ||
754 | |||
755 | static inline unsigned int norm_maxh(struct cx231xx *dev) | ||
756 | { | ||
757 | if (dev->board.max_range_640_480) | ||
758 | return 480; | ||
759 | else | ||
760 | return (dev->norm & V4L2_STD_625_50) ? 576 : 480; | ||
761 | } | ||
762 | #endif | ||