aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2014-12-02 10:40:32 -0500
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-12-16 20:21:43 -0500
commitea2e813e8cc3492c951b9895724fd47187e04a6f (patch)
tree3b36f7b9b2260016fe78a07db079e208488dc472 /drivers/media/usb
parentc1d9e03d4ef47de60b414fa25f05f9c867f43c5a (diff)
[media] tlg2300: move to staging in preparation for removal
This driver hasn't been tested in a long, long time. The company that made this chip has gone bust many years ago and hardware using this chip is next to impossible to find. This driver needs to be converted to newer media frameworks but due to the lack of hardware that's going to be impossible. Since cheap alternatives are easily available, there is little point in keeping this driver alive. In other words, this driver is a prime candidate for removal. If someone is interested in working on this driver to prevent its removal, then please contact the linux-media mailinglist. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Huang Shijie <shijie8@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/Kconfig1
-rw-r--r--drivers/media/usb/Makefile1
-rw-r--r--drivers/media/usb/tlg2300/Kconfig16
-rw-r--r--drivers/media/usb/tlg2300/Makefile9
-rw-r--r--drivers/media/usb/tlg2300/pd-alsa.c337
-rw-r--r--drivers/media/usb/tlg2300/pd-common.h271
-rw-r--r--drivers/media/usb/tlg2300/pd-dvb.c597
-rw-r--r--drivers/media/usb/tlg2300/pd-main.c553
-rw-r--r--drivers/media/usb/tlg2300/pd-radio.c339
-rw-r--r--drivers/media/usb/tlg2300/pd-video.c1570
-rw-r--r--drivers/media/usb/tlg2300/vendorcmds.h243
11 files changed, 0 insertions, 3937 deletions
diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig
index 056181f2f569..7496f332f3f5 100644
--- a/drivers/media/usb/Kconfig
+++ b/drivers/media/usb/Kconfig
@@ -24,7 +24,6 @@ if MEDIA_ANALOG_TV_SUPPORT
24 comment "Analog TV USB devices" 24 comment "Analog TV USB devices"
25source "drivers/media/usb/pvrusb2/Kconfig" 25source "drivers/media/usb/pvrusb2/Kconfig"
26source "drivers/media/usb/hdpvr/Kconfig" 26source "drivers/media/usb/hdpvr/Kconfig"
27source "drivers/media/usb/tlg2300/Kconfig"
28source "drivers/media/usb/usbvision/Kconfig" 27source "drivers/media/usb/usbvision/Kconfig"
29source "drivers/media/usb/stk1160/Kconfig" 28source "drivers/media/usb/stk1160/Kconfig"
30source "drivers/media/usb/go7007/Kconfig" 29source "drivers/media/usb/go7007/Kconfig"
diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile
index 6f2eb7c8416c..8874ba774a34 100644
--- a/drivers/media/usb/Makefile
+++ b/drivers/media/usb/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
16obj-$(CONFIG_VIDEO_AU0828) += au0828/ 16obj-$(CONFIG_VIDEO_AU0828) += au0828/
17obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ 17obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/
18obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ 18obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
19obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
20obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ 19obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
21obj-$(CONFIG_VIDEO_STK1160) += stk1160/ 20obj-$(CONFIG_VIDEO_STK1160) += stk1160/
22obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ 21obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
diff --git a/drivers/media/usb/tlg2300/Kconfig b/drivers/media/usb/tlg2300/Kconfig
deleted file mode 100644
index 645d915267e6..000000000000
--- a/drivers/media/usb/tlg2300/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
1config VIDEO_TLG2300
2 tristate "Telegent TLG2300 USB video capture support"
3 depends on VIDEO_DEV && I2C && SND && DVB_CORE
4 select VIDEO_TUNER
5 select VIDEO_TVEEPROM
6 depends on RC_CORE
7 select VIDEOBUF_VMALLOC
8 select SND_PCM
9 select VIDEOBUF_DVB
10
11 ---help---
12 This is a video4linux driver for Telegent tlg2300 based TV cards.
13 The driver supports V4L2, DVB-T and radio.
14
15 To compile this driver as a module, choose M here: the
16 module will be called poseidon
diff --git a/drivers/media/usb/tlg2300/Makefile b/drivers/media/usb/tlg2300/Makefile
deleted file mode 100644
index 137f8e38cdec..000000000000
--- a/drivers/media/usb/tlg2300/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
1poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o
2
3obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o
4
5ccflags-y += -Idrivers/media/i2c
6ccflags-y += -Idrivers/media/tuners
7ccflags-y += -Idrivers/media/dvb-core
8ccflags-y += -Idrivers/media/dvb-frontends
9
diff --git a/drivers/media/usb/tlg2300/pd-alsa.c b/drivers/media/usb/tlg2300/pd-alsa.c
deleted file mode 100644
index dd8fe100590f..000000000000
--- a/drivers/media/usb/tlg2300/pd-alsa.c
+++ /dev/null
@@ -1,337 +0,0 @@
1#include <linux/kernel.h>
2#include <linux/usb.h>
3#include <linux/init.h>
4#include <linux/sound.h>
5#include <linux/spinlock.h>
6#include <linux/soundcard.h>
7#include <linux/vmalloc.h>
8#include <linux/proc_fs.h>
9#include <linux/module.h>
10#include <linux/gfp.h>
11#include <sound/core.h>
12#include <sound/pcm.h>
13#include <sound/pcm_params.h>
14#include <sound/info.h>
15#include <sound/initval.h>
16#include <sound/control.h>
17#include <media/v4l2-common.h>
18#include "pd-common.h"
19#include "vendorcmds.h"
20
21static void complete_handler_audio(struct urb *urb);
22#define AUDIO_EP (0x83)
23#define AUDIO_BUF_SIZE (512)
24#define PERIOD_SIZE (1024 * 8)
25#define PERIOD_MIN (4)
26#define PERIOD_MAX PERIOD_MIN
27
28static struct snd_pcm_hardware snd_pd_hw_capture = {
29 .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
30 SNDRV_PCM_INFO_MMAP |
31 SNDRV_PCM_INFO_INTERLEAVED |
32 SNDRV_PCM_INFO_MMAP_VALID,
33
34 .formats = SNDRV_PCM_FMTBIT_S16_LE,
35 .rates = SNDRV_PCM_RATE_48000,
36
37 .rate_min = 48000,
38 .rate_max = 48000,
39 .channels_min = 2,
40 .channels_max = 2,
41 .buffer_bytes_max = PERIOD_SIZE * PERIOD_MIN,
42 .period_bytes_min = PERIOD_SIZE,
43 .period_bytes_max = PERIOD_SIZE,
44 .periods_min = PERIOD_MIN,
45 .periods_max = PERIOD_MAX,
46 /*
47 .buffer_bytes_max = 62720 * 8,
48 .period_bytes_min = 64,
49 .period_bytes_max = 12544,
50 .periods_min = 2,
51 .periods_max = 98
52 */
53};
54
55static int snd_pd_capture_open(struct snd_pcm_substream *substream)
56{
57 struct poseidon *p = snd_pcm_substream_chip(substream);
58 struct poseidon_audio *pa = &p->audio;
59 struct snd_pcm_runtime *runtime = substream->runtime;
60
61 if (!p)
62 return -ENODEV;
63 pa->users++;
64 pa->card_close = 0;
65 pa->capture_pcm_substream = substream;
66 runtime->private_data = p;
67
68 runtime->hw = snd_pd_hw_capture;
69 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
70 usb_autopm_get_interface(p->interface);
71 kref_get(&p->kref);
72 return 0;
73}
74
75static int snd_pd_pcm_close(struct snd_pcm_substream *substream)
76{
77 struct poseidon *p = snd_pcm_substream_chip(substream);
78 struct poseidon_audio *pa = &p->audio;
79
80 pa->users--;
81 pa->card_close = 1;
82 usb_autopm_put_interface(p->interface);
83 kref_put(&p->kref, poseidon_delete);
84 return 0;
85}
86
87static int snd_pd_hw_capture_params(struct snd_pcm_substream *substream,
88 struct snd_pcm_hw_params *hw_params)
89{
90 struct snd_pcm_runtime *runtime = substream->runtime;
91 unsigned int size;
92
93 size = params_buffer_bytes(hw_params);
94 if (runtime->dma_area) {
95 if (runtime->dma_bytes > size)
96 return 0;
97 vfree(runtime->dma_area);
98 }
99 runtime->dma_area = vmalloc(size);
100 if (!runtime->dma_area)
101 return -ENOMEM;
102 else
103 runtime->dma_bytes = size;
104 return 0;
105}
106
107static int audio_buf_free(struct poseidon *p)
108{
109 struct poseidon_audio *pa = &p->audio;
110 int i;
111
112 for (i = 0; i < AUDIO_BUFS; i++)
113 if (pa->urb_array[i])
114 usb_kill_urb(pa->urb_array[i]);
115 free_all_urb_generic(pa->urb_array, AUDIO_BUFS);
116 logpm();
117 return 0;
118}
119
120static int snd_pd_hw_capture_free(struct snd_pcm_substream *substream)
121{
122 struct poseidon *p = snd_pcm_substream_chip(substream);
123
124 logpm();
125 audio_buf_free(p);
126 return 0;
127}
128
129static int snd_pd_prepare(struct snd_pcm_substream *substream)
130{
131 return 0;
132}
133
134#define AUDIO_TRAILER_SIZE (16)
135static inline void handle_audio_data(struct urb *urb, int *period_elapsed)
136{
137 struct poseidon_audio *pa = urb->context;
138 struct snd_pcm_runtime *runtime = pa->capture_pcm_substream->runtime;
139
140 int stride = runtime->frame_bits >> 3;
141 int len = urb->actual_length / stride;
142 unsigned char *cp = urb->transfer_buffer;
143 unsigned int oldptr = pa->rcv_position;
144
145 if (urb->actual_length == AUDIO_BUF_SIZE - 4)
146 len -= (AUDIO_TRAILER_SIZE / stride);
147
148 /* do the copy */
149 if (oldptr + len >= runtime->buffer_size) {
150 unsigned int cnt = runtime->buffer_size - oldptr;
151
152 memcpy(runtime->dma_area + oldptr * stride, cp, cnt * stride);
153 memcpy(runtime->dma_area, (cp + cnt * stride),
154 (len * stride - cnt * stride));
155 } else
156 memcpy(runtime->dma_area + oldptr * stride, cp, len * stride);
157
158 /* update the statas */
159 snd_pcm_stream_lock(pa->capture_pcm_substream);
160 pa->rcv_position += len;
161 if (pa->rcv_position >= runtime->buffer_size)
162 pa->rcv_position -= runtime->buffer_size;
163
164 pa->copied_position += (len);
165 if (pa->copied_position >= runtime->period_size) {
166 pa->copied_position -= runtime->period_size;
167 *period_elapsed = 1;
168 }
169 snd_pcm_stream_unlock(pa->capture_pcm_substream);
170}
171
172static void complete_handler_audio(struct urb *urb)
173{
174 struct poseidon_audio *pa = urb->context;
175 struct snd_pcm_substream *substream = pa->capture_pcm_substream;
176 int period_elapsed = 0;
177 int ret;
178
179 if (1 == pa->card_close || pa->capture_stream != STREAM_ON)
180 return;
181
182 if (urb->status != 0) {
183 /*if (urb->status == -ESHUTDOWN)*/
184 return;
185 }
186
187 if (substream) {
188 if (urb->actual_length) {
189 handle_audio_data(urb, &period_elapsed);
190 if (period_elapsed)
191 snd_pcm_period_elapsed(substream);
192 }
193 }
194
195 ret = usb_submit_urb(urb, GFP_ATOMIC);
196 if (ret < 0)
197 log("audio urb failed (errcod = %i)", ret);
198 return;
199}
200
201static int fire_audio_urb(struct poseidon *p)
202{
203 int i, ret = 0;
204 struct poseidon_audio *pa = &p->audio;
205
206 alloc_bulk_urbs_generic(pa->urb_array, AUDIO_BUFS,
207 p->udev, AUDIO_EP,
208 AUDIO_BUF_SIZE, GFP_ATOMIC,
209 complete_handler_audio, pa);
210
211 for (i = 0; i < AUDIO_BUFS; i++) {
212 ret = usb_submit_urb(pa->urb_array[i], GFP_KERNEL);
213 if (ret)
214 log("urb err : %d", ret);
215 }
216 log();
217 return ret;
218}
219
220static int snd_pd_capture_trigger(struct snd_pcm_substream *substream, int cmd)
221{
222 struct poseidon *p = snd_pcm_substream_chip(substream);
223 struct poseidon_audio *pa = &p->audio;
224
225 if (debug_mode)
226 log("cmd %d, audio stat : %d\n", cmd, pa->capture_stream);
227
228 switch (cmd) {
229 case SNDRV_PCM_TRIGGER_RESUME:
230 case SNDRV_PCM_TRIGGER_START:
231 if (pa->capture_stream == STREAM_ON)
232 return 0;
233
234 pa->rcv_position = pa->copied_position = 0;
235 pa->capture_stream = STREAM_ON;
236
237 if (in_hibernation(p))
238 return 0;
239 fire_audio_urb(p);
240 return 0;
241
242 case SNDRV_PCM_TRIGGER_SUSPEND:
243 pa->capture_stream = STREAM_SUSPEND;
244 return 0;
245 case SNDRV_PCM_TRIGGER_STOP:
246 pa->capture_stream = STREAM_OFF;
247 return 0;
248 default:
249 return -EINVAL;
250 }
251}
252
253static snd_pcm_uframes_t
254snd_pd_capture_pointer(struct snd_pcm_substream *substream)
255{
256 struct poseidon *p = snd_pcm_substream_chip(substream);
257 struct poseidon_audio *pa = &p->audio;
258 return pa->rcv_position;
259}
260
261static struct page *snd_pcm_pd_get_page(struct snd_pcm_substream *subs,
262 unsigned long offset)
263{
264 void *pageptr = subs->runtime->dma_area + offset;
265 return vmalloc_to_page(pageptr);
266}
267
268static struct snd_pcm_ops pcm_capture_ops = {
269 .open = snd_pd_capture_open,
270 .close = snd_pd_pcm_close,
271 .ioctl = snd_pcm_lib_ioctl,
272 .hw_params = snd_pd_hw_capture_params,
273 .hw_free = snd_pd_hw_capture_free,
274 .prepare = snd_pd_prepare,
275 .trigger = snd_pd_capture_trigger,
276 .pointer = snd_pd_capture_pointer,
277 .page = snd_pcm_pd_get_page,
278};
279
280#ifdef CONFIG_PM
281int pm_alsa_suspend(struct poseidon *p)
282{
283 logpm(p);
284 audio_buf_free(p);
285 return 0;
286}
287
288int pm_alsa_resume(struct poseidon *p)
289{
290 logpm(p);
291 fire_audio_urb(p);
292 return 0;
293}
294#endif
295
296int poseidon_audio_init(struct poseidon *p)
297{
298 struct poseidon_audio *pa = &p->audio;
299 struct snd_card *card;
300 struct snd_pcm *pcm;
301 int ret;
302
303 ret = snd_card_new(&p->interface->dev, -1, "Telegent",
304 THIS_MODULE, 0, &card);
305 if (ret != 0)
306 return ret;
307
308 ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm);
309 if (ret < 0) {
310 snd_card_free(card);
311 return ret;
312 }
313 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
314 pcm->info_flags = 0;
315 pcm->private_data = p;
316 strcpy(pcm->name, "poseidon audio capture");
317
318 strcpy(card->driver, "ALSA driver");
319 strcpy(card->shortname, "poseidon Audio");
320 strcpy(card->longname, "poseidon ALSA Audio");
321
322 if (snd_card_register(card)) {
323 snd_card_free(card);
324 return -ENOMEM;
325 }
326 pa->card = card;
327 return 0;
328}
329
330int poseidon_audio_free(struct poseidon *p)
331{
332 struct poseidon_audio *pa = &p->audio;
333
334 if (pa->card)
335 snd_card_free(pa->card);
336 return 0;
337}
diff --git a/drivers/media/usb/tlg2300/pd-common.h b/drivers/media/usb/tlg2300/pd-common.h
deleted file mode 100644
index 9e23ad32d2fe..000000000000
--- a/drivers/media/usb/tlg2300/pd-common.h
+++ /dev/null
@@ -1,271 +0,0 @@
1#ifndef PD_COMMON_H
2#define PD_COMMON_H
3
4#include <linux/fs.h>
5#include <linux/wait.h>
6#include <linux/list.h>
7#include <linux/videodev2.h>
8#include <linux/semaphore.h>
9#include <linux/usb.h>
10#include <linux/poll.h>
11#include <media/videobuf-vmalloc.h>
12#include <media/v4l2-device.h>
13#include <media/v4l2-ctrls.h>
14
15#include "dvb_frontend.h"
16#include "dvbdev.h"
17#include "dvb_demux.h"
18#include "dmxdev.h"
19
20#define SBUF_NUM 8
21#define MAX_BUFFER_NUM 6
22#define PK_PER_URB 32
23#define ISO_PKT_SIZE 3072
24
25#define POSEIDON_STATE_NONE (0x0000)
26#define POSEIDON_STATE_ANALOG (0x0001)
27#define POSEIDON_STATE_FM (0x0002)
28#define POSEIDON_STATE_DVBT (0x0004)
29#define POSEIDON_STATE_DISCONNECT (0x0080)
30
31#define PM_SUSPEND_DELAY 3
32
33#define V4L_PAL_VBI_LINES 18
34#define V4L_NTSC_VBI_LINES 12
35#define V4L_PAL_VBI_FRAMESIZE (V4L_PAL_VBI_LINES * 1440 * 2)
36#define V4L_NTSC_VBI_FRAMESIZE (V4L_NTSC_VBI_LINES * 1440 * 2)
37
38#define TUNER_FREQ_MIN (45000000U)
39#define TUNER_FREQ_MAX (862000000U)
40
41struct vbi_data {
42 struct video_device v_dev;
43 struct video_data *video;
44 struct front_face *front;
45
46 unsigned int copied;
47 unsigned int vbi_size; /* the whole size of two fields */
48 int users;
49};
50
51/*
52 * This is the running context of the video, it is useful for
53 * resume()
54 */
55struct running_context {
56 u32 freq; /* VIDIOC_S_FREQUENCY */
57 int audio_idx; /* VIDIOC_S_TUNER */
58 v4l2_std_id tvnormid; /* VIDIOC_S_STD */
59 int sig_index; /* VIDIOC_S_INPUT */
60 struct v4l2_pix_format pix; /* VIDIOC_S_FMT */
61};
62
63struct video_data {
64 /* v4l2 video device */
65 struct video_device v_dev;
66 struct v4l2_ctrl_handler ctrl_handler;
67
68 /* the working context */
69 struct running_context context;
70
71 /* for data copy */
72 int field_count;
73
74 char *dst;
75 int lines_copied;
76 int prev_left;
77
78 int lines_per_field;
79 int lines_size;
80
81 /* for communication */
82 u8 endpoint_addr;
83 struct urb *urb_array[SBUF_NUM];
84 struct vbi_data *vbi;
85 struct poseidon *pd;
86 struct front_face *front;
87
88 int is_streaming;
89 int users;
90
91 /* for bubble handler */
92 struct work_struct bubble_work;
93};
94
95enum pcm_stream_state {
96 STREAM_OFF,
97 STREAM_ON,
98 STREAM_SUSPEND,
99};
100
101#define AUDIO_BUFS (3)
102#define CAPTURE_STREAM_EN 1
103struct poseidon_audio {
104 struct urb *urb_array[AUDIO_BUFS];
105 unsigned int copied_position;
106 struct snd_pcm_substream *capture_pcm_substream;
107
108 unsigned int rcv_position;
109 struct snd_card *card;
110 int card_close;
111
112 int users;
113 int pm_state;
114 enum pcm_stream_state capture_stream;
115};
116
117struct radio_data {
118 __u32 fm_freq;
119 unsigned int is_radio_streaming;
120 int pre_emphasis;
121 struct video_device fm_dev;
122 struct v4l2_ctrl_handler ctrl_handler;
123};
124
125#define DVB_SBUF_NUM 4
126#define DVB_URB_BUF_SIZE 0x2000
127struct pd_dvb_adapter {
128 struct dvb_adapter dvb_adap;
129 struct dvb_frontend dvb_fe;
130 struct dmxdev dmxdev;
131 struct dvb_demux demux;
132
133 atomic_t users;
134 atomic_t active_feed;
135
136 /* data transfer */
137 s32 is_streaming;
138 struct urb *urb_array[DVB_SBUF_NUM];
139 struct poseidon *pd_device;
140 u8 ep_addr;
141 u8 reserved[3];
142
143 /* data for power resume*/
144 struct dtv_frontend_properties fe_param;
145
146 /* for channel scanning */
147 int prev_freq;
148 int bandwidth;
149 unsigned long last_jiffies;
150};
151
152struct front_face {
153 /* use this field to distinguish VIDEO and VBI */
154 enum v4l2_buf_type type;
155
156 /* for host */
157 struct videobuf_queue q;
158
159 /* the bridge for host and device */
160 struct videobuf_buffer *curr_frame;
161
162 /* for device */
163 spinlock_t queue_lock;
164 struct list_head active;
165 struct poseidon *pd;
166};
167
168struct poseidon {
169 struct list_head device_list;
170
171 struct mutex lock;
172 struct kref kref;
173
174 /* for V4L2 */
175 struct v4l2_device v4l2_dev;
176
177 /* hardware info */
178 struct usb_device *udev;
179 struct usb_interface *interface;
180 int cur_transfer_mode;
181
182 struct video_data video_data; /* video */
183 struct vbi_data vbi_data; /* vbi */
184 struct poseidon_audio audio; /* audio (alsa) */
185 struct radio_data radio_data; /* FM */
186 struct pd_dvb_adapter dvb_data; /* DVB */
187
188 u32 state;
189 struct file *file_for_stream; /* the active stream*/
190
191#ifdef CONFIG_PM
192 int (*pm_suspend)(struct poseidon *);
193 int (*pm_resume)(struct poseidon *);
194 pm_message_t msg;
195
196 struct work_struct pm_work;
197 u8 portnum;
198#endif
199};
200
201struct poseidon_format {
202 char *name;
203 int fourcc; /* video4linux 2 */
204 int depth; /* bit/pixel */
205 int flags;
206};
207
208struct poseidon_tvnorm {
209 v4l2_std_id v4l2_id;
210 char name[12];
211 u32 tlg_tvnorm;
212};
213
214/* video */
215int pd_video_init(struct poseidon *);
216void pd_video_exit(struct poseidon *);
217int stop_all_video_stream(struct poseidon *);
218
219/* alsa audio */
220int poseidon_audio_init(struct poseidon *);
221int poseidon_audio_free(struct poseidon *);
222#ifdef CONFIG_PM
223int pm_alsa_suspend(struct poseidon *);
224int pm_alsa_resume(struct poseidon *);
225#endif
226
227/* dvb */
228int pd_dvb_usb_device_init(struct poseidon *);
229void pd_dvb_usb_device_exit(struct poseidon *);
230void pd_dvb_usb_device_cleanup(struct poseidon *);
231int pd_dvb_get_adapter_num(struct pd_dvb_adapter *);
232void dvb_stop_streaming(struct pd_dvb_adapter *);
233
234/* FM */
235int poseidon_fm_init(struct poseidon *);
236int poseidon_fm_exit(struct poseidon *);
237
238/* vendor command ops */
239int send_set_req(struct poseidon*, u8, s32, s32*);
240int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32);
241s32 set_tuner_mode(struct poseidon*, unsigned char);
242
243/* bulk urb alloc/free */
244int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
245 struct usb_device *udev, u8 ep_addr,
246 int buf_size, gfp_t gfp_flags,
247 usb_complete_t complete_fn, void *context);
248void free_all_urb_generic(struct urb **urb_array, int num);
249
250/* misc */
251void poseidon_delete(struct kref *kref);
252extern int debug_mode;
253void set_debug_mode(struct video_device *vfd, int debug_mode);
254
255#ifdef CONFIG_PM
256#define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE)
257#else
258#define in_hibernation(pd) (0)
259#endif
260#define get_pm_count(p) (atomic_read(&(p)->interface->pm_usage_cnt))
261
262#define log(a, ...) printk(KERN_DEBUG "\t[ %s : %.3d ] "a"\n", \
263 __func__, __LINE__, ## __VA_ARGS__)
264
265/* for power management */
266#define logpm(pd) do {\
267 if (debug_mode & 0x10)\
268 log();\
269 } while (0)
270
271#endif
diff --git a/drivers/media/usb/tlg2300/pd-dvb.c b/drivers/media/usb/tlg2300/pd-dvb.c
deleted file mode 100644
index ca4994a5190c..000000000000
--- a/drivers/media/usb/tlg2300/pd-dvb.c
+++ /dev/null
@@ -1,597 +0,0 @@
1#include "pd-common.h"
2#include <linux/kernel.h>
3#include <linux/usb.h>
4#include <linux/time.h>
5#include <linux/dvb/dmx.h>
6#include <linux/delay.h>
7#include <linux/gfp.h>
8
9#include "vendorcmds.h"
10#include <linux/sched.h>
11#include <linux/atomic.h>
12
13static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
14
15static int dvb_bandwidth[][2] = {
16 { TLG_BW_8, 8000000 },
17 { TLG_BW_7, 7000000 },
18 { TLG_BW_6, 6000000 }
19};
20static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth);
21
22static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb);
23static int poseidon_check_mode_dvbt(struct poseidon *pd)
24{
25 s32 ret = 0, cmd_status = 0;
26
27 set_current_state(TASK_INTERRUPTIBLE);
28 schedule_timeout(HZ/4);
29
30 ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE);
31 if (ret != 0)
32 return ret;
33
34 ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T);
35 if (ret)
36 return ret;
37
38 /* signal source */
39 ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status);
40 if (ret|cmd_status)
41 return ret;
42
43 return 0;
44}
45
46/* acquire :
47 * 1 == open
48 * 0 == release
49 */
50static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
51{
52 struct poseidon *pd = fe->demodulator_priv;
53 struct pd_dvb_adapter *pd_dvb;
54 int ret = 0;
55
56 if (!pd)
57 return -ENODEV;
58
59 pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe);
60 if (acquire) {
61 mutex_lock(&pd->lock);
62 if (pd->state & POSEIDON_STATE_DISCONNECT) {
63 ret = -ENODEV;
64 goto open_out;
65 }
66
67 if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) {
68 ret = -EBUSY;
69 goto open_out;
70 }
71
72 usb_autopm_get_interface(pd->interface);
73 if (0 == pd->state) {
74 ret = poseidon_check_mode_dvbt(pd);
75 if (ret < 0) {
76 usb_autopm_put_interface(pd->interface);
77 goto open_out;
78 }
79 pd->state |= POSEIDON_STATE_DVBT;
80 pd_dvb->bandwidth = 0;
81 pd_dvb->prev_freq = 0;
82 }
83 atomic_inc(&pd_dvb->users);
84 kref_get(&pd->kref);
85open_out:
86 mutex_unlock(&pd->lock);
87 } else {
88 dvb_stop_streaming(pd_dvb);
89
90 if (atomic_dec_and_test(&pd_dvb->users)) {
91 mutex_lock(&pd->lock);
92 pd->state &= ~POSEIDON_STATE_DVBT;
93 mutex_unlock(&pd->lock);
94 }
95 kref_put(&pd->kref, poseidon_delete);
96 usb_autopm_put_interface(pd->interface);
97 }
98 return ret;
99}
100
101#ifdef CONFIG_PM
102static void poseidon_fe_release(struct dvb_frontend *fe)
103{
104 struct poseidon *pd = fe->demodulator_priv;
105
106 pd->pm_suspend = NULL;
107 pd->pm_resume = NULL;
108}
109#else
110#define poseidon_fe_release NULL
111#endif
112
113static s32 poseidon_fe_sleep(struct dvb_frontend *fe)
114{
115 return 0;
116}
117
118/*
119 * return true if we can satisfy the conditions, else return false.
120 */
121static bool check_scan_ok(__u32 freq, int bandwidth,
122 struct pd_dvb_adapter *adapter)
123{
124 if (bandwidth < 0)
125 return false;
126
127 if (adapter->prev_freq == freq
128 && adapter->bandwidth == bandwidth) {
129 long nl = jiffies - adapter->last_jiffies;
130 unsigned int msec ;
131
132 msec = jiffies_to_msecs(abs(nl));
133 return msec > 15000 ? true : false;
134 }
135 return true;
136}
137
138/*
139 * Check if the firmware delays too long for an invalid frequency.
140 */
141static int fw_delay_overflow(struct pd_dvb_adapter *adapter)
142{
143 long nl = jiffies - adapter->last_jiffies;
144 unsigned int msec ;
145
146 msec = jiffies_to_msecs(abs(nl));
147 return msec > 800 ? true : false;
148}
149
150static int poseidon_set_fe(struct dvb_frontend *fe)
151{
152 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
153 s32 ret = 0, cmd_status = 0;
154 s32 i, bandwidth = -1;
155 struct poseidon *pd = fe->demodulator_priv;
156 struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
157
158 if (in_hibernation(pd))
159 return -EBUSY;
160
161 mutex_lock(&pd->lock);
162 for (i = 0; i < dvb_bandwidth_length; i++)
163 if (fep->bandwidth_hz == dvb_bandwidth[i][1])
164 bandwidth = dvb_bandwidth[i][0];
165
166 if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) {
167 ret = send_set_req(pd, TUNE_FREQ_SELECT,
168 fep->frequency / 1000, &cmd_status);
169 if (ret | cmd_status) {
170 log("error line");
171 goto front_out;
172 }
173
174 ret = send_set_req(pd, DVBT_BANDW_SEL,
175 bandwidth, &cmd_status);
176 if (ret | cmd_status) {
177 log("error line");
178 goto front_out;
179 }
180
181 ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
182 if (ret | cmd_status) {
183 log("error line");
184 goto front_out;
185 }
186
187 /* save the context for future */
188 memcpy(&pd_dvb->fe_param, fep, sizeof(*fep));
189 pd_dvb->bandwidth = bandwidth;
190 pd_dvb->prev_freq = fep->frequency;
191 pd_dvb->last_jiffies = jiffies;
192 }
193front_out:
194 mutex_unlock(&pd->lock);
195 return ret;
196}
197
198#ifdef CONFIG_PM
199static int pm_dvb_suspend(struct poseidon *pd)
200{
201 struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
202 dvb_stop_streaming(pd_dvb);
203 dvb_urb_cleanup(pd_dvb);
204 msleep(500);
205 return 0;
206}
207
208static int pm_dvb_resume(struct poseidon *pd)
209{
210 struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
211
212 poseidon_check_mode_dvbt(pd);
213 msleep(300);
214 poseidon_set_fe(&pd_dvb->dvb_fe);
215
216 dvb_start_streaming(pd_dvb);
217 return 0;
218}
219#endif
220
221static s32 poseidon_fe_init(struct dvb_frontend *fe)
222{
223 struct poseidon *pd = fe->demodulator_priv;
224 struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
225
226#ifdef CONFIG_PM
227 pd->pm_suspend = pm_dvb_suspend;
228 pd->pm_resume = pm_dvb_resume;
229#endif
230 memset(&pd_dvb->fe_param, 0,
231 sizeof(struct dtv_frontend_properties));
232 return 0;
233}
234
235static int poseidon_get_fe(struct dvb_frontend *fe)
236{
237 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
238 struct poseidon *pd = fe->demodulator_priv;
239 struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
240
241 memcpy(fep, &pd_dvb->fe_param, sizeof(*fep));
242 return 0;
243}
244
245static int poseidon_fe_get_tune_settings(struct dvb_frontend *fe,
246 struct dvb_frontend_tune_settings *tune)
247{
248 tune->min_delay_ms = 1000;
249 return 0;
250}
251
252static int poseidon_read_status(struct dvb_frontend *fe, fe_status_t *stat)
253{
254 struct poseidon *pd = fe->demodulator_priv;
255 s32 ret = -1, cmd_status;
256 struct tuner_dtv_sig_stat_s status = {};
257
258 if (in_hibernation(pd))
259 return -EBUSY;
260 mutex_lock(&pd->lock);
261
262 ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T,
263 &status, &cmd_status, sizeof(status));
264 if (ret | cmd_status) {
265 log("get tuner status error");
266 goto out;
267 }
268
269 if (debug_mode)
270 log("P : %d, L %d, LB :%d", status.sig_present,
271 status.sig_locked, status.sig_lock_busy);
272
273 if (status.sig_lock_busy) {
274 goto out;
275 } else if (status.sig_present || status.sig_locked) {
276 *stat |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER
277 | FE_HAS_SYNC | FE_HAS_VITERBI;
278 } else {
279 if (fw_delay_overflow(&pd->dvb_data))
280 *stat |= FE_TIMEDOUT;
281 }
282out:
283 mutex_unlock(&pd->lock);
284 return ret;
285}
286
287static int poseidon_read_ber(struct dvb_frontend *fe, u32 *ber)
288{
289 struct poseidon *pd = fe->demodulator_priv;
290 struct tuner_ber_rate_s tlg_ber = {};
291 s32 ret = -1, cmd_status;
292
293 mutex_lock(&pd->lock);
294 ret = send_get_req(pd, TUNER_BER_RATE, 0,
295 &tlg_ber, &cmd_status, sizeof(tlg_ber));
296 if (ret | cmd_status)
297 goto out;
298 *ber = tlg_ber.ber_rate;
299out:
300 mutex_unlock(&pd->lock);
301 return ret;
302}
303
304static s32 poseidon_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
305{
306 struct poseidon *pd = fe->demodulator_priv;
307 struct tuner_dtv_sig_stat_s status = {};
308 s32 ret = 0, cmd_status;
309
310 mutex_lock(&pd->lock);
311 ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T,
312 &status, &cmd_status, sizeof(status));
313 if (ret | cmd_status)
314 goto out;
315 if ((status.sig_present || status.sig_locked) && !status.sig_strength)
316 *strength = 0xFFFF;
317 else
318 *strength = status.sig_strength;
319out:
320 mutex_unlock(&pd->lock);
321 return ret;
322}
323
324static int poseidon_read_snr(struct dvb_frontend *fe, u16 *snr)
325{
326 return 0;
327}
328
329static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
330{
331 *unc = 0;
332 return 0;
333}
334
335static struct dvb_frontend_ops poseidon_frontend_ops = {
336 .delsys = { SYS_DVBT },
337 .info = {
338 .name = "Poseidon DVB-T",
339 .frequency_min = 174000000,
340 .frequency_max = 862000000,
341 .frequency_stepsize = 62500,/* FIXME */
342 .caps = FE_CAN_INVERSION_AUTO |
343 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
344 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
345 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
346 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
347 FE_CAN_GUARD_INTERVAL_AUTO |
348 FE_CAN_RECOVER |
349 FE_CAN_HIERARCHY_AUTO,
350 },
351
352 .release = poseidon_fe_release,
353
354 .init = poseidon_fe_init,
355 .sleep = poseidon_fe_sleep,
356
357 .set_frontend = poseidon_set_fe,
358 .get_frontend = poseidon_get_fe,
359 .get_tune_settings = poseidon_fe_get_tune_settings,
360
361 .read_status = poseidon_read_status,
362 .read_ber = poseidon_read_ber,
363 .read_signal_strength = poseidon_read_signal_strength,
364 .read_snr = poseidon_read_snr,
365 .read_ucblocks = poseidon_read_unc_blocks,
366
367 .ts_bus_ctrl = poseidon_ts_bus_ctrl,
368};
369
370static void dvb_urb_irq(struct urb *urb)
371{
372 struct pd_dvb_adapter *pd_dvb = urb->context;
373 int len = urb->transfer_buffer_length;
374 struct dvb_demux *demux = &pd_dvb->demux;
375 s32 ret;
376
377 if (!pd_dvb->is_streaming || urb->status) {
378 if (urb->status == -EPROTO)
379 goto resend;
380 return;
381 }
382
383 if (urb->actual_length == len)
384 dvb_dmx_swfilter(demux, urb->transfer_buffer, len);
385 else if (urb->actual_length == len - 4) {
386 int offset;
387 u8 *buf = urb->transfer_buffer;
388
389 /*
390 * The packet size is 512,
391 * last packet contains 456 bytes tsp data
392 */
393 for (offset = 456; offset < len; offset += 512) {
394 if (!strncmp(buf + offset, "DVHS", 4)) {
395 dvb_dmx_swfilter(demux, buf, offset);
396 if (len > offset + 52 + 4) {
397 /*16 bytes trailer + 36 bytes padding */
398 buf += offset + 52;
399 len -= offset + 52 + 4;
400 dvb_dmx_swfilter(demux, buf, len);
401 }
402 break;
403 }
404 }
405 }
406
407resend:
408 ret = usb_submit_urb(urb, GFP_ATOMIC);
409 if (ret)
410 log(" usb_submit_urb failed: error %d", ret);
411}
412
413static int dvb_urb_init(struct pd_dvb_adapter *pd_dvb)
414{
415 if (pd_dvb->urb_array[0])
416 return 0;
417
418 alloc_bulk_urbs_generic(pd_dvb->urb_array, DVB_SBUF_NUM,
419 pd_dvb->pd_device->udev, pd_dvb->ep_addr,
420 DVB_URB_BUF_SIZE, GFP_KERNEL,
421 dvb_urb_irq, pd_dvb);
422 return 0;
423}
424
425static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb)
426{
427 free_all_urb_generic(pd_dvb->urb_array, DVB_SBUF_NUM);
428}
429
430static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb)
431{
432 struct poseidon *pd = pd_dvb->pd_device;
433 int ret = 0;
434
435 if (pd->state & POSEIDON_STATE_DISCONNECT)
436 return -ENODEV;
437
438 mutex_lock(&pd->lock);
439 if (!pd_dvb->is_streaming) {
440 s32 i, cmd_status = 0;
441 /*
442 * Once upon a time, there was a difficult bug lying here.
443 * ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
444 */
445
446 ret = send_set_req(pd, PLAY_SERVICE, 1, &cmd_status);
447 if (ret | cmd_status)
448 goto out;
449
450 ret = dvb_urb_init(pd_dvb);
451 if (ret < 0)
452 goto out;
453
454 pd_dvb->is_streaming = 1;
455 for (i = 0; i < DVB_SBUF_NUM; i++) {
456 ret = usb_submit_urb(pd_dvb->urb_array[i],
457 GFP_KERNEL);
458 if (ret) {
459 log(" submit urb error %d", ret);
460 goto out;
461 }
462 }
463 }
464out:
465 mutex_unlock(&pd->lock);
466 return ret;
467}
468
469void dvb_stop_streaming(struct pd_dvb_adapter *pd_dvb)
470{
471 struct poseidon *pd = pd_dvb->pd_device;
472
473 mutex_lock(&pd->lock);
474 if (pd_dvb->is_streaming) {
475 s32 i, ret, cmd_status = 0;
476
477 pd_dvb->is_streaming = 0;
478
479 for (i = 0; i < DVB_SBUF_NUM; i++)
480 if (pd_dvb->urb_array[i])
481 usb_kill_urb(pd_dvb->urb_array[i]);
482
483 ret = send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
484 &cmd_status);
485 if (ret | cmd_status)
486 log("error");
487 }
488 mutex_unlock(&pd->lock);
489}
490
491static int pd_start_feed(struct dvb_demux_feed *feed)
492{
493 struct pd_dvb_adapter *pd_dvb = feed->demux->priv;
494 int ret = 0;
495
496 if (!pd_dvb)
497 return -1;
498 if (atomic_inc_return(&pd_dvb->active_feed) == 1)
499 ret = dvb_start_streaming(pd_dvb);
500 return ret;
501}
502
503static int pd_stop_feed(struct dvb_demux_feed *feed)
504{
505 struct pd_dvb_adapter *pd_dvb = feed->demux->priv;
506
507 if (!pd_dvb)
508 return -1;
509 if (atomic_dec_and_test(&pd_dvb->active_feed))
510 dvb_stop_streaming(pd_dvb);
511 return 0;
512}
513
514DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
515int pd_dvb_usb_device_init(struct poseidon *pd)
516{
517 struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
518 struct dvb_demux *dvbdemux;
519 int ret = 0;
520
521 pd_dvb->ep_addr = 0x82;
522 atomic_set(&pd_dvb->users, 0);
523 atomic_set(&pd_dvb->active_feed, 0);
524 pd_dvb->pd_device = pd;
525
526 ret = dvb_register_adapter(&pd_dvb->dvb_adap,
527 "Poseidon dvbt adapter",
528 THIS_MODULE,
529 NULL /* for hibernation correctly*/,
530 adapter_nr);
531 if (ret < 0)
532 goto error1;
533
534 /* register frontend */
535 pd_dvb->dvb_fe.demodulator_priv = pd;
536 memcpy(&pd_dvb->dvb_fe.ops, &poseidon_frontend_ops,
537 sizeof(struct dvb_frontend_ops));
538 ret = dvb_register_frontend(&pd_dvb->dvb_adap, &pd_dvb->dvb_fe);
539 if (ret < 0)
540 goto error2;
541
542 /* register demux device */
543 dvbdemux = &pd_dvb->demux;
544 dvbdemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
545 dvbdemux->priv = pd_dvb;
546 dvbdemux->feednum = dvbdemux->filternum = 64;
547 dvbdemux->start_feed = pd_start_feed;
548 dvbdemux->stop_feed = pd_stop_feed;
549 dvbdemux->write_to_decoder = NULL;
550
551 ret = dvb_dmx_init(dvbdemux);
552 if (ret < 0)
553 goto error3;
554
555 pd_dvb->dmxdev.filternum = pd_dvb->demux.filternum;
556 pd_dvb->dmxdev.demux = &pd_dvb->demux.dmx;
557 pd_dvb->dmxdev.capabilities = 0;
558
559 ret = dvb_dmxdev_init(&pd_dvb->dmxdev, &pd_dvb->dvb_adap);
560 if (ret < 0)
561 goto error3;
562 return 0;
563
564error3:
565 dvb_unregister_frontend(&pd_dvb->dvb_fe);
566error2:
567 dvb_unregister_adapter(&pd_dvb->dvb_adap);
568error1:
569 return ret;
570}
571
572void pd_dvb_usb_device_exit(struct poseidon *pd)
573{
574 struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
575
576 while (atomic_read(&pd_dvb->users) != 0
577 || atomic_read(&pd_dvb->active_feed) != 0) {
578 set_current_state(TASK_INTERRUPTIBLE);
579 schedule_timeout(HZ);
580 }
581 dvb_dmxdev_release(&pd_dvb->dmxdev);
582 dvb_unregister_frontend(&pd_dvb->dvb_fe);
583 dvb_unregister_adapter(&pd_dvb->dvb_adap);
584 pd_dvb_usb_device_cleanup(pd);
585}
586
587void pd_dvb_usb_device_cleanup(struct poseidon *pd)
588{
589 struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
590
591 dvb_urb_cleanup(pd_dvb);
592}
593
594int pd_dvb_get_adapter_num(struct pd_dvb_adapter *pd_dvb)
595{
596 return pd_dvb->dvb_adap.num;
597}
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c
deleted file mode 100644
index b31f4791b8ff..000000000000
--- a/drivers/media/usb/tlg2300/pd-main.c
+++ /dev/null
@@ -1,553 +0,0 @@
1/*
2 * device driver for Telegent tlg2300 based TV cards
3 *
4 * Author :
5 * Kang Yong <kangyong@telegent.com>
6 * Zhang Xiaobing <xbzhang@telegent.com>
7 * Huang Shijie <zyziii@telegent.com> or <shijie8@gmail.com>
8 *
9 * (c) 2009 Telegent Systems
10 * (c) 2010 Telegent Systems
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include <linux/kernel.h>
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/slab.h>
31#include <linux/module.h>
32#include <linux/kref.h>
33#include <linux/suspend.h>
34#include <linux/usb/quirks.h>
35#include <linux/ctype.h>
36#include <linux/string.h>
37#include <linux/types.h>
38#include <linux/firmware.h>
39
40#include "vendorcmds.h"
41#include "pd-common.h"
42
43#define VENDOR_ID 0x1B24
44#define PRODUCT_ID 0x4001
45static struct usb_device_id id_table[] = {
46 { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 0) },
47 { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 1) },
48 { },
49};
50MODULE_DEVICE_TABLE(usb, id_table);
51
52int debug_mode;
53module_param(debug_mode, int, 0644);
54MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose");
55
56#define TLG2300_FIRMWARE "tlg2300_firmware.bin"
57static const char *firmware_name = TLG2300_FIRMWARE;
58static LIST_HEAD(pd_device_list);
59
60/*
61 * send set request to USB firmware.
62 */
63s32 send_set_req(struct poseidon *pd, u8 cmdid, s32 param, s32 *cmd_status)
64{
65 s32 ret;
66 s8 data[32] = {};
67 u16 lower_16, upper_16;
68
69 if (pd->state & POSEIDON_STATE_DISCONNECT)
70 return -ENODEV;
71
72 mdelay(30);
73
74 if (param == 0) {
75 upper_16 = lower_16 = 0;
76 } else {
77 /* send 32 bit param as two 16 bit param,little endian */
78 lower_16 = (unsigned short)(param & 0xffff);
79 upper_16 = (unsigned short)((param >> 16) & 0xffff);
80 }
81 ret = usb_control_msg(pd->udev,
82 usb_rcvctrlpipe(pd->udev, 0),
83 REQ_SET_CMD | cmdid,
84 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
85 lower_16,
86 upper_16,
87 &data,
88 sizeof(*cmd_status),
89 USB_CTRL_GET_TIMEOUT);
90
91 if (!ret) {
92 return -ENXIO;
93 } else {
94 /* 1st 4 bytes into cmd_status */
95 memcpy((char *)cmd_status, &(data[0]), sizeof(*cmd_status));
96 }
97 return 0;
98}
99
100/*
101 * send get request to Poseidon firmware.
102 */
103s32 send_get_req(struct poseidon *pd, u8 cmdid, s32 param,
104 void *buf, s32 *cmd_status, s32 datalen)
105{
106 s32 ret;
107 s8 data[128] = {};
108 u16 lower_16, upper_16;
109
110 if (pd->state & POSEIDON_STATE_DISCONNECT)
111 return -ENODEV;
112
113 mdelay(30);
114 if (param == 0) {
115 upper_16 = lower_16 = 0;
116 } else {
117 /*send 32 bit param as two 16 bit param, little endian */
118 lower_16 = (unsigned short)(param & 0xffff);
119 upper_16 = (unsigned short)((param >> 16) & 0xffff);
120 }
121 ret = usb_control_msg(pd->udev,
122 usb_rcvctrlpipe(pd->udev, 0),
123 REQ_GET_CMD | cmdid,
124 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
125 lower_16,
126 upper_16,
127 &data,
128 (datalen + sizeof(*cmd_status)),
129 USB_CTRL_GET_TIMEOUT);
130
131 if (ret < 0) {
132 return -ENXIO;
133 } else {
134 /* 1st 4 bytes into cmd_status, remaining data into cmd_data */
135 memcpy((char *)cmd_status, &data[0], sizeof(*cmd_status));
136 memcpy((char *)buf, &data[sizeof(*cmd_status)], datalen);
137 }
138 return 0;
139}
140
141static int pm_notifier_block(struct notifier_block *nb,
142 unsigned long event, void *dummy)
143{
144 struct poseidon *pd = NULL;
145 struct list_head *node, *next;
146
147 switch (event) {
148 case PM_POST_HIBERNATION:
149 list_for_each_safe(node, next, &pd_device_list) {
150 struct usb_device *udev;
151 struct usb_interface *iface;
152 int rc = 0;
153
154 pd = container_of(node, struct poseidon, device_list);
155 udev = pd->udev;
156 iface = pd->interface;
157
158 /* It will cause the system to reload the firmware */
159 rc = usb_lock_device_for_reset(udev, iface);
160 if (rc >= 0) {
161 usb_reset_device(udev);
162 usb_unlock_device(udev);
163 }
164 }
165 break;
166 default:
167 break;
168 }
169 log("event :%ld\n", event);
170 return 0;
171}
172
173static struct notifier_block pm_notifer = {
174 .notifier_call = pm_notifier_block,
175};
176
177int set_tuner_mode(struct poseidon *pd, unsigned char mode)
178{
179 s32 ret, cmd_status;
180
181 if (pd->state & POSEIDON_STATE_DISCONNECT)
182 return -ENODEV;
183
184 ret = send_set_req(pd, TUNE_MODE_SELECT, mode, &cmd_status);
185 if (ret || cmd_status)
186 return -ENXIO;
187 return 0;
188}
189
190void poseidon_delete(struct kref *kref)
191{
192 struct poseidon *pd = container_of(kref, struct poseidon, kref);
193
194 if (!pd)
195 return;
196 list_del_init(&pd->device_list);
197
198 pd_dvb_usb_device_cleanup(pd);
199 /* clean_audio_data(&pd->audio_data);*/
200
201 if (pd->udev) {
202 usb_put_dev(pd->udev);
203 pd->udev = NULL;
204 }
205 if (pd->interface) {
206 usb_put_intf(pd->interface);
207 pd->interface = NULL;
208 }
209 kfree(pd);
210 log();
211}
212
213static int firmware_download(struct usb_device *udev)
214{
215 int ret = 0, actual_length;
216 const struct firmware *fw = NULL;
217 void *fwbuf = NULL;
218 size_t fwlength = 0, offset;
219 size_t max_packet_size;
220
221 ret = request_firmware(&fw, firmware_name, &udev->dev);
222 if (ret) {
223 log("download err : %d", ret);
224 return ret;
225 }
226
227 fwlength = fw->size;
228
229 fwbuf = kmemdup(fw->data, fwlength, GFP_KERNEL);
230 if (!fwbuf) {
231 ret = -ENOMEM;
232 goto out;
233 }
234
235 max_packet_size = le16_to_cpu(udev->ep_out[0x1]->desc.wMaxPacketSize);
236 log("\t\t download size : %d", (int)max_packet_size);
237
238 for (offset = 0; offset < fwlength; offset += max_packet_size) {
239 actual_length = 0;
240 ret = usb_bulk_msg(udev,
241 usb_sndbulkpipe(udev, 0x01), /* ep 1 */
242 fwbuf + offset,
243 min(max_packet_size, fwlength - offset),
244 &actual_length,
245 HZ * 10);
246 if (ret)
247 break;
248 }
249 kfree(fwbuf);
250out:
251 release_firmware(fw);
252 return ret;
253}
254
255static inline struct poseidon *get_pd(struct usb_interface *intf)
256{
257 return usb_get_intfdata(intf);
258}
259
260#ifdef CONFIG_PM
261/* one-to-one map : poseidon{} <----> usb_device{}'s port */
262static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
263{
264 pd->portnum = udev->portnum;
265}
266
267static inline int get_autopm_ref(struct poseidon *pd)
268{
269 return pd->video_data.users + pd->vbi_data.users + pd->audio.users
270 + atomic_read(&pd->dvb_data.users) +
271 !list_empty(&pd->radio_data.fm_dev.fh_list);
272}
273
274/* fixup something for poseidon */
275static inline struct poseidon *fixup(struct poseidon *pd)
276{
277 int count;
278
279 /* old udev and interface have gone, so put back reference . */
280 count = get_autopm_ref(pd);
281 log("count : %d, ref count : %d", count, get_pm_count(pd));
282 while (count--)
283 usb_autopm_put_interface(pd->interface);
284 /*usb_autopm_set_interface(pd->interface); */
285
286 usb_put_dev(pd->udev);
287 usb_put_intf(pd->interface);
288 log("event : %d\n", pd->msg.event);
289 return pd;
290}
291
292static struct poseidon *find_old_poseidon(struct usb_device *udev)
293{
294 struct poseidon *pd;
295
296 list_for_each_entry(pd, &pd_device_list, device_list) {
297 if (pd->portnum == udev->portnum && in_hibernation(pd))
298 return fixup(pd);
299 }
300 return NULL;
301}
302
303/* Is the card working now ? */
304static inline int is_working(struct poseidon *pd)
305{
306 return get_pm_count(pd) > 0;
307}
308
309static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg)
310{
311 struct poseidon *pd = get_pd(intf);
312
313 if (!pd)
314 return 0;
315 if (!is_working(pd)) {
316 if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) {
317 pd->msg.event = PM_EVENT_AUTO_SUSPEND;
318 pd->pm_resume = NULL; /* a good guard */
319 printk(KERN_DEBUG "TLG2300 auto suspend\n");
320 }
321 return 0;
322 }
323 pd->msg = msg; /* save it here */
324 logpm(pd);
325 return pd->pm_suspend ? pd->pm_suspend(pd) : 0;
326}
327
328static int poseidon_resume(struct usb_interface *intf)
329{
330 struct poseidon *pd = get_pd(intf);
331
332 if (!pd)
333 return 0;
334 printk(KERN_DEBUG "TLG2300 resume\n");
335
336 if (!is_working(pd)) {
337 if (PM_EVENT_AUTO_SUSPEND == pd->msg.event)
338 pd->msg = PMSG_ON;
339 return 0;
340 }
341 if (in_hibernation(pd)) {
342 logpm(pd);
343 return 0;
344 }
345 logpm(pd);
346 return pd->pm_resume ? pd->pm_resume(pd) : 0;
347}
348
349static void hibernation_resume(struct work_struct *w)
350{
351 struct poseidon *pd = container_of(w, struct poseidon, pm_work);
352 int count;
353
354 pd->msg.event = 0; /* clear it here */
355 pd->state &= ~POSEIDON_STATE_DISCONNECT;
356
357 /* set the new interface's reference */
358 count = get_autopm_ref(pd);
359 while (count--)
360 usb_autopm_get_interface(pd->interface);
361
362 /* resume the context */
363 logpm(pd);
364 if (pd->pm_resume)
365 pd->pm_resume(pd);
366}
367#else /* CONFIG_PM is not enabled: */
368static inline struct poseidon *find_old_poseidon(struct usb_device *udev)
369{
370 return NULL;
371}
372
373static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
374{
375}
376#endif
377
378static int check_firmware(struct usb_device *udev)
379{
380 void *buf;
381 int ret;
382 struct cmd_firmware_vers_s *cmd_firm;
383
384 buf = kzalloc(sizeof(*cmd_firm) + sizeof(u32), GFP_KERNEL);
385 if (!buf)
386 return -ENOMEM;
387 ret = usb_control_msg(udev,
388 usb_rcvctrlpipe(udev, 0),
389 REQ_GET_CMD | GET_FW_ID,
390 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
391 0,
392 0,
393 buf,
394 sizeof(*cmd_firm) + sizeof(u32),
395 USB_CTRL_GET_TIMEOUT);
396 kfree(buf);
397
398 if (ret < 0)
399 return firmware_download(udev);
400 return 0;
401}
402
403static int poseidon_probe(struct usb_interface *interface,
404 const struct usb_device_id *id)
405{
406 struct usb_device *udev = interface_to_usbdev(interface);
407 struct poseidon *pd = NULL;
408 int ret = 0;
409 int new_one = 0;
410
411 /* download firmware */
412 ret = check_firmware(udev);
413 if (ret)
414 return ret;
415
416 /* Do I recovery from the hibernate ? */
417 pd = find_old_poseidon(udev);
418 if (!pd) {
419 pd = kzalloc(sizeof(*pd), GFP_KERNEL);
420 if (!pd)
421 return -ENOMEM;
422 kref_init(&pd->kref);
423 set_map_flags(pd, udev);
424 new_one = 1;
425 }
426
427 pd->udev = usb_get_dev(udev);
428 pd->interface = usb_get_intf(interface);
429 usb_set_intfdata(interface, pd);
430
431 if (new_one) {
432 logpm(pd);
433 mutex_init(&pd->lock);
434
435 /* register v4l2 device */
436 ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev);
437 if (ret)
438 goto err_v4l2;
439
440 /* register devices in directory /dev */
441 ret = pd_video_init(pd);
442 if (ret)
443 goto err_video;
444 ret = poseidon_audio_init(pd);
445 if (ret)
446 goto err_audio;
447 ret = poseidon_fm_init(pd);
448 if (ret)
449 goto err_fm;
450 ret = pd_dvb_usb_device_init(pd);
451 if (ret)
452 goto err_dvb;
453
454 INIT_LIST_HEAD(&pd->device_list);
455 list_add_tail(&pd->device_list, &pd_device_list);
456 }
457
458 device_init_wakeup(&udev->dev, 1);
459#ifdef CONFIG_PM
460 pm_runtime_set_autosuspend_delay(&pd->udev->dev,
461 1000 * PM_SUSPEND_DELAY);
462 usb_enable_autosuspend(pd->udev);
463
464 if (in_hibernation(pd)) {
465 INIT_WORK(&pd->pm_work, hibernation_resume);
466 schedule_work(&pd->pm_work);
467 }
468#endif
469 return 0;
470err_dvb:
471 poseidon_fm_exit(pd);
472err_fm:
473 poseidon_audio_free(pd);
474err_audio:
475 pd_video_exit(pd);
476err_video:
477 v4l2_device_unregister(&pd->v4l2_dev);
478err_v4l2:
479 usb_put_intf(pd->interface);
480 usb_put_dev(pd->udev);
481 kfree(pd);
482 return ret;
483}
484
485static void poseidon_disconnect(struct usb_interface *interface)
486{
487 struct poseidon *pd = get_pd(interface);
488
489 if (!pd)
490 return;
491 logpm(pd);
492 if (in_hibernation(pd))
493 return;
494
495 mutex_lock(&pd->lock);
496 pd->state |= POSEIDON_STATE_DISCONNECT;
497 mutex_unlock(&pd->lock);
498
499 /* stop urb transferring */
500 stop_all_video_stream(pd);
501 dvb_stop_streaming(&pd->dvb_data);
502
503 /*unregister v4l2 device */
504 v4l2_device_unregister(&pd->v4l2_dev);
505
506 pd_dvb_usb_device_exit(pd);
507 poseidon_fm_exit(pd);
508
509 poseidon_audio_free(pd);
510 pd_video_exit(pd);
511
512 usb_set_intfdata(interface, NULL);
513 kref_put(&pd->kref, poseidon_delete);
514}
515
516static struct usb_driver poseidon_driver = {
517 .name = "poseidon",
518 .probe = poseidon_probe,
519 .disconnect = poseidon_disconnect,
520 .id_table = id_table,
521#ifdef CONFIG_PM
522 .suspend = poseidon_suspend,
523 .resume = poseidon_resume,
524#endif
525 .supports_autosuspend = 1,
526};
527
528static int __init poseidon_init(void)
529{
530 int ret;
531
532 ret = usb_register(&poseidon_driver);
533 if (ret)
534 return ret;
535 register_pm_notifier(&pm_notifer);
536 return ret;
537}
538
539static void __exit poseidon_exit(void)
540{
541 log();
542 unregister_pm_notifier(&pm_notifer);
543 usb_deregister(&poseidon_driver);
544}
545
546module_init(poseidon_init);
547module_exit(poseidon_exit);
548
549MODULE_AUTHOR("Telegent Systems");
550MODULE_DESCRIPTION("For tlg2300-based USB device");
551MODULE_LICENSE("GPL");
552MODULE_VERSION("0.0.2");
553MODULE_FIRMWARE(TLG2300_FIRMWARE);
diff --git a/drivers/media/usb/tlg2300/pd-radio.c b/drivers/media/usb/tlg2300/pd-radio.c
deleted file mode 100644
index b391194a840c..000000000000
--- a/drivers/media/usb/tlg2300/pd-radio.c
+++ /dev/null
@@ -1,339 +0,0 @@
1#include <linux/init.h>
2#include <linux/list.h>
3#include <linux/module.h>
4#include <linux/kernel.h>
5#include <linux/bitmap.h>
6#include <linux/usb.h>
7#include <linux/i2c.h>
8#include <media/v4l2-dev.h>
9#include <linux/mm.h>
10#include <linux/mutex.h>
11#include <media/v4l2-ioctl.h>
12#include <media/v4l2-event.h>
13#include <media/v4l2-fh.h>
14#include <linux/sched.h>
15
16#include "pd-common.h"
17#include "vendorcmds.h"
18
19static int set_frequency(struct poseidon *p, __u32 frequency);
20static int poseidon_fm_close(struct file *filp);
21static int poseidon_fm_open(struct file *filp);
22
23#define TUNER_FREQ_MIN_FM 76000000U
24#define TUNER_FREQ_MAX_FM 108000000U
25
26#define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1)
27static int preemphasis[MAX_PREEMPHASIS] = {
28 TLG_TUNE_ASTD_NONE, /* V4L2_PREEMPHASIS_DISABLED */
29 TLG_TUNE_ASTD_FM_EUR, /* V4L2_PREEMPHASIS_50_uS */
30 TLG_TUNE_ASTD_FM_US, /* V4L2_PREEMPHASIS_75_uS */
31};
32
33static int poseidon_check_mode_radio(struct poseidon *p)
34{
35 int ret;
36 u32 status;
37
38 set_current_state(TASK_INTERRUPTIBLE);
39 schedule_timeout(HZ/2);
40 ret = usb_set_interface(p->udev, 0, BULK_ALTERNATE_IFACE);
41 if (ret < 0)
42 goto out;
43
44 ret = set_tuner_mode(p, TLG_MODE_FM_RADIO);
45 if (ret != 0)
46 goto out;
47
48 ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status);
49 ret = send_set_req(p, TUNER_AUD_ANA_STD,
50 p->radio_data.pre_emphasis, &status);
51 ret |= send_set_req(p, TUNER_AUD_MODE,
52 TLG_TUNE_TVAUDIO_MODE_STEREO, &status);
53 ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL,
54 ATV_AUDIO_RATE_48K, &status);
55 ret |= send_set_req(p, TUNE_FREQ_SELECT, TUNER_FREQ_MIN_FM, &status);
56out:
57 return ret;
58}
59
60#ifdef CONFIG_PM
61static int pm_fm_suspend(struct poseidon *p)
62{
63 logpm(p);
64 pm_alsa_suspend(p);
65 usb_set_interface(p->udev, 0, 0);
66 msleep(300);
67 return 0;
68}
69
70static int pm_fm_resume(struct poseidon *p)
71{
72 logpm(p);
73 poseidon_check_mode_radio(p);
74 set_frequency(p, p->radio_data.fm_freq);
75 pm_alsa_resume(p);
76 return 0;
77}
78#endif
79
80static int poseidon_fm_open(struct file *filp)
81{
82 struct poseidon *p = video_drvdata(filp);
83 int ret = 0;
84
85 mutex_lock(&p->lock);
86 if (p->state & POSEIDON_STATE_DISCONNECT) {
87 ret = -ENODEV;
88 goto out;
89 }
90
91 if (p->state && !(p->state & POSEIDON_STATE_FM)) {
92 ret = -EBUSY;
93 goto out;
94 }
95 ret = v4l2_fh_open(filp);
96 if (ret)
97 goto out;
98
99 usb_autopm_get_interface(p->interface);
100 if (0 == p->state) {
101 struct video_device *vfd = &p->radio_data.fm_dev;
102
103 /* default pre-emphasis */
104 if (p->radio_data.pre_emphasis == 0)
105 p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR;
106 set_debug_mode(vfd, debug_mode);
107
108 ret = poseidon_check_mode_radio(p);
109 if (ret < 0) {
110 usb_autopm_put_interface(p->interface);
111 goto out;
112 }
113 p->state |= POSEIDON_STATE_FM;
114 }
115 kref_get(&p->kref);
116out:
117 mutex_unlock(&p->lock);
118 return ret;
119}
120
121static int poseidon_fm_close(struct file *filp)
122{
123 struct poseidon *p = video_drvdata(filp);
124 struct radio_data *fm = &p->radio_data;
125 uint32_t status;
126
127 mutex_lock(&p->lock);
128 if (v4l2_fh_is_singular_file(filp))
129 p->state &= ~POSEIDON_STATE_FM;
130
131 if (fm->is_radio_streaming && filp == p->file_for_stream) {
132 fm->is_radio_streaming = 0;
133 send_set_req(p, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, &status);
134 }
135 usb_autopm_put_interface(p->interface);
136 mutex_unlock(&p->lock);
137
138 kref_put(&p->kref, poseidon_delete);
139 return v4l2_fh_release(filp);
140}
141
142static int vidioc_querycap(struct file *file, void *priv,
143 struct v4l2_capability *v)
144{
145 struct poseidon *p = video_drvdata(file);
146
147 strlcpy(v->driver, "tele-radio", sizeof(v->driver));
148 strlcpy(v->card, "Telegent Poseidon", sizeof(v->card));
149 usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info));
150 v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
151 /* Report all capabilities of the USB device */
152 v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS |
153 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
154 V4L2_CAP_AUDIO | V4L2_CAP_STREAMING |
155 V4L2_CAP_READWRITE;
156 return 0;
157}
158
159static const struct v4l2_file_operations poseidon_fm_fops = {
160 .owner = THIS_MODULE,
161 .open = poseidon_fm_open,
162 .release = poseidon_fm_close,
163 .poll = v4l2_ctrl_poll,
164 .unlocked_ioctl = video_ioctl2,
165};
166
167static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
168 struct v4l2_tuner *vt)
169{
170 struct poseidon *p = video_drvdata(file);
171 struct tuner_fm_sig_stat_s fm_stat = {};
172 int ret, status, count = 5;
173
174 if (vt->index != 0)
175 return -EINVAL;
176
177 vt->type = V4L2_TUNER_RADIO;
178 vt->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
179 vt->rangelow = TUNER_FREQ_MIN_FM * 2 / 125;
180 vt->rangehigh = TUNER_FREQ_MAX_FM * 2 / 125;
181 vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
182 vt->audmode = V4L2_TUNER_MODE_STEREO;
183 vt->signal = 0;
184 vt->afc = 0;
185 strlcpy(vt->name, "Radio", sizeof(vt->name));
186
187 mutex_lock(&p->lock);
188 ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO,
189 &fm_stat, &status, sizeof(fm_stat));
190
191 while (fm_stat.sig_lock_busy && count-- && !ret) {
192 set_current_state(TASK_INTERRUPTIBLE);
193 schedule_timeout(HZ);
194
195 ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO,
196 &fm_stat, &status, sizeof(fm_stat));
197 }
198 mutex_unlock(&p->lock);
199
200 if (ret || status) {
201 vt->signal = 0;
202 } else if ((fm_stat.sig_present || fm_stat.sig_locked)
203 && fm_stat.sig_strength == 0) {
204 vt->signal = 0xffff;
205 } else
206 vt->signal = (fm_stat.sig_strength * 255 / 10) << 8;
207
208 return 0;
209}
210
211static int fm_get_freq(struct file *file, void *priv,
212 struct v4l2_frequency *argp)
213{
214 struct poseidon *p = video_drvdata(file);
215
216 if (argp->tuner)
217 return -EINVAL;
218 argp->frequency = p->radio_data.fm_freq;
219 return 0;
220}
221
222static int set_frequency(struct poseidon *p, __u32 frequency)
223{
224 __u32 freq ;
225 int ret, status;
226
227 mutex_lock(&p->lock);
228
229 ret = send_set_req(p, TUNER_AUD_ANA_STD,
230 p->radio_data.pre_emphasis, &status);
231
232 freq = (frequency * 125) / 2; /* Hz */
233 freq = clamp(freq, TUNER_FREQ_MIN_FM, TUNER_FREQ_MAX_FM);
234
235 ret = send_set_req(p, TUNE_FREQ_SELECT, freq, &status);
236 if (ret < 0)
237 goto error ;
238 ret = send_set_req(p, TAKE_REQUEST, 0, &status);
239
240 set_current_state(TASK_INTERRUPTIBLE);
241 schedule_timeout(HZ/4);
242 if (!p->radio_data.is_radio_streaming) {
243 ret = send_set_req(p, TAKE_REQUEST, 0, &status);
244 ret = send_set_req(p, PLAY_SERVICE,
245 TLG_TUNE_PLAY_SVC_START, &status);
246 p->radio_data.is_radio_streaming = 1;
247 }
248 p->radio_data.fm_freq = freq * 2 / 125;
249error:
250 mutex_unlock(&p->lock);
251 return ret;
252}
253
254static int fm_set_freq(struct file *file, void *priv,
255 const struct v4l2_frequency *argp)
256{
257 struct poseidon *p = video_drvdata(file);
258
259 if (argp->tuner)
260 return -EINVAL;
261 p->file_for_stream = file;
262#ifdef CONFIG_PM
263 p->pm_suspend = pm_fm_suspend;
264 p->pm_resume = pm_fm_resume;
265#endif
266 return set_frequency(p, argp->frequency);
267}
268
269static int tlg_fm_s_ctrl(struct v4l2_ctrl *ctrl)
270{
271 struct poseidon *p = container_of(ctrl->handler, struct poseidon,
272 radio_data.ctrl_handler);
273 int pre_emphasis;
274 u32 status;
275
276 switch (ctrl->id) {
277 case V4L2_CID_TUNE_PREEMPHASIS:
278 pre_emphasis = preemphasis[ctrl->val];
279 send_set_req(p, TUNER_AUD_ANA_STD, pre_emphasis, &status);
280 p->radio_data.pre_emphasis = pre_emphasis;
281 return 0;
282 }
283 return -EINVAL;
284}
285
286static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
287{
288 return vt->index > 0 ? -EINVAL : 0;
289}
290
291static const struct v4l2_ctrl_ops tlg_fm_ctrl_ops = {
292 .s_ctrl = tlg_fm_s_ctrl,
293};
294
295static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
296 .vidioc_querycap = vidioc_querycap,
297 .vidioc_s_tuner = vidioc_s_tuner,
298 .vidioc_g_tuner = tlg_fm_vidioc_g_tuner,
299 .vidioc_g_frequency = fm_get_freq,
300 .vidioc_s_frequency = fm_set_freq,
301 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
302 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
303};
304
305static struct video_device poseidon_fm_template = {
306 .name = "Telegent-Radio",
307 .fops = &poseidon_fm_fops,
308 .minor = -1,
309 .release = video_device_release_empty,
310 .ioctl_ops = &poseidon_fm_ioctl_ops,
311};
312
313int poseidon_fm_init(struct poseidon *p)
314{
315 struct video_device *vfd = &p->radio_data.fm_dev;
316 struct v4l2_ctrl_handler *hdl = &p->radio_data.ctrl_handler;
317
318 *vfd = poseidon_fm_template;
319
320 set_frequency(p, TUNER_FREQ_MIN_FM);
321 v4l2_ctrl_handler_init(hdl, 1);
322 v4l2_ctrl_new_std_menu(hdl, &tlg_fm_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS,
323 V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
324 if (hdl->error) {
325 v4l2_ctrl_handler_free(hdl);
326 return hdl->error;
327 }
328 vfd->v4l2_dev = &p->v4l2_dev;
329 vfd->ctrl_handler = hdl;
330 video_set_drvdata(vfd, p);
331 return video_register_device(vfd, VFL_TYPE_RADIO, -1);
332}
333
334int poseidon_fm_exit(struct poseidon *p)
335{
336 video_unregister_device(&p->radio_data.fm_dev);
337 v4l2_ctrl_handler_free(&p->radio_data.ctrl_handler);
338 return 0;
339}
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c
deleted file mode 100644
index 8cd7f02fcf9f..000000000000
--- a/drivers/media/usb/tlg2300/pd-video.c
+++ /dev/null
@@ -1,1570 +0,0 @@
1#include <linux/fs.h>
2#include <linux/vmalloc.h>
3#include <linux/videodev2.h>
4#include <linux/usb.h>
5#include <linux/mm.h>
6#include <linux/sched.h>
7#include <linux/slab.h>
8
9#include <media/v4l2-ioctl.h>
10#include <media/v4l2-dev.h>
11#include <media/v4l2-ctrls.h>
12
13#include "pd-common.h"
14#include "vendorcmds.h"
15
16#ifdef CONFIG_PM
17static int pm_video_suspend(struct poseidon *pd);
18static int pm_video_resume(struct poseidon *pd);
19#endif
20static void iso_bubble_handler(struct work_struct *w);
21
22static int usb_transfer_mode;
23module_param(usb_transfer_mode, int, 0644);
24MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous");
25
26static const struct poseidon_format poseidon_formats[] = {
27 { "YUV 422", V4L2_PIX_FMT_YUYV, 16, 0},
28 { "RGB565", V4L2_PIX_FMT_RGB565, 16, 0},
29};
30
31static const struct poseidon_tvnorm poseidon_tvnorms[] = {
32 { V4L2_STD_PAL_D, "PAL-D", TLG_TUNE_VSTD_PAL_D },
33 { V4L2_STD_PAL_B, "PAL-B", TLG_TUNE_VSTD_PAL_B },
34 { V4L2_STD_PAL_G, "PAL-G", TLG_TUNE_VSTD_PAL_G },
35 { V4L2_STD_PAL_H, "PAL-H", TLG_TUNE_VSTD_PAL_H },
36 { V4L2_STD_PAL_I, "PAL-I", TLG_TUNE_VSTD_PAL_I },
37 { V4L2_STD_PAL_M, "PAL-M", TLG_TUNE_VSTD_PAL_M },
38 { V4L2_STD_PAL_N, "PAL-N", TLG_TUNE_VSTD_PAL_N_COMBO },
39 { V4L2_STD_PAL_Nc, "PAL-Nc", TLG_TUNE_VSTD_PAL_N_COMBO },
40 { V4L2_STD_NTSC_M, "NTSC-M", TLG_TUNE_VSTD_NTSC_M },
41 { V4L2_STD_NTSC_M_JP, "NTSC-JP", TLG_TUNE_VSTD_NTSC_M_J },
42 { V4L2_STD_SECAM_B, "SECAM-B", TLG_TUNE_VSTD_SECAM_B },
43 { V4L2_STD_SECAM_D, "SECAM-D", TLG_TUNE_VSTD_SECAM_D },
44 { V4L2_STD_SECAM_G, "SECAM-G", TLG_TUNE_VSTD_SECAM_G },
45 { V4L2_STD_SECAM_H, "SECAM-H", TLG_TUNE_VSTD_SECAM_H },
46 { V4L2_STD_SECAM_K, "SECAM-K", TLG_TUNE_VSTD_SECAM_K },
47 { V4L2_STD_SECAM_K1, "SECAM-K1", TLG_TUNE_VSTD_SECAM_K1 },
48 { V4L2_STD_SECAM_L, "SECAM-L", TLG_TUNE_VSTD_SECAM_L },
49 { V4L2_STD_SECAM_LC, "SECAM-LC", TLG_TUNE_VSTD_SECAM_L1 },
50};
51static const unsigned int POSEIDON_TVNORMS = ARRAY_SIZE(poseidon_tvnorms);
52
53struct pd_audio_mode {
54 u32 tlg_audio_mode;
55 u32 v4l2_audio_sub;
56 u32 v4l2_audio_mode;
57};
58
59static const struct pd_audio_mode pd_audio_modes[] = {
60 { TLG_TUNE_TVAUDIO_MODE_MONO, V4L2_TUNER_SUB_MONO,
61 V4L2_TUNER_MODE_MONO },
62 { TLG_TUNE_TVAUDIO_MODE_STEREO, V4L2_TUNER_SUB_STEREO,
63 V4L2_TUNER_MODE_STEREO },
64 { TLG_TUNE_TVAUDIO_MODE_LANG_A, V4L2_TUNER_SUB_LANG1,
65 V4L2_TUNER_MODE_LANG1 },
66 { TLG_TUNE_TVAUDIO_MODE_LANG_B, V4L2_TUNER_SUB_LANG2,
67 V4L2_TUNER_MODE_LANG2 },
68 { TLG_TUNE_TVAUDIO_MODE_LANG_C, V4L2_TUNER_SUB_LANG1,
69 V4L2_TUNER_MODE_LANG1_LANG2 }
70};
71static const unsigned int POSEIDON_AUDIOMODS = ARRAY_SIZE(pd_audio_modes);
72
73struct pd_input {
74 char *name;
75 uint32_t tlg_src;
76};
77
78static const struct pd_input pd_inputs[] = {
79 { "TV Antenna", TLG_SIG_SRC_ANTENNA },
80 { "TV Cable", TLG_SIG_SRC_CABLE },
81 { "TV SVideo", TLG_SIG_SRC_SVIDEO },
82 { "TV Composite", TLG_SIG_SRC_COMPOSITE }
83};
84static const unsigned int POSEIDON_INPUTS = ARRAY_SIZE(pd_inputs);
85
86struct video_std_to_audio_std {
87 v4l2_std_id video_std;
88 int audio_std;
89};
90
91static const struct video_std_to_audio_std video_to_audio_map[] = {
92 /* country : { 27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64,
93 65, 86, 351, 352, 353, 354, 358, 372, 852, 972 } */
94 { (V4L2_STD_PAL_I | V4L2_STD_PAL_B | V4L2_STD_PAL_D |
95 V4L2_STD_SECAM_L | V4L2_STD_SECAM_D), TLG_TUNE_ASTD_NICAM },
96
97 /* country : { 1, 52, 54, 55, 886 } */
98 {V4L2_STD_NTSC_M | V4L2_STD_PAL_N | V4L2_STD_PAL_M, TLG_TUNE_ASTD_BTSC},
99
100 /* country : { 81 } */
101 { V4L2_STD_NTSC_M_JP, TLG_TUNE_ASTD_EIAJ },
102
103 /* other country : TLG_TUNE_ASTD_A2 */
104};
105static const unsigned int map_size = ARRAY_SIZE(video_to_audio_map);
106
107static int get_audio_std(v4l2_std_id v4l2_std)
108{
109 int i = 0;
110
111 for (; i < map_size; i++) {
112 if (v4l2_std & video_to_audio_map[i].video_std)
113 return video_to_audio_map[i].audio_std;
114 }
115 return TLG_TUNE_ASTD_A2;
116}
117
118static int vidioc_querycap(struct file *file, void *fh,
119 struct v4l2_capability *cap)
120{
121 struct video_device *vdev = video_devdata(file);
122 struct poseidon *p = video_get_drvdata(vdev);
123
124 strcpy(cap->driver, "tele-video");
125 strcpy(cap->card, "Telegent Poseidon");
126 usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info));
127 cap->device_caps = V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
128 V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
129 if (vdev->vfl_type == VFL_TYPE_VBI)
130 cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
131 else
132 cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
133 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
134 V4L2_CAP_RADIO | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE;
135 return 0;
136}
137
138/*====================================================================*/
139static void init_copy(struct video_data *video, bool index)
140{
141 struct front_face *front = video->front;
142
143 video->field_count = index;
144 video->lines_copied = 0;
145 video->prev_left = 0 ;
146 video->dst = (char *)videobuf_to_vmalloc(front->curr_frame)
147 + index * video->lines_size;
148 video->vbi->copied = 0; /* set it here */
149}
150
151static bool get_frame(struct front_face *front, int *need_init)
152{
153 struct videobuf_buffer *vb = front->curr_frame;
154
155 if (vb)
156 return true;
157
158 spin_lock(&front->queue_lock);
159 if (!list_empty(&front->active)) {
160 vb = list_entry(front->active.next,
161 struct videobuf_buffer, queue);
162 if (need_init)
163 *need_init = 1;
164 front->curr_frame = vb;
165 list_del_init(&vb->queue);
166 }
167 spin_unlock(&front->queue_lock);
168
169 return !!vb;
170}
171
172/* check if the video's buffer is ready */
173static bool get_video_frame(struct front_face *front, struct video_data *video)
174{
175 int need_init = 0;
176 bool ret = true;
177
178 ret = get_frame(front, &need_init);
179 if (ret && need_init)
180 init_copy(video, 0);
181 return ret;
182}
183
184static void submit_frame(struct front_face *front)
185{
186 struct videobuf_buffer *vb = front->curr_frame;
187
188 if (vb == NULL)
189 return;
190
191 front->curr_frame = NULL;
192 vb->state = VIDEOBUF_DONE;
193 vb->field_count++;
194 v4l2_get_timestamp(&vb->ts);
195
196 wake_up(&vb->done);
197}
198
199/*
200 * A frame is composed of two fields. If we receive all the two fields,
201 * call the submit_frame() to submit the whole frame to applications.
202 */
203static void end_field(struct video_data *video)
204{
205 if (1 == video->field_count)
206 submit_frame(video->front);
207 else
208 init_copy(video, 1);
209}
210
211static void copy_video_data(struct video_data *video, char *src,
212 unsigned int count)
213{
214#define copy_data(len) \
215 do { \
216 if (++video->lines_copied > video->lines_per_field) \
217 goto overflow; \
218 memcpy(video->dst, src, len);\
219 video->dst += len + video->lines_size; \
220 src += len; \
221 count -= len; \
222 } while (0)
223
224 while (count && count >= video->lines_size) {
225 if (video->prev_left) {
226 copy_data(video->prev_left);
227 video->prev_left = 0;
228 continue;
229 }
230 copy_data(video->lines_size);
231 }
232 if (count && count < video->lines_size) {
233 memcpy(video->dst, src, count);
234
235 video->prev_left = video->lines_size - count;
236 video->dst += count;
237 }
238 return;
239
240overflow:
241 end_field(video);
242}
243
244static void check_trailer(struct video_data *video, char *src, int count)
245{
246 struct vbi_data *vbi = video->vbi;
247 int offset; /* trailer's offset */
248 char *buf;
249
250 offset = (video->context.pix.sizeimage / 2 + vbi->vbi_size / 2)
251 - (vbi->copied + video->lines_size * video->lines_copied);
252 if (video->prev_left)
253 offset -= (video->lines_size - video->prev_left);
254
255 if (offset > count || offset <= 0)
256 goto short_package;
257
258 buf = src + offset;
259
260 /* trailer : (VFHS) + U32 + U32 + field_num */
261 if (!strncmp(buf, "VFHS", 4)) {
262 int field_num = *((u32 *)(buf + 12));
263
264 if ((field_num & 1) ^ video->field_count) {
265 init_copy(video, video->field_count);
266 return;
267 }
268 copy_video_data(video, src, offset);
269 }
270short_package:
271 end_field(video);
272}
273
274/* ========== Check this more carefully! =========== */
275static inline void copy_vbi_data(struct vbi_data *vbi,
276 char *src, unsigned int count)
277{
278 struct front_face *front = vbi->front;
279
280 if (front && get_frame(front, NULL)) {
281 char *buf = videobuf_to_vmalloc(front->curr_frame);
282
283 if (vbi->video->field_count)
284 buf += (vbi->vbi_size / 2);
285 memcpy(buf + vbi->copied, src, count);
286 }
287 vbi->copied += count;
288}
289
290/*
291 * Copy the normal data (VBI or VIDEO) without the trailer.
292 * VBI is not interlaced, while VIDEO is interlaced.
293 */
294static inline void copy_vbi_video_data(struct video_data *video,
295 char *src, unsigned int count)
296{
297 struct vbi_data *vbi = video->vbi;
298 unsigned int vbi_delta = (vbi->vbi_size / 2) - vbi->copied;
299
300 if (vbi_delta >= count) {
301 copy_vbi_data(vbi, src, count);
302 } else {
303 if (vbi_delta) {
304 copy_vbi_data(vbi, src, vbi_delta);
305
306 /* we receive the two fields of the VBI*/
307 if (vbi->front && video->field_count)
308 submit_frame(vbi->front);
309 }
310 copy_video_data(video, src + vbi_delta, count - vbi_delta);
311 }
312}
313
314static void urb_complete_bulk(struct urb *urb)
315{
316 struct front_face *front = urb->context;
317 struct video_data *video = &front->pd->video_data;
318 char *src = (char *)urb->transfer_buffer;
319 int count = urb->actual_length;
320 int ret = 0;
321
322 if (!video->is_streaming || urb->status) {
323 if (urb->status == -EPROTO)
324 goto resend_it;
325 return;
326 }
327 if (!get_video_frame(front, video))
328 goto resend_it;
329
330 if (count == urb->transfer_buffer_length)
331 copy_vbi_video_data(video, src, count);
332 else
333 check_trailer(video, src, count);
334
335resend_it:
336 ret = usb_submit_urb(urb, GFP_ATOMIC);
337 if (ret)
338 log(" submit failed: error %d", ret);
339}
340
341/************************* for ISO *********************/
342#define GET_SUCCESS (0)
343#define GET_TRAILER (1)
344#define GET_TOO_MUCH_BUBBLE (2)
345#define GET_NONE (3)
346static int get_chunk(int start, struct urb *urb,
347 int *head, int *tail, int *bubble_err)
348{
349 struct usb_iso_packet_descriptor *pkt = NULL;
350 int ret = GET_SUCCESS;
351
352 for (*head = *tail = -1; start < urb->number_of_packets; start++) {
353 pkt = &urb->iso_frame_desc[start];
354
355 /* handle the bubble of the Hub */
356 if (-EOVERFLOW == pkt->status) {
357 if (++*bubble_err > urb->number_of_packets / 3)
358 return GET_TOO_MUCH_BUBBLE;
359 continue;
360 }
361
362 /* This is the gap */
363 if (pkt->status || pkt->actual_length <= 0
364 || pkt->actual_length > ISO_PKT_SIZE) {
365 if (*head != -1)
366 break;
367 continue;
368 }
369
370 /* a good isochronous packet */
371 if (pkt->actual_length == ISO_PKT_SIZE) {
372 if (*head == -1)
373 *head = start;
374 *tail = start;
375 continue;
376 }
377
378 /* trailer is here */
379 if (pkt->actual_length < ISO_PKT_SIZE) {
380 if (*head == -1) {
381 *head = start;
382 *tail = start;
383 return GET_TRAILER;
384 }
385 break;
386 }
387 }
388
389 if (*head == -1 && *tail == -1)
390 ret = GET_NONE;
391 return ret;
392}
393
394/*
395 * |__|------|___|-----|_______|
396 * ^ ^
397 * | |
398 * gap gap
399 */
400static void urb_complete_iso(struct urb *urb)
401{
402 struct front_face *front = urb->context;
403 struct video_data *video = &front->pd->video_data;
404 int bubble_err = 0, head = 0, tail = 0;
405 char *src = (char *)urb->transfer_buffer;
406 int ret = 0;
407
408 if (!video->is_streaming)
409 return;
410
411 do {
412 if (!get_video_frame(front, video))
413 goto out;
414
415 switch (get_chunk(head, urb, &head, &tail, &bubble_err)) {
416 case GET_SUCCESS:
417 copy_vbi_video_data(video, src + (head * ISO_PKT_SIZE),
418 (tail - head + 1) * ISO_PKT_SIZE);
419 break;
420 case GET_TRAILER:
421 check_trailer(video, src + (head * ISO_PKT_SIZE),
422 ISO_PKT_SIZE);
423 break;
424 case GET_NONE:
425 goto out;
426 case GET_TOO_MUCH_BUBBLE:
427 log("\t We got too much bubble");
428 schedule_work(&video->bubble_work);
429 return;
430 }
431 } while (head = tail + 1, head < urb->number_of_packets);
432
433out:
434 ret = usb_submit_urb(urb, GFP_ATOMIC);
435 if (ret)
436 log("usb_submit_urb err : %d", ret);
437}
438/*============================= [ end ] =====================*/
439
440static int prepare_iso_urb(struct video_data *video)
441{
442 struct usb_device *udev = video->pd->udev;
443 int i;
444
445 if (video->urb_array[0])
446 return 0;
447
448 for (i = 0; i < SBUF_NUM; i++) {
449 struct urb *urb;
450 void *mem;
451 int j;
452
453 urb = usb_alloc_urb(PK_PER_URB, GFP_KERNEL);
454 if (urb == NULL)
455 goto out;
456
457 video->urb_array[i] = urb;
458 mem = usb_alloc_coherent(udev,
459 ISO_PKT_SIZE * PK_PER_URB,
460 GFP_KERNEL,
461 &urb->transfer_dma);
462
463 urb->complete = urb_complete_iso; /* handler */
464 urb->dev = udev;
465 urb->context = video->front;
466 urb->pipe = usb_rcvisocpipe(udev,
467 video->endpoint_addr);
468 urb->interval = 1;
469 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
470 urb->number_of_packets = PK_PER_URB;
471 urb->transfer_buffer = mem;
472 urb->transfer_buffer_length = PK_PER_URB * ISO_PKT_SIZE;
473
474 for (j = 0; j < PK_PER_URB; j++) {
475 urb->iso_frame_desc[j].offset = ISO_PKT_SIZE * j;
476 urb->iso_frame_desc[j].length = ISO_PKT_SIZE;
477 }
478 }
479 return 0;
480out:
481 for (; i > 0; i--)
482 ;
483 return -ENOMEM;
484}
485
486/* return the succeeded number of the allocation */
487int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
488 struct usb_device *udev, u8 ep_addr,
489 int buf_size, gfp_t gfp_flags,
490 usb_complete_t complete_fn, void *context)
491{
492 int i = 0;
493
494 for (; i < num; i++) {
495 void *mem;
496 struct urb *urb = usb_alloc_urb(0, gfp_flags);
497 if (urb == NULL)
498 return i;
499
500 mem = usb_alloc_coherent(udev, buf_size, gfp_flags,
501 &urb->transfer_dma);
502 if (mem == NULL) {
503 usb_free_urb(urb);
504 return i;
505 }
506
507 usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr),
508 mem, buf_size, complete_fn, context);
509 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
510 urb_array[i] = urb;
511 }
512 return i;
513}
514
515void free_all_urb_generic(struct urb **urb_array, int num)
516{
517 int i;
518 struct urb *urb;
519
520 for (i = 0; i < num; i++) {
521 urb = urb_array[i];
522 if (urb) {
523 usb_free_coherent(urb->dev,
524 urb->transfer_buffer_length,
525 urb->transfer_buffer,
526 urb->transfer_dma);
527 usb_free_urb(urb);
528 urb_array[i] = NULL;
529 }
530 }
531}
532
533static int prepare_bulk_urb(struct video_data *video)
534{
535 if (video->urb_array[0])
536 return 0;
537
538 alloc_bulk_urbs_generic(video->urb_array, SBUF_NUM,
539 video->pd->udev, video->endpoint_addr,
540 0x2000, GFP_KERNEL,
541 urb_complete_bulk, video->front);
542 return 0;
543}
544
545/* free the URBs */
546static void free_all_urb(struct video_data *video)
547{
548 free_all_urb_generic(video->urb_array, SBUF_NUM);
549}
550
551static void pd_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
552{
553 videobuf_vmalloc_free(vb);
554 vb->state = VIDEOBUF_NEEDS_INIT;
555}
556
557static void pd_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
558{
559 struct front_face *front = q->priv_data;
560 vb->state = VIDEOBUF_QUEUED;
561 list_add_tail(&vb->queue, &front->active);
562}
563
564static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
565 enum v4l2_field field)
566{
567 struct front_face *front = q->priv_data;
568 int rc;
569
570 switch (front->type) {
571 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
572 if (VIDEOBUF_NEEDS_INIT == vb->state) {
573 struct v4l2_pix_format *pix;
574
575 pix = &front->pd->video_data.context.pix;
576 vb->size = pix->sizeimage; /* real frame size */
577 vb->width = pix->width;
578 vb->height = pix->height;
579 rc = videobuf_iolock(q, vb, NULL);
580 if (rc < 0)
581 return rc;
582 }
583 break;
584 case V4L2_BUF_TYPE_VBI_CAPTURE:
585 if (VIDEOBUF_NEEDS_INIT == vb->state) {
586 vb->size = front->pd->vbi_data.vbi_size;
587 rc = videobuf_iolock(q, vb, NULL);
588 if (rc < 0)
589 return rc;
590 }
591 break;
592 default:
593 return -EINVAL;
594 }
595 vb->field = field;
596 vb->state = VIDEOBUF_PREPARED;
597 return 0;
598}
599
600static int fire_all_urb(struct video_data *video)
601{
602 int i, ret;
603
604 video->is_streaming = 1;
605
606 for (i = 0; i < SBUF_NUM; i++) {
607 ret = usb_submit_urb(video->urb_array[i], GFP_KERNEL);
608 if (ret)
609 log("(%d) failed: error %d", i, ret);
610 }
611 return ret;
612}
613
614static int start_video_stream(struct poseidon *pd)
615{
616 struct video_data *video = &pd->video_data;
617 s32 cmd_status;
618
619 send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
620 send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_START, &cmd_status);
621
622 if (pd->cur_transfer_mode) {
623 prepare_iso_urb(video);
624 INIT_WORK(&video->bubble_work, iso_bubble_handler);
625 } else {
626 /* The bulk mode does not need a bubble handler */
627 prepare_bulk_urb(video);
628 }
629 fire_all_urb(video);
630 return 0;
631}
632
633static int pd_buf_setup(struct videobuf_queue *q, unsigned int *count,
634 unsigned int *size)
635{
636 struct front_face *front = q->priv_data;
637 struct poseidon *pd = front->pd;
638
639 switch (front->type) {
640 default:
641 return -EINVAL;
642 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
643 struct video_data *video = &pd->video_data;
644 struct v4l2_pix_format *pix = &video->context.pix;
645
646 *size = PAGE_ALIGN(pix->sizeimage);/* page aligned frame size */
647 if (*count < 4)
648 *count = 4;
649 if (1) {
650 /* same in different altersetting */
651 video->endpoint_addr = 0x82;
652 video->vbi = &pd->vbi_data;
653 video->vbi->video = video;
654 video->pd = pd;
655 video->lines_per_field = pix->height / 2;
656 video->lines_size = pix->width * 2;
657 video->front = front;
658 }
659 return start_video_stream(pd);
660 }
661
662 case V4L2_BUF_TYPE_VBI_CAPTURE: {
663 struct vbi_data *vbi = &pd->vbi_data;
664
665 *size = PAGE_ALIGN(vbi->vbi_size);
666 log("size : %d", *size);
667 if (*count == 0)
668 *count = 4;
669 }
670 break;
671 }
672 return 0;
673}
674
675static struct videobuf_queue_ops pd_video_qops = {
676 .buf_setup = pd_buf_setup,
677 .buf_prepare = pd_buf_prepare,
678 .buf_queue = pd_buf_queue,
679 .buf_release = pd_buf_release,
680};
681
682static int vidioc_enum_fmt(struct file *file, void *fh,
683 struct v4l2_fmtdesc *f)
684{
685 if (ARRAY_SIZE(poseidon_formats) <= f->index)
686 return -EINVAL;
687 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
688 f->flags = 0;
689 f->pixelformat = poseidon_formats[f->index].fourcc;
690 strcpy(f->description, poseidon_formats[f->index].name);
691 return 0;
692}
693
694static int vidioc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
695{
696 struct front_face *front = fh;
697 struct poseidon *pd = front->pd;
698
699 f->fmt.pix = pd->video_data.context.pix;
700 return 0;
701}
702
703/*
704 * VLC calls VIDIOC_S_STD before VIDIOC_S_FMT, while
705 * Mplayer calls them in the reverse order.
706 */
707static int pd_vidioc_s_fmt(struct poseidon *pd, struct v4l2_pix_format *pix)
708{
709 struct video_data *video = &pd->video_data;
710 struct running_context *context = &video->context;
711 struct v4l2_pix_format *pix_def = &context->pix;
712 s32 ret = 0, cmd_status = 0, vid_resol;
713
714 /* set the pixel format to firmware */
715 if (pix->pixelformat == V4L2_PIX_FMT_RGB565) {
716 vid_resol = TLG_TUNER_VID_FORMAT_RGB_565;
717 } else {
718 pix->pixelformat = V4L2_PIX_FMT_YUYV;
719 vid_resol = TLG_TUNER_VID_FORMAT_YUV;
720 }
721 ret = send_set_req(pd, VIDEO_STREAM_FMT_SEL,
722 vid_resol, &cmd_status);
723
724 /* set the resolution to firmware */
725 vid_resol = TLG_TUNE_VID_RES_720;
726 switch (pix->width) {
727 case 704:
728 vid_resol = TLG_TUNE_VID_RES_704;
729 break;
730 default:
731 pix->width = 720;
732 case 720:
733 break;
734 }
735 ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
736 vid_resol, &cmd_status);
737 if (ret || cmd_status)
738 return -EBUSY;
739
740 pix_def->pixelformat = pix->pixelformat; /* save it */
741 pix->height = (context->tvnormid & V4L2_STD_525_60) ? 480 : 576;
742
743 /* Compare with the default setting */
744 if ((pix_def->width != pix->width)
745 || (pix_def->height != pix->height)) {
746 pix_def->width = pix->width;
747 pix_def->height = pix->height;
748 pix_def->bytesperline = pix->width * 2;
749 pix_def->sizeimage = pix->width * pix->height * 2;
750 }
751 *pix = *pix_def;
752
753 return 0;
754}
755
756static int vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
757{
758 struct front_face *front = fh;
759 struct poseidon *pd = front->pd;
760
761 /* stop VBI here */
762 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
763 return -EINVAL;
764
765 mutex_lock(&pd->lock);
766 if (pd->file_for_stream == NULL)
767 pd->file_for_stream = file;
768 else if (file != pd->file_for_stream) {
769 mutex_unlock(&pd->lock);
770 return -EINVAL;
771 }
772
773 pd_vidioc_s_fmt(pd, &f->fmt.pix);
774 mutex_unlock(&pd->lock);
775 return 0;
776}
777
778static int vidioc_g_fmt_vbi(struct file *file, void *fh,
779 struct v4l2_format *v4l2_f)
780{
781 struct front_face *front = fh;
782 struct poseidon *pd = front->pd;
783 struct v4l2_vbi_format *vbi_fmt = &v4l2_f->fmt.vbi;
784
785 vbi_fmt->samples_per_line = 720 * 2;
786 vbi_fmt->sampling_rate = 6750000 * 4;
787 vbi_fmt->sample_format = V4L2_PIX_FMT_GREY;
788 vbi_fmt->offset = 64 * 4; /*FIXME: why offset */
789 if (pd->video_data.context.tvnormid & V4L2_STD_525_60) {
790 vbi_fmt->start[0] = 10;
791 vbi_fmt->start[1] = 264;
792 vbi_fmt->count[0] = V4L_NTSC_VBI_LINES;
793 vbi_fmt->count[1] = V4L_NTSC_VBI_LINES;
794 } else {
795 vbi_fmt->start[0] = 6;
796 vbi_fmt->start[1] = 314;
797 vbi_fmt->count[0] = V4L_PAL_VBI_LINES;
798 vbi_fmt->count[1] = V4L_PAL_VBI_LINES;
799 }
800 vbi_fmt->flags = V4L2_VBI_UNSYNC;
801 return 0;
802}
803
804static int set_std(struct poseidon *pd, v4l2_std_id norm)
805{
806 struct video_data *video = &pd->video_data;
807 struct vbi_data *vbi = &pd->vbi_data;
808 struct running_context *context;
809 struct v4l2_pix_format *pix;
810 s32 i, ret = 0, cmd_status, param;
811 int height;
812
813 for (i = 0; i < POSEIDON_TVNORMS; i++) {
814 if (norm & poseidon_tvnorms[i].v4l2_id) {
815 param = poseidon_tvnorms[i].tlg_tvnorm;
816 log("name : %s", poseidon_tvnorms[i].name);
817 goto found;
818 }
819 }
820 return -EINVAL;
821found:
822 mutex_lock(&pd->lock);
823 ret = send_set_req(pd, VIDEO_STD_SEL, param, &cmd_status);
824 if (ret || cmd_status)
825 goto out;
826
827 /* Set vbi size and check the height of the frame */
828 context = &video->context;
829 context->tvnormid = poseidon_tvnorms[i].v4l2_id;
830 if (context->tvnormid & V4L2_STD_525_60) {
831 vbi->vbi_size = V4L_NTSC_VBI_FRAMESIZE;
832 height = 480;
833 } else {
834 vbi->vbi_size = V4L_PAL_VBI_FRAMESIZE;
835 height = 576;
836 }
837
838 pix = &context->pix;
839 if (pix->height != height) {
840 pix->height = height;
841 pix->sizeimage = pix->width * pix->height * 2;
842 }
843
844out:
845 mutex_unlock(&pd->lock);
846 return ret;
847}
848
849static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id norm)
850{
851 struct front_face *front = fh;
852
853 return set_std(front->pd, norm);
854}
855
856static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
857{
858 struct front_face *front = fh;
859
860 *norm = front->pd->video_data.context.tvnormid;
861 return 0;
862}
863
864static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
865{
866 if (in->index >= POSEIDON_INPUTS)
867 return -EINVAL;
868 strcpy(in->name, pd_inputs[in->index].name);
869 in->type = V4L2_INPUT_TYPE_TUNER;
870
871 /*
872 * the audio input index mixed with this video input,
873 * Poseidon only have one audio/video, set to "0"
874 */
875 in->audioset = 1;
876 in->tuner = 0;
877 in->std = V4L2_STD_ALL;
878 in->status = 0;
879 return 0;
880}
881
882static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
883{
884 struct front_face *front = fh;
885 struct poseidon *pd = front->pd;
886 struct running_context *context = &pd->video_data.context;
887
888 *i = context->sig_index;
889 return 0;
890}
891
892/* We can support several inputs */
893static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
894{
895 struct front_face *front = fh;
896 struct poseidon *pd = front->pd;
897 s32 ret, cmd_status;
898
899 if (i >= POSEIDON_INPUTS)
900 return -EINVAL;
901 ret = send_set_req(pd, SGNL_SRC_SEL,
902 pd_inputs[i].tlg_src, &cmd_status);
903 if (ret)
904 return ret;
905
906 pd->video_data.context.sig_index = i;
907 return 0;
908}
909
910static int tlg_s_ctrl(struct v4l2_ctrl *c)
911{
912 struct poseidon *pd = container_of(c->handler, struct poseidon,
913 video_data.ctrl_handler);
914 struct tuner_custom_parameter_s param = {0};
915 s32 ret = 0, cmd_status, params;
916
917 switch (c->id) {
918 case V4L2_CID_BRIGHTNESS:
919 param.param_id = CUST_PARM_ID_BRIGHTNESS_CTRL;
920 break;
921 case V4L2_CID_CONTRAST:
922 param.param_id = CUST_PARM_ID_CONTRAST_CTRL;
923 break;
924 case V4L2_CID_HUE:
925 param.param_id = CUST_PARM_ID_HUE_CTRL;
926 break;
927 case V4L2_CID_SATURATION:
928 param.param_id = CUST_PARM_ID_SATURATION_CTRL;
929 break;
930 }
931 param.param_value = c->val;
932 params = *(s32 *)&param; /* temp code */
933
934 mutex_lock(&pd->lock);
935 ret = send_set_req(pd, TUNER_CUSTOM_PARAMETER, params, &cmd_status);
936 ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
937 mutex_unlock(&pd->lock);
938
939 set_current_state(TASK_INTERRUPTIBLE);
940 schedule_timeout(HZ/4);
941 return ret;
942}
943
944/* Audio ioctls */
945static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
946{
947 if (0 != a->index)
948 return -EINVAL;
949 a->capability = V4L2_AUDCAP_STEREO;
950 strcpy(a->name, "USB audio in");
951 /*Poseidon have no AVL function.*/
952 a->mode = 0;
953 return 0;
954}
955
956static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
957{
958 a->index = 0;
959 a->capability = V4L2_AUDCAP_STEREO;
960 strcpy(a->name, "USB audio in");
961 a->mode = 0;
962 return 0;
963}
964
965static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
966{
967 return (0 == a->index) ? 0 : -EINVAL;
968}
969
970/* Tuner ioctls */
971static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *tuner)
972{
973 struct front_face *front = fh;
974 struct poseidon *pd = front->pd;
975 struct tuner_atv_sig_stat_s atv_stat;
976 s32 count = 5, ret, cmd_status;
977 int index;
978
979 if (0 != tuner->index)
980 return -EINVAL;
981
982 mutex_lock(&pd->lock);
983 ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV,
984 &atv_stat, &cmd_status, sizeof(atv_stat));
985
986 while (atv_stat.sig_lock_busy && count-- && !ret) {
987 set_current_state(TASK_INTERRUPTIBLE);
988 schedule_timeout(HZ);
989
990 ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV,
991 &atv_stat, &cmd_status, sizeof(atv_stat));
992 }
993 mutex_unlock(&pd->lock);
994
995 if (debug_mode)
996 log("P:%d,S:%d", atv_stat.sig_present, atv_stat.sig_strength);
997
998 if (ret || cmd_status)
999 tuner->signal = 0;
1000 else if (atv_stat.sig_present && !atv_stat.sig_strength)
1001 tuner->signal = 0xFFFF;
1002 else
1003 tuner->signal = (atv_stat.sig_strength * 255 / 10) << 8;
1004
1005 strcpy(tuner->name, "Telegent Systems");
1006 tuner->type = V4L2_TUNER_ANALOG_TV;
1007 tuner->rangelow = TUNER_FREQ_MIN / 62500;
1008 tuner->rangehigh = TUNER_FREQ_MAX / 62500;
1009 tuner->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
1010 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
1011 index = pd->video_data.context.audio_idx;
1012 tuner->rxsubchans = pd_audio_modes[index].v4l2_audio_sub;
1013 tuner->audmode = pd_audio_modes[index].v4l2_audio_mode;
1014 tuner->afc = 0;
1015 return 0;
1016}
1017
1018static int pd_vidioc_s_tuner(struct poseidon *pd, int index)
1019{
1020 s32 ret = 0, cmd_status, param, audiomode;
1021
1022 mutex_lock(&pd->lock);
1023 param = pd_audio_modes[index].tlg_audio_mode;
1024 ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status);
1025 audiomode = get_audio_std(pd->video_data.context.tvnormid);
1026 ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode,
1027 &cmd_status);
1028 if (!ret)
1029 pd->video_data.context.audio_idx = index;
1030 mutex_unlock(&pd->lock);
1031 return ret;
1032}
1033
1034static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *a)
1035{
1036 struct front_face *front = fh;
1037 struct poseidon *pd = front->pd;
1038 int index;
1039
1040 if (0 != a->index)
1041 return -EINVAL;
1042 for (index = 0; index < POSEIDON_AUDIOMODS; index++)
1043 if (a->audmode == pd_audio_modes[index].v4l2_audio_mode)
1044 return pd_vidioc_s_tuner(pd, index);
1045 return -EINVAL;
1046}
1047
1048static int vidioc_g_frequency(struct file *file, void *fh,
1049 struct v4l2_frequency *freq)
1050{
1051 struct front_face *front = fh;
1052 struct poseidon *pd = front->pd;
1053 struct running_context *context = &pd->video_data.context;
1054
1055 if (0 != freq->tuner)
1056 return -EINVAL;
1057 freq->frequency = context->freq;
1058 freq->type = V4L2_TUNER_ANALOG_TV;
1059 return 0;
1060}
1061
1062static int set_frequency(struct poseidon *pd, u32 *frequency)
1063{
1064 s32 ret = 0, param, cmd_status;
1065 struct running_context *context = &pd->video_data.context;
1066
1067 *frequency = clamp(*frequency,
1068 TUNER_FREQ_MIN / 62500, TUNER_FREQ_MAX / 62500);
1069 param = (*frequency) * 62500 / 1000;
1070
1071 mutex_lock(&pd->lock);
1072 ret = send_set_req(pd, TUNE_FREQ_SELECT, param, &cmd_status);
1073 ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
1074
1075 msleep(250); /* wait for a while until the hardware is ready. */
1076 context->freq = *frequency;
1077 mutex_unlock(&pd->lock);
1078 return ret;
1079}
1080
1081static int vidioc_s_frequency(struct file *file, void *fh,
1082 const struct v4l2_frequency *freq)
1083{
1084 struct front_face *front = fh;
1085 struct poseidon *pd = front->pd;
1086 u32 frequency = freq->frequency;
1087
1088 if (freq->tuner)
1089 return -EINVAL;
1090#ifdef CONFIG_PM
1091 pd->pm_suspend = pm_video_suspend;
1092 pd->pm_resume = pm_video_resume;
1093#endif
1094 return set_frequency(pd, &frequency);
1095}
1096
1097static int vidioc_reqbufs(struct file *file, void *fh,
1098 struct v4l2_requestbuffers *b)
1099{
1100 struct front_face *front = file->private_data;
1101 return videobuf_reqbufs(&front->q, b);
1102}
1103
1104static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
1105{
1106 struct front_face *front = file->private_data;
1107 return videobuf_querybuf(&front->q, b);
1108}
1109
1110static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
1111{
1112 struct front_face *front = file->private_data;
1113 return videobuf_qbuf(&front->q, b);
1114}
1115
1116static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
1117{
1118 struct front_face *front = file->private_data;
1119 return videobuf_dqbuf(&front->q, b, file->f_flags & O_NONBLOCK);
1120}
1121
1122/* Just stop the URBs, do not free the URBs */
1123static int usb_transfer_stop(struct video_data *video)
1124{
1125 if (video->is_streaming) {
1126 int i;
1127 s32 cmd_status;
1128 struct poseidon *pd = video->pd;
1129
1130 video->is_streaming = 0;
1131 for (i = 0; i < SBUF_NUM; ++i) {
1132 if (video->urb_array[i])
1133 usb_kill_urb(video->urb_array[i]);
1134 }
1135
1136 send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
1137 &cmd_status);
1138 }
1139 return 0;
1140}
1141
1142int stop_all_video_stream(struct poseidon *pd)
1143{
1144 struct video_data *video = &pd->video_data;
1145 struct vbi_data *vbi = &pd->vbi_data;
1146
1147 mutex_lock(&pd->lock);
1148 if (video->is_streaming) {
1149 struct front_face *front = video->front;
1150
1151 /* stop the URBs */
1152 usb_transfer_stop(video);
1153 free_all_urb(video);
1154
1155 /* stop the host side of VIDEO */
1156 videobuf_stop(&front->q);
1157 videobuf_mmap_free(&front->q);
1158
1159 /* stop the host side of VBI */
1160 front = vbi->front;
1161 if (front) {
1162 videobuf_stop(&front->q);
1163 videobuf_mmap_free(&front->q);
1164 }
1165 }
1166 mutex_unlock(&pd->lock);
1167 return 0;
1168}
1169
1170/*
1171 * The bubbles can seriously damage the video's quality,
1172 * though it occurs in very rare situation.
1173 */
1174static void iso_bubble_handler(struct work_struct *w)
1175{
1176 struct video_data *video;
1177 struct poseidon *pd;
1178
1179 video = container_of(w, struct video_data, bubble_work);
1180 pd = video->pd;
1181
1182 mutex_lock(&pd->lock);
1183 usb_transfer_stop(video);
1184 msleep(500);
1185 start_video_stream(pd);
1186 mutex_unlock(&pd->lock);
1187}
1188
1189
1190static int vidioc_streamon(struct file *file, void *fh,
1191 enum v4l2_buf_type type)
1192{
1193 struct front_face *front = fh;
1194
1195 if (unlikely(type != front->type))
1196 return -EINVAL;
1197 return videobuf_streamon(&front->q);
1198}
1199
1200static int vidioc_streamoff(struct file *file, void *fh,
1201 enum v4l2_buf_type type)
1202{
1203 struct front_face *front = file->private_data;
1204
1205 if (unlikely(type != front->type))
1206 return -EINVAL;
1207 return videobuf_streamoff(&front->q);
1208}
1209
1210/* Set the firmware's default values : need altersetting */
1211static int pd_video_checkmode(struct poseidon *pd)
1212{
1213 s32 ret = 0, cmd_status, audiomode;
1214
1215 set_current_state(TASK_INTERRUPTIBLE);
1216 schedule_timeout(HZ/2);
1217
1218 /* choose the altersetting */
1219 ret = usb_set_interface(pd->udev, 0,
1220 (pd->cur_transfer_mode ?
1221 ISO_3K_BULK_ALTERNATE_IFACE :
1222 BULK_ALTERNATE_IFACE));
1223 if (ret < 0)
1224 goto error;
1225
1226 /* set default parameters for PAL-D , with the VBI enabled*/
1227 ret = set_tuner_mode(pd, TLG_MODE_ANALOG_TV);
1228 ret |= send_set_req(pd, SGNL_SRC_SEL,
1229 TLG_SIG_SRC_ANTENNA, &cmd_status);
1230 ret |= send_set_req(pd, VIDEO_STD_SEL,
1231 TLG_TUNE_VSTD_PAL_D, &cmd_status);
1232 ret |= send_set_req(pd, VIDEO_STREAM_FMT_SEL,
1233 TLG_TUNER_VID_FORMAT_YUV, &cmd_status);
1234 ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
1235 TLG_TUNE_VID_RES_720, &cmd_status);
1236 ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status);
1237 ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */
1238
1239 /* set the audio */
1240 audiomode = get_audio_std(pd->video_data.context.tvnormid);
1241 ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status);
1242 ret |= send_set_req(pd, TUNER_AUD_MODE,
1243 TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status);
1244 ret |= send_set_req(pd, AUDIO_SAMPLE_RATE_SEL,
1245 ATV_AUDIO_RATE_48K, &cmd_status);
1246error:
1247 return ret;
1248}
1249
1250#ifdef CONFIG_PM
1251static int pm_video_suspend(struct poseidon *pd)
1252{
1253 /* stop audio */
1254 pm_alsa_suspend(pd);
1255
1256 /* stop and free all the URBs */
1257 usb_transfer_stop(&pd->video_data);
1258 free_all_urb(&pd->video_data);
1259
1260 /* reset the interface */
1261 usb_set_interface(pd->udev, 0, 0);
1262 msleep(300);
1263 return 0;
1264}
1265
1266static int restore_v4l2_context(struct poseidon *pd,
1267 struct running_context *context)
1268{
1269 struct front_face *front = pd->video_data.front;
1270
1271 pd_video_checkmode(pd);
1272
1273 set_std(pd, context->tvnormid);
1274 vidioc_s_input(NULL, front, context->sig_index);
1275 pd_vidioc_s_tuner(pd, context->audio_idx);
1276 pd_vidioc_s_fmt(pd, &context->pix);
1277 set_frequency(pd, &context->freq);
1278 return 0;
1279}
1280
1281static int pm_video_resume(struct poseidon *pd)
1282{
1283 struct video_data *video = &pd->video_data;
1284
1285 /* resume the video */
1286 /* [1] restore the origin V4L2 parameters */
1287 restore_v4l2_context(pd, &video->context);
1288
1289 /* [2] initiate video copy variables */
1290 if (video->front->curr_frame)
1291 init_copy(video, 0);
1292
1293 /* [3] fire urbs */
1294 start_video_stream(pd);
1295
1296 /* resume the audio */
1297 pm_alsa_resume(pd);
1298 return 0;
1299}
1300#endif
1301
1302void set_debug_mode(struct video_device *vfd, int debug_mode)
1303{
1304 vfd->debug = 0;
1305 if (debug_mode & 0x1)
1306 vfd->debug = V4L2_DEBUG_IOCTL;
1307 if (debug_mode & 0x2)
1308 vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
1309}
1310
1311static void init_video_context(struct running_context *context)
1312{
1313 context->sig_index = 0;
1314 context->audio_idx = 1; /* stereo */
1315 context->tvnormid = V4L2_STD_PAL_D;
1316 context->pix = (struct v4l2_pix_format) {
1317 .width = 720,
1318 .height = 576,
1319 .pixelformat = V4L2_PIX_FMT_YUYV,
1320 .field = V4L2_FIELD_INTERLACED,
1321 .bytesperline = 720 * 2,
1322 .sizeimage = 720 * 576 * 2,
1323 .colorspace = V4L2_COLORSPACE_SMPTE170M,
1324 };
1325}
1326
1327static int pd_video_open(struct file *file)
1328{
1329 struct video_device *vfd = video_devdata(file);
1330 struct poseidon *pd = video_get_drvdata(vfd);
1331 struct front_face *front = NULL;
1332 int ret = -ENOMEM;
1333
1334 mutex_lock(&pd->lock);
1335 usb_autopm_get_interface(pd->interface);
1336
1337 if (pd->state && !(pd->state & POSEIDON_STATE_ANALOG)) {
1338 ret = -EBUSY;
1339 goto out;
1340 }
1341 front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
1342 if (!front)
1343 goto out;
1344 if (vfd->vfl_type == VFL_TYPE_GRABBER) {
1345 pd->cur_transfer_mode = usb_transfer_mode;/* bulk or iso */
1346 init_video_context(&pd->video_data.context);
1347
1348 ret = pd_video_checkmode(pd);
1349 if (ret < 0) {
1350 kfree(front);
1351 ret = -1;
1352 goto out;
1353 }
1354
1355 front->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1356 pd->video_data.users++;
1357 set_debug_mode(vfd, debug_mode);
1358
1359 videobuf_queue_vmalloc_init(&front->q, &pd_video_qops,
1360 NULL, &front->queue_lock,
1361 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1362 V4L2_FIELD_INTERLACED,/* video is interlacd */
1363 sizeof(struct videobuf_buffer),/*it's enough*/
1364 front, NULL);
1365 } else {
1366 front->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1367 pd->vbi_data.front = front;
1368 pd->vbi_data.users++;
1369
1370 videobuf_queue_vmalloc_init(&front->q, &pd_video_qops,
1371 NULL, &front->queue_lock,
1372 V4L2_BUF_TYPE_VBI_CAPTURE,
1373 V4L2_FIELD_NONE, /* vbi is NONE mode */
1374 sizeof(struct videobuf_buffer),
1375 front, NULL);
1376 }
1377
1378 pd->state |= POSEIDON_STATE_ANALOG;
1379 front->pd = pd;
1380 front->curr_frame = NULL;
1381 INIT_LIST_HEAD(&front->active);
1382 spin_lock_init(&front->queue_lock);
1383
1384 file->private_data = front;
1385 kref_get(&pd->kref);
1386
1387 mutex_unlock(&pd->lock);
1388 return 0;
1389out:
1390 usb_autopm_put_interface(pd->interface);
1391 mutex_unlock(&pd->lock);
1392 return ret;
1393}
1394
1395static int pd_video_release(struct file *file)
1396{
1397 struct front_face *front = file->private_data;
1398 struct poseidon *pd = front->pd;
1399 s32 cmd_status = 0;
1400
1401 mutex_lock(&pd->lock);
1402
1403 if (front->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1404 /* stop the device, and free the URBs */
1405 usb_transfer_stop(&pd->video_data);
1406 free_all_urb(&pd->video_data);
1407
1408 /* stop the firmware */
1409 send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
1410 &cmd_status);
1411
1412 pd->file_for_stream = NULL;
1413 pd->video_data.users--;
1414 } else if (front->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1415 pd->vbi_data.front = NULL;
1416 pd->vbi_data.users--;
1417 }
1418 if (!pd->vbi_data.users && !pd->video_data.users)
1419 pd->state &= ~POSEIDON_STATE_ANALOG;
1420 videobuf_stop(&front->q);
1421 videobuf_mmap_free(&front->q);
1422
1423 usb_autopm_put_interface(pd->interface);
1424 mutex_unlock(&pd->lock);
1425
1426 kfree(front);
1427 file->private_data = NULL;
1428 kref_put(&pd->kref, poseidon_delete);
1429 return 0;
1430}
1431
1432static int pd_video_mmap(struct file *file, struct vm_area_struct *vma)
1433{
1434 struct front_face *front = file->private_data;
1435 return videobuf_mmap_mapper(&front->q, vma);
1436}
1437
1438static unsigned int pd_video_poll(struct file *file, poll_table *table)
1439{
1440 struct front_face *front = file->private_data;
1441 return videobuf_poll_stream(file, &front->q, table);
1442}
1443
1444static ssize_t pd_video_read(struct file *file, char __user *buffer,
1445 size_t count, loff_t *ppos)
1446{
1447 struct front_face *front = file->private_data;
1448 return videobuf_read_stream(&front->q, buffer, count, ppos,
1449 0, file->f_flags & O_NONBLOCK);
1450}
1451
1452/* This struct works for both VIDEO and VBI */
1453static const struct v4l2_file_operations pd_video_fops = {
1454 .owner = THIS_MODULE,
1455 .open = pd_video_open,
1456 .release = pd_video_release,
1457 .read = pd_video_read,
1458 .poll = pd_video_poll,
1459 .mmap = pd_video_mmap,
1460 .ioctl = video_ioctl2, /* maybe changed in future */
1461};
1462
1463static const struct v4l2_ioctl_ops pd_video_ioctl_ops = {
1464 .vidioc_querycap = vidioc_querycap,
1465
1466 /* Video format */
1467 .vidioc_g_fmt_vid_cap = vidioc_g_fmt,
1468 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt,
1469 .vidioc_s_fmt_vid_cap = vidioc_s_fmt,
1470 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi, /* VBI */
1471
1472 /* Input */
1473 .vidioc_g_input = vidioc_g_input,
1474 .vidioc_s_input = vidioc_s_input,
1475 .vidioc_enum_input = vidioc_enum_input,
1476
1477 /* Audio ioctls */
1478 .vidioc_enumaudio = vidioc_enumaudio,
1479 .vidioc_g_audio = vidioc_g_audio,
1480 .vidioc_s_audio = vidioc_s_audio,
1481
1482 /* Tuner ioctls */
1483 .vidioc_g_tuner = vidioc_g_tuner,
1484 .vidioc_s_tuner = vidioc_s_tuner,
1485 .vidioc_g_std = vidioc_g_std,
1486 .vidioc_s_std = vidioc_s_std,
1487 .vidioc_g_frequency = vidioc_g_frequency,
1488 .vidioc_s_frequency = vidioc_s_frequency,
1489
1490 /* Buffer handlers */
1491 .vidioc_reqbufs = vidioc_reqbufs,
1492 .vidioc_querybuf = vidioc_querybuf,
1493 .vidioc_qbuf = vidioc_qbuf,
1494 .vidioc_dqbuf = vidioc_dqbuf,
1495
1496 /* Stream on/off */
1497 .vidioc_streamon = vidioc_streamon,
1498 .vidioc_streamoff = vidioc_streamoff,
1499};
1500
1501static struct video_device pd_video_template = {
1502 .name = "Telegent-Video",
1503 .fops = &pd_video_fops,
1504 .minor = -1,
1505 .release = video_device_release_empty,
1506 .tvnorms = V4L2_STD_ALL,
1507 .ioctl_ops = &pd_video_ioctl_ops,
1508};
1509
1510static const struct v4l2_ctrl_ops tlg_ctrl_ops = {
1511 .s_ctrl = tlg_s_ctrl,
1512};
1513
1514void pd_video_exit(struct poseidon *pd)
1515{
1516 struct video_data *video = &pd->video_data;
1517 struct vbi_data *vbi = &pd->vbi_data;
1518
1519 video_unregister_device(&video->v_dev);
1520 video_unregister_device(&vbi->v_dev);
1521 v4l2_ctrl_handler_free(&video->ctrl_handler);
1522 log();
1523}
1524
1525int pd_video_init(struct poseidon *pd)
1526{
1527 struct video_data *video = &pd->video_data;
1528 struct vbi_data *vbi = &pd->vbi_data;
1529 struct v4l2_ctrl_handler *hdl = &video->ctrl_handler;
1530 u32 freq = TUNER_FREQ_MIN / 62500;
1531 int ret = -ENOMEM;
1532
1533 v4l2_ctrl_handler_init(hdl, 4);
1534 v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_BRIGHTNESS,
1535 0, 10000, 1, 100);
1536 v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_CONTRAST,
1537 0, 10000, 1, 100);
1538 v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_HUE,
1539 0, 10000, 1, 100);
1540 v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_SATURATION,
1541 0, 10000, 1, 100);
1542 if (hdl->error) {
1543 v4l2_ctrl_handler_free(hdl);
1544 return hdl->error;
1545 }
1546 set_frequency(pd, &freq);
1547 video->v_dev = pd_video_template;
1548 video->v_dev.v4l2_dev = &pd->v4l2_dev;
1549 video->v_dev.ctrl_handler = hdl;
1550 video_set_drvdata(&video->v_dev, pd);
1551
1552 ret = video_register_device(&video->v_dev, VFL_TYPE_GRABBER, -1);
1553 if (ret != 0)
1554 goto out;
1555
1556 /* VBI uses the same template as video */
1557 vbi->v_dev = pd_video_template;
1558 vbi->v_dev.v4l2_dev = &pd->v4l2_dev;
1559 vbi->v_dev.ctrl_handler = hdl;
1560 video_set_drvdata(&vbi->v_dev, pd);
1561 ret = video_register_device(&vbi->v_dev, VFL_TYPE_VBI, -1);
1562 if (ret != 0)
1563 goto out;
1564 log("register VIDEO/VBI devices");
1565 return 0;
1566out:
1567 log("VIDEO/VBI devices register failed, : %d", ret);
1568 pd_video_exit(pd);
1569 return ret;
1570}
diff --git a/drivers/media/usb/tlg2300/vendorcmds.h b/drivers/media/usb/tlg2300/vendorcmds.h
deleted file mode 100644
index ba6f4ae3b2c2..000000000000
--- a/drivers/media/usb/tlg2300/vendorcmds.h
+++ /dev/null
@@ -1,243 +0,0 @@
1#ifndef VENDOR_CMD_H_
2#define VENDOR_CMD_H_
3
4#define BULK_ALTERNATE_IFACE (2)
5#define ISO_3K_BULK_ALTERNATE_IFACE (1)
6#define REQ_SET_CMD (0X00)
7#define REQ_GET_CMD (0X80)
8
9enum tlg__analog_audio_standard {
10 TLG_TUNE_ASTD_NONE = 0x00000000,
11 TLG_TUNE_ASTD_A2 = 0x00000001,
12 TLG_TUNE_ASTD_NICAM = 0x00000002,
13 TLG_TUNE_ASTD_EIAJ = 0x00000004,
14 TLG_TUNE_ASTD_BTSC = 0x00000008,
15 TLG_TUNE_ASTD_FM_US = 0x00000010,
16 TLG_TUNE_ASTD_FM_EUR = 0x00000020,
17 TLG_TUNE_ASTD_ALL = 0x0000003f
18};
19
20/*
21 * identifiers for Custom Parameter messages.
22 * @typedef cmd_custom_param_id_t
23 */
24enum cmd_custom_param_id {
25 CUST_PARM_ID_NONE = 0x00,
26 CUST_PARM_ID_BRIGHTNESS_CTRL = 0x01,
27 CUST_PARM_ID_CONTRAST_CTRL = 0x02,
28 CUST_PARM_ID_HUE_CTRL = 0x03,
29 CUST_PARM_ID_SATURATION_CTRL = 0x04,
30 CUST_PARM_ID_AUDIO_SNR_THRESHOLD = 0x10,
31 CUST_PARM_ID_AUDIO_AGC_THRESHOLD = 0x11,
32 CUST_PARM_ID_MAX
33};
34
35struct tuner_custom_parameter_s {
36 uint16_t param_id; /* Parameter identifier */
37 uint16_t param_value; /* Parameter value */
38};
39
40struct tuner_ber_rate_s {
41 uint32_t ber_rate; /* BER sample rate in seconds */
42};
43
44struct tuner_atv_sig_stat_s {
45 uint32_t sig_present;
46 uint32_t sig_locked;
47 uint32_t sig_lock_busy;
48 uint32_t sig_strength; /* milliDb */
49 uint32_t tv_audio_chan; /* mono/stereo/sap*/
50 uint32_t mvision_stat; /* macrovision status */
51};
52
53struct tuner_dtv_sig_stat_s {
54 uint32_t sig_present; /* Boolean*/
55 uint32_t sig_locked; /* Boolean */
56 uint32_t sig_lock_busy; /* Boolean (Can this time-out?) */
57 uint32_t sig_strength; /* milliDb*/
58};
59
60struct tuner_fm_sig_stat_s {
61 uint32_t sig_present; /* Boolean*/
62 uint32_t sig_locked; /* Boolean */
63 uint32_t sig_lock_busy; /* Boolean */
64 uint32_t sig_stereo_mono;/* TBD*/
65 uint32_t sig_strength; /* milliDb*/
66};
67
68enum _tag_tlg_tune_srv_cmd {
69 TLG_TUNE_PLAY_SVC_START = 1,
70 TLG_TUNE_PLAY_SVC_STOP
71};
72
73enum _tag_tune_atv_audio_mode_caps {
74 TLG_TUNE_TVAUDIO_MODE_MONO = 0x00000001,
75 TLG_TUNE_TVAUDIO_MODE_STEREO = 0x00000002,
76 TLG_TUNE_TVAUDIO_MODE_LANG_A = 0x00000010,/* Primary language*/
77 TLG_TUNE_TVAUDIO_MODE_LANG_B = 0x00000020,/* 2nd avail language*/
78 TLG_TUNE_TVAUDIO_MODE_LANG_C = 0x00000040
79};
80
81
82enum _tag_tuner_atv_audio_rates {
83 ATV_AUDIO_RATE_NONE = 0x00,/* Audio not supported*/
84 ATV_AUDIO_RATE_32K = 0x01,/* Audio rate = 32 KHz*/
85 ATV_AUDIO_RATE_48K = 0x02, /* Audio rate = 48 KHz*/
86 ATV_AUDIO_RATE_31_25K = 0x04 /* Audio rate = 31.25KHz */
87};
88
89enum _tag_tune_atv_vid_res_caps {
90 TLG_TUNE_VID_RES_NONE = 0x00000000,
91 TLG_TUNE_VID_RES_720 = 0x00000001,
92 TLG_TUNE_VID_RES_704 = 0x00000002,
93 TLG_TUNE_VID_RES_360 = 0x00000004
94};
95
96enum _tag_tuner_analog_video_format {
97 TLG_TUNER_VID_FORMAT_YUV = 0x00000001,
98 TLG_TUNER_VID_FORMAT_YCRCB = 0x00000002,
99 TLG_TUNER_VID_FORMAT_RGB_565 = 0x00000004,
100};
101
102enum tlg_ext_audio_support {
103 TLG_EXT_AUDIO_NONE = 0x00,/* No external audio input supported */
104 TLG_EXT_AUDIO_LR = 0x01/* LR external audio inputs supported*/
105};
106
107enum {
108 TLG_MODE_NONE = 0x00, /* No Mode specified*/
109 TLG_MODE_ANALOG_TV = 0x01, /* Analog Television mode*/
110 TLG_MODE_ANALOG_TV_UNCOMP = 0x01, /* Analog Television mode*/
111 TLG_MODE_ANALOG_TV_COMP = 0x02, /* Analog TV mode (compressed)*/
112 TLG_MODE_FM_RADIO = 0x04, /* FM Radio mode*/
113 TLG_MODE_DVB_T = 0x08, /* Digital TV (DVB-T)*/
114};
115
116enum tlg_signal_sources_t {
117 TLG_SIG_SRC_NONE = 0x00,/* Signal source not specified */
118 TLG_SIG_SRC_ANTENNA = 0x01,/* Signal src is: Antenna */
119 TLG_SIG_SRC_CABLE = 0x02,/* Signal src is: Coax Cable*/
120 TLG_SIG_SRC_SVIDEO = 0x04,/* Signal src is: S_VIDEO */
121 TLG_SIG_SRC_COMPOSITE = 0x08 /* Signal src is: Composite Video */
122};
123
124enum tuner_analog_video_standard {
125 TLG_TUNE_VSTD_NONE = 0x00000000,
126 TLG_TUNE_VSTD_NTSC_M = 0x00000001,
127 TLG_TUNE_VSTD_NTSC_M_J = 0x00000002,/* Japan */
128 TLG_TUNE_VSTD_PAL_B = 0x00000010,
129 TLG_TUNE_VSTD_PAL_D = 0x00000020,
130 TLG_TUNE_VSTD_PAL_G = 0x00000040,
131 TLG_TUNE_VSTD_PAL_H = 0x00000080,
132 TLG_TUNE_VSTD_PAL_I = 0x00000100,
133 TLG_TUNE_VSTD_PAL_M = 0x00000200,
134 TLG_TUNE_VSTD_PAL_N = 0x00000400,
135 TLG_TUNE_VSTD_SECAM_B = 0x00001000,
136 TLG_TUNE_VSTD_SECAM_D = 0x00002000,
137 TLG_TUNE_VSTD_SECAM_G = 0x00004000,
138 TLG_TUNE_VSTD_SECAM_H = 0x00008000,
139 TLG_TUNE_VSTD_SECAM_K = 0x00010000,
140 TLG_TUNE_VSTD_SECAM_K1 = 0x00020000,
141 TLG_TUNE_VSTD_SECAM_L = 0x00040000,
142 TLG_TUNE_VSTD_SECAM_L1 = 0x00080000,
143 TLG_TUNE_VSTD_PAL_N_COMBO = 0x00100000
144};
145
146enum tlg_mode_caps {
147 TLG_MODE_CAPS_NONE = 0x00, /* No Mode specified */
148 TLG_MODE_CAPS_ANALOG_TV_UNCOMP = 0x01, /* Analog TV mode */
149 TLG_MODE_CAPS_ANALOG_TV_COMP = 0x02, /* Analog TV (compressed)*/
150 TLG_MODE_CAPS_FM_RADIO = 0x04, /* FM Radio mode */
151 TLG_MODE_CAPS_DVB_T = 0x08, /* Digital TV (DVB-T) */
152};
153
154enum poseidon_vendor_cmds {
155 LAST_CMD_STAT = 0x00,
156 GET_CHIP_ID = 0x01,
157 GET_FW_ID = 0x02,
158 PRODUCT_CAPS = 0x03,
159
160 TUNE_MODE_CAP_ATV = 0x10,
161 TUNE_MODE_CAP_ATVCOMP = 0X10,
162 TUNE_MODE_CAP_DVBT = 0x10,
163 TUNE_MODE_CAP_FM = 0x10,
164 TUNE_MODE_SELECT = 0x11,
165 TUNE_FREQ_SELECT = 0x12,
166 SGNL_SRC_SEL = 0x13,
167
168 VIDEO_STD_SEL = 0x14,
169 VIDEO_STREAM_FMT_SEL = 0x15,
170 VIDEO_ROSOLU_AVAIL = 0x16,
171 VIDEO_ROSOLU_SEL = 0x17,
172 VIDEO_CONT_PROTECT = 0x20,
173
174 VCR_TIMING_MODSEL = 0x21,
175 EXT_AUDIO_CAP = 0x22,
176 EXT_AUDIO_SEL = 0x23,
177 TEST_PATTERN_SEL = 0x24,
178 VBI_DATA_SEL = 0x25,
179 AUDIO_SAMPLE_RATE_CAP = 0x28,
180 AUDIO_SAMPLE_RATE_SEL = 0x29,
181 TUNER_AUD_MODE = 0x2a,
182 TUNER_AUD_MODE_AVAIL = 0x2b,
183 TUNER_AUD_ANA_STD = 0x2c,
184 TUNER_CUSTOM_PARAMETER = 0x2f,
185
186 DVBT_TUNE_MODE_SEL = 0x30,
187 DVBT_BANDW_CAP = 0x31,
188 DVBT_BANDW_SEL = 0x32,
189 DVBT_GUARD_INTERV_CAP = 0x33,
190 DVBT_GUARD_INTERV_SEL = 0x34,
191 DVBT_MODULATION_CAP = 0x35,
192 DVBT_MODULATION_SEL = 0x36,
193 DVBT_INNER_FEC_RATE_CAP = 0x37,
194 DVBT_INNER_FEC_RATE_SEL = 0x38,
195 DVBT_TRANS_MODE_CAP = 0x39,
196 DVBT_TRANS_MODE_SEL = 0x3a,
197 DVBT_SEARCH_RANG = 0x3c,
198
199 TUNER_SETUP_ANALOG = 0x40,
200 TUNER_SETUP_DIGITAL = 0x41,
201 TUNER_SETUP_FM_RADIO = 0x42,
202 TAKE_REQUEST = 0x43, /* Take effect of the command */
203 PLAY_SERVICE = 0x44, /* Play start or Play stop */
204 TUNER_STATUS = 0x45,
205 TUNE_PROP_DVBT = 0x46,
206 ERR_RATE_STATS = 0x47,
207 TUNER_BER_RATE = 0x48,
208
209 SCAN_CAPS = 0x50,
210 SCAN_SETUP = 0x51,
211 SCAN_SERVICE = 0x52,
212 SCAN_STATS = 0x53,
213
214 PID_SET = 0x58,
215 PID_UNSET = 0x59,
216 PID_LIST = 0x5a,
217
218 IRD_CAP = 0x60,
219 IRD_MODE_SEL = 0x61,
220 IRD_SETUP = 0x62,
221
222 PTM_MODE_CAP = 0x70,
223 PTM_MODE_SEL = 0x71,
224 PTM_SERVICE = 0x72,
225 TUNER_REG_SCRIPT = 0x73,
226 CMD_CHIP_RST = 0x74,
227};
228
229enum tlg_bw {
230 TLG_BW_5 = 5,
231 TLG_BW_6 = 6,
232 TLG_BW_7 = 7,
233 TLG_BW_8 = 8,
234 TLG_BW_12 = 12,
235 TLG_BW_15 = 15
236};
237
238struct cmd_firmware_vers_s {
239 uint8_t fw_rev_major;
240 uint8_t fw_rev_minor;
241 uint16_t fw_patch;
242};
243#endif /* VENDOR_CMD_H_ */