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 16static int force_lna_activation; 17module_param(force_lna_activation, int, 0644); 18MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), " 19 "if applicable for the device (default: 0=automatic/off)."); 20 21/* Hauppauge Nova-T 500 22 * has a LNA on GPIO0 which is enabled by setting 1 */ 23static struct mt2060_config bristol_mt2060_config[2] = { 24 { 25 .i2c_address = 0x60, 26 .clock_out = 3, 27 }, { 28 .i2c_address = 0x61, 29 } 30}; 31 32static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = { 33 .band_caps = BAND_VHF | BAND_UHF, 34 .setup = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0), 35 36 .agc1_max = 42598, 37 .agc1_min = 17694, 38 .agc2_max = 45875, 39 .agc2_min = 0, 40 41 .agc1_pt1 = 0, 42 .agc1_pt2 = 59, 43 44 .agc1_slope1 = 0, 45 .agc1_slope2 = 69, 46 47 .agc2_pt1 = 0, 48 .agc2_pt2 = 59, 49 50 .agc2_slope1 = 111, 51 .agc2_slope2 = 28, 52}; 53 54static struct dib3000mc_config bristol_dib3000mc_config[2] = { 55 { .agc = &bristol_dib3000p_mt2060_agc_config, 56 .max_time = 0x196, 57 .ln_adc_level = 0x1cc7, 58 .output_mpeg2_in_188_bytes = 1, 59 }, 60 { .agc = &bristol_dib3000p_mt2060_agc_config, 61 .max_time = 0x196, 62 .ln_adc_level = 0x1cc7, 63 .output_mpeg2_in_188_bytes = 1, 64 } 65}; 66 67static int bristol_frontend_attach(struct dvb_usb_adapter *adap) 68{ 69 struct dib0700_state *st = adap->dev->priv; 70 if (adap->id == 0) { 71 dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); 72 dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); 73 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); 74 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); 75 76 if (force_lna_activation) 77 dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); 78 else 79 dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0); 80 81 if (dib3000mc_i2c_enumeration(&adap->dev->i2c_adap, 2, DEFAULT_DIB3000P_I2C_ADDRESS, bristol_dib3000mc_config) != 0) { 82 dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); 83 return -ENODEV; 84 } 85 } 86 st->mt2060_if1[adap->id] = 1220; 87 return (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, 88 (10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0; 89} 90 91static int bristol_tuner_attach(struct dvb_usb_adapter *adap) 92{ 93 struct dib0700_state *st = adap->dev->priv; 94 struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1); 95 return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &bristol_mt2060_config[adap->id], 96 st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0; 97} 98 99/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ 100static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { 101 BAND_UHF | BAND_VHF, // band_caps 102 103 /* 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, 104 * 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 */ 105 (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup 106 107 712, // inv_gain 108 41, // time_stabiliz 109 110 0, // alpha_level 111 118, // thlock 112 113 0, // wbd_inv 114 4095, // wbd_ref 115 0, // wbd_sel 116 0, // wbd_alpha 117 118 42598, // agc1_max 119 17694, // agc1_min 120 45875, // agc2_max 121 2621, // agc2_min 122 0, // agc1_pt1 123 76, // agc1_pt2 124 139, // agc1_pt3 125 52, // agc1_slope1 126 59, // agc1_slope2 127 107, // agc2_pt1 128 172, // agc2_pt2 129 57, // agc2_slope1 130 70, // agc2_slope2 131 132 21, // alpha_mant 133 25, // alpha_exp 134 28, // beta_mant 135 48, // beta_exp 136 137 1, // perform_agc_softsplit 138 { 0, // split_min 139 107, // split_max 140 51800, // global_split_min 141 24700 // global_split_max 142 }, 143}; 144 145static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = { 146 BAND_UHF | BAND_VHF, 147 148 /* 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, 149 * 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 */ 150 (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup 151 152 712, // inv_gain 153 41, // time_stabiliz 154 155 0, // alpha_level 156 118, // thlock 157 158 0, // wbd_inv 159 4095, // wbd_ref 160 0, // wbd_sel 161 0, // wbd_alpha 162 163 42598, // agc1_max 164 16384, // agc1_min 165 42598, // agc2_max 166 0, // agc2_min 167 168 0, // agc1_pt1 169 137, // agc1_pt2 170 255, // agc1_pt3 171 172 0, // agc1_slope1 173 255, // agc1_slope2 174 175 0, // agc2_pt1 176 0, // agc2_pt2 177 178 0, // agc2_slope1 179 41, // agc2_slope2 180 181 15, // alpha_mant 182 25, // alpha_exp 183 184 28, // beta_mant 185 48, // beta_exp 186 187 0, // perform_agc_softsplit 188}; 189 190static struct dibx000_bandwidth_config stk7700p_pll_config = { 191 60000, 30000, // internal, sampling 192 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass 193 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo 194 (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k 195 60258167, // ifreq 196 20452225, // timf 197}; 198 199static struct dib7000m_config stk7700p_dib7000m_config = { 200 .dvbt_mode = 1, 201 .output_mpeg2_in_188_bytes = 1, 202 .quartz_direct = 1, 203 204 .agc_config_count = 1, 205 .agc = &stk7700p_7000m_mt2060_agc_config, 206 .bw = &stk7700p_pll_config, 207 208 .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, 209 .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, 210 .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, 211}; 212 213static struct dib7000p_config stk7700p_dib7000p_config = { 214 .output_mpeg2_in_188_bytes = 1, 215 216 .agc = &stk7700p_7000p_mt2060_agc_config, 217 .bw = &stk7700p_pll_config, 218 219 .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, 220 .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, 221 .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, 222}; 223 224static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) 225{ 226 struct dib0700_state *st = adap->dev->priv; 227 /* unless there is no real power management in DVB - we leave the device on GPIO6 */ 228 229 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); 230 dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50); 231 232 dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); 233 dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); 234 235 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); 236 dib0700_ctrl_clock(adap->dev, 72, 1); 237 dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100); 238 239 dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); 240 241 st->mt2060_if1[0] = 1220; 242 243 if (dib7000pc_detection(&adap->dev->i2c_adap)) { 244 adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config); 245 st->is_dib7000pc = 1; 246 } else 247 adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config); 248 249 return adap->fe == NULL ? -ENODEV : 0; 250} 251 252static struct mt2060_config stk7700p_mt2060_config = { 253 0x60 254}; 255 256static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) 257{ 258 struct dib0700_state *st = adap->dev->priv; 259 struct i2c_adapter *tun_i2c; 260 261 if (st->is_dib7000pc) 262 tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); 263 else 264 tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); 265 266 return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config, 267 st->mt2060_if1[0]) == NULL ? -ENODEV : 0; 268} 269 270struct usb_device_id dib0700_usb_id_table[] = { 271 { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, 272 { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, 273 274 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, 275 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, 276 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, 277 { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, 278 { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, 279 { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, 280 { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, 281 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, 282 { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, 283 { } /* Terminating entry */ 284}; 285MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); 286 287#define DIB0700_DEFAULT_DEVICE_PROPERTIES \ 288 .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ 289 .usb_ctrl = DEVICE_SPECIFIC, \ 290 .firmware = "dvb-usb-dib0700-01.fw", \ 291 .download_firmware = dib0700_download_firmware, \ 292 .no_reconnect = 1, \ 293 .size_of_priv = sizeof(struct dib0700_state), \ 294 .i2c_algo = &dib0700_i2c_algo, \ 295 .identify_state = dib0700_identify_state 296 297#define DIB0700_DEFAULT_STREAMING_CONFIG(ep) \ 298 .streaming_ctrl = dib0700_streaming_ctrl, \ 299 .stream = { \ 300 .type = USB_BULK, \ 301 .count = 4, \ 302 .endpoint = ep, \ 303 .u = { \ 304 .bulk = { \ 305 .buffersize = 39480, \ 306 } \ 307 } \ 308 } 309 310struct dvb_usb_device_properties dib0700_devices[] = { 311 { 312 DIB0700_DEFAULT_DEVICE_PROPERTIES, 313 314 .num_adapters = 1, 315 .adapter = { 316 { 317 .frontend_attach = stk7700p_frontend_attach, 318 .tuner_attach = stk7700p_tuner_attach, 319 320 DIB0700_DEFAULT_STREAMING_CONFIG(0x02), 321 }, 322 }, 323 324 .num_device_descs = 6, 325 .devices = { 326 { "DiBcom STK7700P reference design", 327 { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, 328 { NULL }, 329 }, 330 { "Hauppauge Nova-T Stick", 331 { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL }, 332 { NULL }, 333 }, 334 { "AVerMedia AVerTV DVB-T Volar", 335 { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] }, 336 { NULL }, 337 }, 338 { "Compro Videomate U500", 339 { &dib0700_usb_id_table[6], NULL }, 340 { NULL }, 341 }, 342 { "Uniwill STK7700P based (Hama and others)", 343 { &dib0700_usb_id_table[7], NULL }, 344 { NULL }, 345 }, 346 { "Leadtek Winfast DTV Dongle (STK7700P based)", 347 { &dib0700_usb_id_table[8], NULL }, 348 { NULL }, 349 } 350 } 351 }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, 352 353 .num_adapters = 2, 354 .adapter = { 355 { 356 .frontend_attach = bristol_frontend_attach, 357 .tuner_attach = bristol_tuner_attach, 358 359 DIB0700_DEFAULT_STREAMING_CONFIG(0x02), 360 }, { 361 .frontend_attach = bristol_frontend_attach, 362 .tuner_attach = bristol_tuner_attach, 363 364 DIB0700_DEFAULT_STREAMING_CONFIG(0x03), 365 } 366 }, 367 368 .num_device_descs = 1, 369 .devices = { 370 { "Hauppauge Nova-T 500 Dual DVB-T", 371 { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL }, 372 { NULL }, 373 }, 374 } 375 } 376}; 377 378int dib0700_device_count = ARRAY_SIZE(dib0700_devices); 379