1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
|
/*
* tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices
*
* Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
*
* Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
* - DVB-T support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/videobuf-vmalloc.h>
#include "tm6000-usb-isoc.h"
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h>
#include <linux/dvb/frontend.h>
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dmxdev.h"
/* Inputs */
enum tm6000_itype {
TM6000_INPUT_TV = 1,
TM6000_INPUT_COMPOSITE1,
TM6000_INPUT_COMPOSITE2,
TM6000_INPUT_SVIDEO,
TM6000_INPUT_DVB,
TM6000_INPUT_RADIO,
};
enum tm6000_mux {
TM6000_VMUX_VIDEO_A = 1,
TM6000_VMUX_VIDEO_B,
TM6000_VMUX_VIDEO_AB,
TM6000_AMUX_ADC1,
TM6000_AMUX_ADC2,
TM6000_AMUX_SIF1,
TM6000_AMUX_SIF2,
TM6000_AMUX_I2S,
};
enum tm6000_devtype {
TM6000 = 0,
TM5600,
TM6010,
};
struct tm6000_input {
enum tm6000_itype type;
enum tm6000_mux vmux;
enum tm6000_mux amux;
unsigned int v_gpio;
unsigned int a_gpio;
};
/* ------------------------------------------------------------------
* Basic structures
* ------------------------------------------------------------------
*/
struct tm6000_fmt {
char *name;
u32 fourcc; /* v4l2 format id */
int depth;
};
/* buffer for one video frame */
struct tm6000_buffer {
/* common v4l buffer stuff -- must be first */
struct videobuf_buffer vb;
struct tm6000_fmt *fmt;
};
struct tm6000_dmaqueue {
struct list_head active;
struct list_head queued;
/* thread for generating video stream*/
struct task_struct *kthread;
wait_queue_head_t wq;
/* Counters to control fps rate */
int frame;
int ini_jiffies;
};
/* device states */
enum tm6000_core_state {
DEV_INITIALIZED = 0x01,
DEV_DISCONNECTED = 0x02,
DEV_MISCONFIGURED = 0x04,
};
/* io methods */
enum tm6000_io_method {
IO_NONE,
IO_READ,
IO_MMAP,
};
enum tm6000_mode {
TM6000_MODE_UNKNOWN = 0,
TM6000_MODE_ANALOG,
TM6000_MODE_DIGITAL,
};
struct tm6000_gpio {
int tuner_reset;
int tuner_on;
int demod_reset;
int demod_on;
int power_led;
int dvb_led;
int ir;
};
struct tm6000_capabilities {
unsigned int has_tuner:1;
unsigned int has_tda9874:1;
unsigned int has_dvb:1;
unsigned int has_zl10353:1;
unsigned int has_eeprom:1;
unsigned int has_remote:1;
unsigned int has_radio:1;
};
struct tm6000_dvb {
struct dvb_adapter adapter;
struct dvb_demux demux;
struct dvb_frontend *frontend;
struct dmxdev dmxdev;
unsigned int streams;
struct urb *bulk_urb;
struct mutex mutex;
};
struct snd_tm6000_card {
struct snd_card *card;
spinlock_t reg_lock;
struct tm6000_core *core;
struct snd_pcm_substream *substream;
/* temporary data for buffer fill processing */
unsigned buf_pos;
unsigned period_pos;
};
struct tm6000_endpoint {
struct usb_host_endpoint *endp;
__u8 bInterfaceNumber;
__u8 bAlternateSetting;
unsigned maxsize;
};
#define TM6000_QUIRK_NO_USB_DELAY (1 << 0)
struct tm6000_core {
/* generic device properties */
char name[30]; /* name (including minor) of the device */
int model; /* index in the device_data struct */
int devno; /* marks the number of this device */
enum tm6000_devtype dev_type; /* type of device */
unsigned char eedata[256]; /* Eeprom data */
unsigned eedata_size; /* Size of the eeprom info */
v4l2_std_id norm; /* Current norm */
int width, height; /* Selected resolution */
enum tm6000_core_state state;
/* Device Capabilities*/
struct tm6000_capabilities caps;
/* Used to load alsa/dvb */
struct work_struct request_module_wk;
/* Tuner configuration */
int tuner_type; /* type of the tuner */
int tuner_addr; /* tuner address */
struct tm6000_gpio gpio;
char *ir_codes;
__u8 radio;
/* Demodulator configuration */
int demod_addr; /* demodulator address */
int audio_bitrate;
/* i2c i/o */
struct i2c_adapter i2c_adap;
struct i2c_client i2c_client;
/* extension */
struct list_head devlist;
/* video for linux */
int users;
/* various device info */
struct tm6000_fh *resources; /* Points to fh that is streaming */
bool is_res_read;
struct video_device *vfd;
struct video_device *radio_dev;
struct tm6000_dmaqueue vidq;
struct v4l2_device v4l2_dev;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl_handler radio_ctrl_handler;
int input;
struct tm6000_input vinput[3]; /* video input */
struct tm6000_input rinput; /* radio input */
int freq;
unsigned int fourcc;
enum tm6000_mode mode;
int ctl_mute; /* audio */
int ctl_volume;
int amode;
/* DVB-T support */
struct tm6000_dvb *dvb;
/* audio support */
struct snd_tm6000_card *adev;
struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */
atomic_t stream_started; /* stream should be running if true */
struct tm6000_IR *ir;
/* locks */
struct mutex lock;
struct mutex usb_lock;
/* usb transfer */
struct usb_device *udev; /* the usb device */
struct tm6000_endpoint bulk_in, bulk_out, isoc_in, isoc_out;
struct tm6000_endpoint int_in, int_out;
/* scaler!=0 if scaler is active*/
int scaler;
/* Isoc control struct */
struct usb_isoc_ctl isoc_ctl;
spinlock_t slock;
/* urb dma buffers */
char **urb_buffer;
dma_addr_t *urb_dma;
unsigned int urb_size;
unsigned long quirks;
};
enum tm6000_ops_type {
TM6000_AUDIO = 0x10,
TM6000_DVB = 0x20,
};
struct tm6000_ops {
struct list_head next;
char *name;
enum tm6000_ops_type type;
int (*init)(struct tm6000_core *);
int (*fini)(struct tm6000_core *);
int (*fillbuf)(struct tm6000_core *, char *buf, int size);
};
struct tm6000_fh {
struct v4l2_fh fh;
struct tm6000_core *dev;
unsigned int radio;
/* video capture */
struct tm6000_fmt *fmt;
unsigned int width, height;
struct videobuf_queue vb_vidq;
enum v4l2_buf_type type;
};
#define TM6000_STD (V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc| \
V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \
V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM)
/* In tm6000-cards.c */
int tm6000_tuner_callback(void *ptr, int component, int command, int arg);
int tm6000_xc5000_callback(void *ptr, int component, int command, int arg);
int tm6000_cards_setup(struct tm6000_core *dev);
void tm6000_flash_led(struct tm6000_core *dev, u8 state);
/* In tm6000-core.c */
int tm6000_read_write_usb(struct tm6000_core *dev, u8 reqtype, u8 req,
u16 value, u16 index, u8 *buf, u16 len);
int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index);
int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index);
int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
u16 index, u16 mask);
int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
int tm6000_init(struct tm6000_core *dev);
int tm6000_reset(struct tm6000_core *dev);
int tm6000_init_analog_mode(struct tm6000_core *dev);
int tm6000_init_digital_mode(struct tm6000_core *dev);
int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate);
int tm6000_set_audio_rinput(struct tm6000_core *dev);
int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute);
void tm6000_set_volume(struct tm6000_core *dev, int vol);
int tm6000_v4l2_register(struct tm6000_core *dev);
int tm6000_v4l2_unregister(struct tm6000_core *dev);
int tm6000_v4l2_exit(void);
void tm6000_set_fourcc_format(struct tm6000_core *dev);
void tm6000_remove_from_devlist(struct tm6000_core *dev);
void tm6000_add_into_devlist(struct tm6000_core *dev);
int tm6000_register_extension(struct tm6000_ops *ops);
void tm6000_unregister_extension(struct tm6000_ops *ops);
void tm6000_init_extension(struct tm6000_core *dev);
void tm6000_close_extension(struct tm6000_core *dev);
int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
char *buf, int size);
/* In tm6000-stds.c */
void tm6000_get_std_res(struct tm6000_core *dev);
int tm6000_set_standard(struct tm6000_core *dev);
/* In tm6000-i2c.c */
int tm6000_i2c_register(struct tm6000_core *dev);
int tm6000_i2c_unregister(struct tm6000_core *dev);
/* In tm6000-queue.c */
int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma);
int tm6000_vidioc_streamon(struct file *file, void *priv,
enum v4l2_buf_type i);
int tm6000_vidioc_streamoff(struct file *file, void *priv,
enum v4l2_buf_type i);
int tm6000_vidioc_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *rb);
int tm6000_vidioc_querybuf(struct file *file, void *priv,
struct v4l2_buffer *b);
int tm6000_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b);
int tm6000_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b);
ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count,
loff_t *f_pos);
unsigned int tm6000_v4l2_poll(struct file *file,
struct poll_table_struct *wait);
int tm6000_queue_init(struct tm6000_core *dev);
/* In tm6000-alsa.c */
/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
/* In tm6000-input.c */
int tm6000_ir_init(struct tm6000_core *dev);
int tm6000_ir_fini(struct tm6000_core *dev);
void tm6000_ir_wait(struct tm6000_core *dev, u8 state);
int tm6000_ir_int_start(struct tm6000_core *dev);
void tm6000_ir_int_stop(struct tm6000_core *dev);
/* Debug stuff */
extern int tm6000_debug;
#define dprintk(dev, level, fmt, arg...) do {\
if (tm6000_debug & level) \
printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \
dev->name, __func__ , ##arg); } while (0)
#define V4L2_DEBUG_REG 0x0004
#define V4L2_DEBUG_I2C 0x0008
#define V4L2_DEBUG_QUEUE 0x0010
#define V4L2_DEBUG_ISOC 0x0020
#define V4L2_DEBUG_RES_LOCK 0x0040 /* Resource locking */
#define V4L2_DEBUG_OPEN 0x0080 /* video open/close debug */
#define tm6000_err(fmt, arg...) do {\
printk(KERN_ERR "tm6000 %s :"fmt, \
__func__ , ##arg); } while (0)
|