V4L/DVB (5914): Add initial support for Dual-DVB-T stick
[linux-2.6.git] / drivers / media / dvb / dvb-usb / dib0700_devices.c
1 /* Linux driver for devices based on the DiBcom DiB0700 USB bridge
2  *
3  *      This program is free software; you can redistribute it and/or modify it
4  *      under the terms of the GNU General Public License as published by the Free
5  *      Software Foundation, version 2.
6  *
7  *  Copyright (C) 2005-6 DiBcom, SA
8  */
9 #include "dib0700.h"
10
11 #include "dib3000mc.h"
12 #include "dib7000m.h"
13 #include "dib7000p.h"
14 #include "mt2060.h"
15 #include "mt2266.h"
16
17 static int force_lna_activation;
18 module_param(force_lna_activation, int, 0644);
19 MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), "
20                 "if applicable for the device (default: 0=automatic/off).");
21
22 /* Hauppauge Nova-T 500
23  *  has a LNA on GPIO0 which is enabled by setting 1 */
24 static struct mt2060_config bristol_mt2060_config[2] = {
25         {
26                 .i2c_address = 0x60,
27                 .clock_out   = 3,
28         }, {
29                 .i2c_address = 0x61,
30         }
31 };
32
33 static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = {
34         .band_caps = BAND_VHF | BAND_UHF,
35         .setup     = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0),
36
37         .agc1_max = 42598,
38         .agc1_min = 17694,
39         .agc2_max = 45875,
40         .agc2_min = 0,
41
42         .agc1_pt1 = 0,
43         .agc1_pt2 = 59,
44
45         .agc1_slope1 = 0,
46         .agc1_slope2 = 69,
47
48         .agc2_pt1 = 0,
49         .agc2_pt2 = 59,
50
51         .agc2_slope1 = 111,
52         .agc2_slope2 = 28,
53 };
54
55 static struct dib3000mc_config bristol_dib3000mc_config[2] = {
56         {       .agc          = &bristol_dib3000p_mt2060_agc_config,
57                 .max_time     = 0x196,
58                 .ln_adc_level = 0x1cc7,
59                 .output_mpeg2_in_188_bytes = 1,
60         },
61         {       .agc          = &bristol_dib3000p_mt2060_agc_config,
62                 .max_time     = 0x196,
63                 .ln_adc_level = 0x1cc7,
64                 .output_mpeg2_in_188_bytes = 1,
65         }
66 };
67
68 static int bristol_frontend_attach(struct dvb_usb_adapter *adap)
69 {
70         struct dib0700_state *st = adap->dev->priv;
71         if (adap->id == 0) {
72                 dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0); msleep(10);
73                 dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1); msleep(10);
74                 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
75                 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10);
76
77                 if (force_lna_activation)
78                         dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
79                 else
80                         dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0);
81
82                 if (dib3000mc_i2c_enumeration(&adap->dev->i2c_adap, 2, DEFAULT_DIB3000P_I2C_ADDRESS, bristol_dib3000mc_config) != 0) {
83                         dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
84                         return -ENODEV;
85                 }
86         }
87         st->mt2060_if1[adap->id] = 1220;
88         return (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
89                 (10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
90 }
91
92 static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
93 {
94         struct dib0700_state *st = adap->dev->priv;
95         struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
96         return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &bristol_mt2060_config[adap->id],
97                 st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0;
98 }
99
100 /* STK7700D: Pinnacle Dual DVB-T Diversity */
101
102 static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config = {
103         BAND_UHF/* | BAND_VHF*/,
104         0xE64, // setup
105         2372, // inv_gain
106         21,  // time_stabiliz
107
108         0,   // alpha_level
109         118, // thlock
110
111         0,    // wbd_inv
112         0,    // wbd_ref
113         0,    // wbd_sel
114         0,    // wbd_alpha
115
116         65535, // agc1_max
117         0,     // agc1_min
118         65535, // agc2_max
119         23592, // agc2_min
120         0,     // agc1_pt1
121         128,   // agc1_pt2
122         128,   // agc1_pt3
123         128,   // agc1_slope1
124         0,     // agc1_slope2
125         128,   // agc2_pt1
126         253,   // agc2_pt2
127         81,    // agc2_slope1
128          0,    // agc2_slope2
129
130         17, // alpha_mant
131         27, // alpha_exp
132
133         23, // beta_mant
134         51, // beta_exp
135
136         0, // perform_agc_softsplit : 1 en vrai!
137 };
138
139 static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = {
140         60000, 30000, // internal, sampling
141         1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
142         0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
143         (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
144         0, // ifreq
145         20452225, // timf
146 };
147
148 static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = {
149         {       .output_mpeg2_in_188_bytes = 1,
150                 .hostbus_diversity = 1,
151                 .tuner_is_baseband = 1,
152
153                 .agc = &stk7700d_7000p_mt2266_agc_config,
154                 .bw  = &stk7700d_mt2266_pll_config,
155
156                 .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
157                 .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
158                 .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
159         },
160         {       .output_mpeg2_in_188_bytes = 1,
161                 .hostbus_diversity = 1,
162                 .tuner_is_baseband = 1,
163
164                 .agc = &stk7700d_7000p_mt2266_agc_config,
165                 .bw  = &stk7700d_mt2266_pll_config,
166
167                 .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
168                 .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
169                 .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
170         }
171 };
172
173 static struct mt2266_config stk7700d_mt2266_config[2] = {
174         {       .i2c_address = 0x60
175         },
176         {       .i2c_address = 0x60
177         }
178 };
179
180 static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
181 {
182         if (adap->id == 0) {
183                 dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
184                 msleep(10);
185                 dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
186                 dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
187                 dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
188                 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
189                 msleep(10);
190                 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
191                 msleep(10);
192                 dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
193                 dib7000p_i2c_enumeration(&adap->dev->i2c_adap,2,18,stk7700d_dib7000p_mt2266_config);
194         }
195
196         adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
197                                 &stk7700d_dib7000p_mt2266_config[adap->id]);
198
199         return adap->fe == NULL ? -ENODEV : 0;
200 }
201
202 static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
203 {
204         struct i2c_adapter *tun_i2c;
205         tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
206         return dvb_attach(mt2266_attach, adap->fe, tun_i2c,
207                 &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;;
208 }
209
210 #define DEFAULT_RC_INTERVAL 150
211
212 static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
213
214 int stk7700d_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
215 {
216         u8 key[4];
217         int i;
218         struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
219         struct dib0700_state *st = d->priv;
220         *event = 0;
221         *state = REMOTE_NO_KEY_PRESSED;
222         i=dib0700_ctrl_rd(d,rc_request,2,key,4);
223         if (i<=0) {
224                 err("stk7700d:RC Query Failed\n");
225                 return 0;
226         }
227         if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
228         if (key[1]!=st->rc_toggle) {
229                 for (i=0;i<d->props.rc_key_map_size; i++) {
230                         if (keymap[i].custom == key[2] && keymap[i].data == key[3]) {
231                                 *event = keymap[i].event;
232                                 *state = REMOTE_KEY_PRESSED;
233                                 st->rc_toggle=key[1];
234                                 return 0;
235                         }
236                 }
237                 err("stk7700d:Unknown remote controller key : %2X %2X\n",(int)key[2],(int)key[3]);
238         }
239         return 0;
240 }
241
242 #define KEY_MAP_SIZE (25+48)
243
244 struct dvb_usb_rc_key stk7700d_rc_keys[] = {
245         /* Key codes for the tiny Pinnacle remote*/
246         { 0x07, 0x00, KEY_MUTE },
247         { 0x07, 0x01, KEY_MENU }, // Pinnacle logo
248         { 0x07, 0x39, KEY_POWER },
249         { 0x07, 0x03, KEY_VOLUMEUP },
250         { 0x07, 0x09, KEY_VOLUMEDOWN },
251         { 0x07, 0x06, KEY_CHANNELUP },
252         { 0x07, 0x0c, KEY_CHANNELDOWN },
253         { 0x07, 0x0f, KEY_1 },
254         { 0x07, 0x15, KEY_2 },
255         { 0x07, 0x10, KEY_3 },
256         { 0x07, 0x18, KEY_4 },
257         { 0x07, 0x1b, KEY_5 },
258         { 0x07, 0x1e, KEY_6 },
259         { 0x07, 0x11, KEY_7 },
260         { 0x07, 0x21, KEY_8 },
261         { 0x07, 0x12, KEY_9 },
262         { 0x07, 0x27, KEY_0 },
263         { 0x07, 0x24, KEY_SCREEN }, // 'Square' key
264         { 0x07, 0x2a, KEY_TEXT },   // 'T' key
265         { 0x07, 0x2d, KEY_REWIND },
266         { 0x07, 0x30, KEY_PLAY },
267         { 0x07, 0x33, KEY_FASTFORWARD },
268         { 0x07, 0x36, KEY_RECORD },
269         { 0x07, 0x3c, KEY_STOP },
270         { 0x07, 0x3f, KEY_CANCEL }, // '?' key
271         /* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
272         { 0xeb, 0x01, KEY_POWER },
273         { 0xeb, 0x02, KEY_1 },
274         { 0xeb, 0x03, KEY_2 },
275         { 0xeb, 0x04, KEY_3 },
276         { 0xeb, 0x05, KEY_4 },
277         { 0xeb, 0x06, KEY_5 },
278         { 0xeb, 0x07, KEY_6 },
279         { 0xeb, 0x08, KEY_7 },
280         { 0xeb, 0x09, KEY_8 },
281         { 0xeb, 0x0a, KEY_9 },
282         { 0xeb, 0x0b, KEY_VIDEO },
283         { 0xeb, 0x0c, KEY_0 },
284         { 0xeb, 0x0d, KEY_REFRESH },
285         { 0xeb, 0x0f, KEY_EPG },
286         { 0xeb, 0x10, KEY_UP },
287         { 0xeb, 0x11, KEY_LEFT },
288         { 0xeb, 0x12, KEY_OK },
289         { 0xeb, 0x13, KEY_RIGHT },
290         { 0xeb, 0x14, KEY_DOWN },
291         { 0xeb, 0x16, KEY_INFO },
292         { 0xeb, 0x17, KEY_RED },
293         { 0xeb, 0x18, KEY_GREEN },
294         { 0xeb, 0x19, KEY_YELLOW },
295         { 0xeb, 0x1a, KEY_BLUE },
296         { 0xeb, 0x1b, KEY_CHANNELUP },
297         { 0xeb, 0x1c, KEY_VOLUMEUP },
298         { 0xeb, 0x1d, KEY_MUTE  },
299         { 0xeb, 0x1e, KEY_VOLUMEDOWN },
300         { 0xeb, 0x1f, KEY_CHANNELDOWN },
301         { 0xeb, 0x40, KEY_PAUSE },
302         { 0xeb, 0x41, KEY_HOME },
303         { 0xeb, 0x42, KEY_MENU }, /* DVD Menu */
304         { 0xeb, 0x43, KEY_SUBTITLE },
305         { 0xeb, 0x44, KEY_TEXT }, /* Teletext */
306         { 0xeb, 0x45, KEY_DELETE },
307         { 0xeb, 0x46, KEY_TV },
308         { 0xeb, 0x47, KEY_DVD },
309         { 0xeb, 0x48, KEY_STOP },
310         { 0xeb, 0x49, KEY_VIDEO },
311         { 0xeb, 0x4a, KEY_AUDIO }, /* Music */
312         { 0xeb, 0x4b, KEY_SCREEN }, /* Pic */
313         { 0xeb, 0x4c, KEY_PLAY },
314         { 0xeb, 0x4d, KEY_BACK },
315         { 0xeb, 0x4e, KEY_REWIND },
316         { 0xeb, 0x4f, KEY_FASTFORWARD },
317         { 0xeb, 0x54, KEY_PREVIOUS },
318         { 0xeb, 0x58, KEY_RECORD },
319         { 0xeb, 0x5c, KEY_NEXT }
320         };
321
322 /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
323 static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
324         BAND_UHF | BAND_VHF,       // band_caps
325
326         /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
327          * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
328         (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
329
330         712,  // inv_gain
331         41,  // time_stabiliz
332
333         0,  // alpha_level
334         118,  // thlock
335
336         0,     // wbd_inv
337         4095,  // wbd_ref
338         0,     // wbd_sel
339         0,     // wbd_alpha
340
341         42598,  // agc1_max
342         17694,  // agc1_min
343         45875,  // agc2_max
344         2621,  // agc2_min
345         0,  // agc1_pt1
346         76,  // agc1_pt2
347         139,  // agc1_pt3
348         52,  // agc1_slope1
349         59,  // agc1_slope2
350         107,  // agc2_pt1
351         172,  // agc2_pt2
352         57,  // agc2_slope1
353         70,  // agc2_slope2
354
355         21,  // alpha_mant
356         25,  // alpha_exp
357         28,  // beta_mant
358         48,  // beta_exp
359
360         1,  // perform_agc_softsplit
361         {  0,     // split_min
362            107,   // split_max
363            51800, // global_split_min
364            24700  // global_split_max
365         },
366 };
367
368 static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = {
369         BAND_UHF | BAND_VHF,
370
371         /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
372          * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
373         (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
374
375         712, // inv_gain
376         41,  // time_stabiliz
377
378         0,   // alpha_level
379         118, // thlock
380
381         0,    // wbd_inv
382         4095, // wbd_ref
383         0,    // wbd_sel
384         0,    // wbd_alpha
385
386         42598, // agc1_max
387         16384, // agc1_min
388         42598, // agc2_max
389             0, // agc2_min
390
391           0,   // agc1_pt1
392         137,   // agc1_pt2
393         255,   // agc1_pt3
394
395           0,   // agc1_slope1
396         255,   // agc1_slope2
397
398         0,     // agc2_pt1
399         0,     // agc2_pt2
400
401          0,    // agc2_slope1
402         41,    // agc2_slope2
403
404         15, // alpha_mant
405         25, // alpha_exp
406
407         28, // beta_mant
408         48, // beta_exp
409
410         0, // perform_agc_softsplit
411 };
412
413 static struct dibx000_bandwidth_config stk7700p_pll_config = {
414         60000, 30000, // internal, sampling
415         1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
416         0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
417         (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
418         60258167, // ifreq
419         20452225, // timf
420 };
421
422 static struct dib7000m_config stk7700p_dib7000m_config = {
423         .dvbt_mode = 1,
424         .output_mpeg2_in_188_bytes = 1,
425         .quartz_direct = 1,
426
427         .agc_config_count = 1,
428         .agc = &stk7700p_7000m_mt2060_agc_config,
429         .bw  = &stk7700p_pll_config,
430
431         .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
432         .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
433         .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
434 };
435
436 static struct dib7000p_config stk7700p_dib7000p_config = {
437         .output_mpeg2_in_188_bytes = 1,
438
439         .agc = &stk7700p_7000p_mt2060_agc_config,
440         .bw  = &stk7700p_pll_config,
441
442         .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
443         .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
444         .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
445 };
446
447 static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
448 {
449         struct dib0700_state *st = adap->dev->priv;
450         /* unless there is no real power management in DVB - we leave the device on GPIO6 */
451
452         dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
453         dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0); msleep(50);
454
455         dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1); msleep(10);
456         dib0700_set_gpio(adap->dev, GPIO9,  GPIO_OUT, 1);
457
458         dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
459         dib0700_ctrl_clock(adap->dev, 72, 1);
460         dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100);
461
462         dib0700_set_gpio(adap->dev,  GPIO0, GPIO_OUT, 1);
463
464         st->mt2060_if1[0] = 1220;
465
466         if (dib7000pc_detection(&adap->dev->i2c_adap)) {
467                 adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
468                 st->is_dib7000pc = 1;
469         } else
470                 adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
471
472         return adap->fe == NULL ? -ENODEV : 0;
473 }
474
475 static struct mt2060_config stk7700p_mt2060_config = {
476         0x60
477 };
478
479 static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
480 {
481         struct dib0700_state *st = adap->dev->priv;
482         struct i2c_adapter *tun_i2c;
483
484         if (st->is_dib7000pc)
485                 tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
486         else
487                 tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
488
489         return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
490                 st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
491 }
492
493 struct usb_device_id dib0700_usb_id_table[] = {
494                 { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P) },
495                 { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
496
497                 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
498                 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
499                 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
500                 { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
501                 { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
502                 { USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
503                 { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
504                 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
505                 { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
506                 { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV2000E) },
507                 { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
508                 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
509                 { }             /* Terminating entry */
510 };
511 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
512
513 #define DIB0700_DEFAULT_DEVICE_PROPERTIES \
514         .caps              = DVB_USB_IS_AN_I2C_ADAPTER, \
515         .usb_ctrl          = DEVICE_SPECIFIC, \
516         .firmware          = "dvb-usb-dib0700-01.fw", \
517         .download_firmware = dib0700_download_firmware, \
518         .no_reconnect      = 1, \
519         .size_of_priv      = sizeof(struct dib0700_state), \
520         .i2c_algo          = &dib0700_i2c_algo, \
521         .identify_state    = dib0700_identify_state
522
523 #define DIB0700_DEFAULT_STREAMING_CONFIG(ep) \
524         .streaming_ctrl   = dib0700_streaming_ctrl, \
525         .stream = { \
526                 .type = USB_BULK, \
527                 .count = 4, \
528                 .endpoint = ep, \
529                 .u = { \
530                         .bulk = { \
531                                 .buffersize = 39480, \
532                         } \
533                 } \
534         }
535
536 struct dvb_usb_device_properties dib0700_devices[] = {
537         {
538                 DIB0700_DEFAULT_DEVICE_PROPERTIES,
539
540                 .num_adapters = 1,
541                 .adapter = {
542                         {
543                                 .frontend_attach  = stk7700p_frontend_attach,
544                                 .tuner_attach     = stk7700p_tuner_attach,
545
546                                 DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
547                         },
548                 },
549
550                 .num_device_descs = 6,
551                 .devices = {
552                         {   "DiBcom STK7700P reference design",
553                                 { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
554                                 { NULL },
555                         },
556                         {   "Hauppauge Nova-T Stick",
557                                 { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL },
558                                 { NULL },
559                         },
560                         {   "AVerMedia AVerTV DVB-T Volar",
561                                 { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] },
562                                 { NULL },
563                         },
564                         {   "Compro Videomate U500",
565                                 { &dib0700_usb_id_table[6], NULL },
566                                 { NULL },
567                         },
568                         {   "Uniwill STK7700P based (Hama and others)",
569                                 { &dib0700_usb_id_table[7], NULL },
570                                 { NULL },
571                         },
572                         {   "Leadtek Winfast DTV Dongle (STK7700P based)",
573                                 { &dib0700_usb_id_table[8], NULL },
574                                 { NULL },
575                         }
576                 }
577         }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
578
579                 .num_adapters = 2,
580                 .adapter = {
581                         {
582                                 .frontend_attach  = bristol_frontend_attach,
583                                 .tuner_attach     = bristol_tuner_attach,
584
585                                 DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
586                         }, {
587                                 .frontend_attach  = bristol_frontend_attach,
588                                 .tuner_attach     = bristol_tuner_attach,
589
590                                 DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
591                         }
592                 },
593
594                 .num_device_descs = 1,
595                 .devices = {
596                         {   "Hauppauge Nova-T 500 Dual DVB-T",
597                                 { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL },
598                                 { NULL },
599                         },
600                 }
601         }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
602
603                 .num_adapters = 2,
604                 .adapter = {
605                         {
606                                 .frontend_attach  = stk7700d_frontend_attach,
607                                 .tuner_attach     = stk7700d_tuner_attach,
608
609                                 DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
610                         }, {
611                                 .frontend_attach  = stk7700d_frontend_attach,
612                                 .tuner_attach     = stk7700d_tuner_attach,
613
614                                 DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
615                         }
616                 },
617
618                 .num_device_descs = 3,
619                 .devices = {
620                         {   "Pinnacle PCTV 2000e",
621                                 { &dib0700_usb_id_table[11], NULL },
622                                 { NULL },
623                         },
624                         {   "Terratec Cinergy DT XS Diversity",
625                                 { &dib0700_usb_id_table[12], NULL },
626                                 { NULL },
627                         },
628                         {   "Haupauge Nova-TD Stick",
629                                 { &dib0700_usb_id_table[13], NULL },
630                                 { NULL },
631                         },
632                 },
633                 .rc_interval      = DEFAULT_RC_INTERVAL,
634                 .rc_key_map       = stk7700d_rc_keys,
635                 .rc_key_map_size  = KEY_MAP_SIZE,
636                 .rc_query         = stk7700d_rc_query
637         }
638 };
639
640 int dib0700_device_count = ARRAY_SIZE(dib0700_devices);