1 // SPDX-License-Identifier: GPL-2.0-only 2 /* DVB USB compliant linux driver for mobile DVB-T USB devices based on 3 * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B) 4 * 5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) 6 * 7 * based on GPL code from DiBcom, which has 8 * Copyright (C) 2004 Amaury Demol for DiBcom 9 * 10 * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information 11 */ 12 #include "dibusb.h" 13 14 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 15 16 static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) 17 { 18 struct dvb_usb_adapter *adap = fe->dvb->priv; 19 struct dibusb_state *st = adap->priv; 20 21 return st->ops.tuner_pass_ctrl(fe, enable, st->tuner_addr); 22 } 23 24 static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap) 25 { 26 struct dib3000_config demod_cfg; 27 struct dibusb_state *st = adap->priv; 28 29 demod_cfg.demod_address = 0x8; 30 31 adap->fe_adap[0].fe = dvb_attach(dib3000mb_attach, &demod_cfg, 32 &adap->dev->i2c_adap, &st->ops); 33 if ((adap->fe_adap[0].fe) == NULL) 34 return -ENODEV; 35 36 adap->fe_adap[0].fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl; 37 38 return 0; 39 } 40 41 static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap) 42 { 43 struct dibusb_state *st = adap->priv; 44 45 st->tuner_addr = 0x61; 46 47 dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap, 48 DVB_PLL_TUA6010XS); 49 return 0; 50 } 51 52 static int dibusb_panasonic_tuner_attach(struct dvb_usb_adapter *adap) 53 { 54 struct dibusb_state *st = adap->priv; 55 56 st->tuner_addr = 0x60; 57 58 dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 59 DVB_PLL_TDA665X); 60 return 0; 61 } 62 63 /* Some of the Artec 1.1 device aren't equipped with the default tuner 64 * (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures 65 * this out. */ 66 static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap) 67 { 68 u8 b[2] = { 0,0 }, b2[1]; 69 int ret = 0; 70 struct i2c_msg msg[2] = { 71 { .flags = 0, .buf = b, .len = 2 }, 72 { .flags = I2C_M_RD, .buf = b2, .len = 1 }, 73 }; 74 struct dibusb_state *st = adap->priv; 75 76 /* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */ 77 msg[0].addr = msg[1].addr = st->tuner_addr = 0x60; 78 79 if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) 80 adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); 81 82 if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) { 83 err("tuner i2c write failed."); 84 return -EREMOTEIO; 85 } 86 87 if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) 88 adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); 89 90 if (b2[0] == 0xfe) { 91 info("This device has the Thomson Cable onboard. Which is default."); 92 ret = dibusb_thomson_tuner_attach(adap); 93 } else { 94 info("This device has the Panasonic ENV77H11D5 onboard."); 95 ret = dibusb_panasonic_tuner_attach(adap); 96 } 97 98 return ret; 99 } 100 101 /* USB Driver stuff */ 102 static struct dvb_usb_device_properties dibusb1_1_properties; 103 static struct dvb_usb_device_properties dibusb1_1_an2235_properties; 104 static struct dvb_usb_device_properties dibusb2_0b_properties; 105 static struct dvb_usb_device_properties artec_t1_usb2_properties; 106 107 static int dibusb_probe(struct usb_interface *intf, 108 const struct usb_device_id *id) 109 { 110 if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties, 111 THIS_MODULE, NULL, adapter_nr) || 112 0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties, 113 THIS_MODULE, NULL, adapter_nr) || 114 0 == dvb_usb_device_init(intf, &dibusb2_0b_properties, 115 THIS_MODULE, NULL, adapter_nr) || 116 0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties, 117 THIS_MODULE, NULL, adapter_nr)) 118 return 0; 119 120 return -EINVAL; 121 } 122 123 /* do not change the order of the ID table */ 124 static struct usb_device_id dibusb_dib3000mb_table [] = { 125 /* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD) }, 126 /* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM) }, 127 /* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) }, 128 /* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) }, 129 /* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) }, 130 /* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) }, 131 /* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) }, 132 /* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, 133 /* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, 134 /* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) }, 135 /* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) }, 136 /* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) }, 137 /* 12 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) }, 138 /* 13 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) }, 139 /* 14 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) }, 140 /* 15 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_COLD) }, 141 /* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) }, 142 /* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) }, 143 /* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) }, 144 /* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, 145 /* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, 146 /* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, 147 /* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, 148 /* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) }, 149 150 /* device ID with default DIBUSB2_0-firmware and with the hacked firmware */ 151 /* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) }, 152 /* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) }, 153 /* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) }, 154 155 /* 27 */ { USB_DEVICE(USB_VID_KWORLD, USB_PID_KWORLD_VSTREAM_COLD) }, 156 157 /* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, 158 /* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, 159 160 /* 161 * XXX: As Artec just 'forgot' to program the EEPROM on some Artec T1 devices 162 * we don't catch these faulty IDs (namely 'Cypress FX1 USB controller') that 163 * have been left on the device. If you don't have such a device but an Artec 164 * device that's supposed to work with this driver but is not detected by it, 165 * free to enable CONFIG_DVB_USB_DIBUSB_MB_FAULTY via your kernel config. 166 */ 167 168 #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY 169 /* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, 170 #endif 171 172 { } /* Terminating entry */ 173 }; 174 MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table); 175 176 static struct dvb_usb_device_properties dibusb1_1_properties = { 177 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 178 179 .usb_ctrl = CYPRESS_AN2135, 180 181 .firmware = "dvb-usb-dibusb-5.0.0.11.fw", 182 183 .num_adapters = 1, 184 .adapter = { 185 { 186 .num_frontends = 1, 187 .fe = {{ 188 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 189 .pid_filter_count = 16, 190 191 .streaming_ctrl = dibusb_streaming_ctrl, 192 .pid_filter = dibusb_pid_filter, 193 .pid_filter_ctrl = dibusb_pid_filter_ctrl, 194 .frontend_attach = dibusb_dib3000mb_frontend_attach, 195 .tuner_attach = dibusb_tuner_probe_and_attach, 196 197 /* parameter for the MPEG2-data transfer */ 198 .stream = { 199 .type = USB_BULK, 200 .count = 7, 201 .endpoint = 0x02, 202 .u = { 203 .bulk = { 204 .buffersize = 4096, 205 } 206 } 207 }, 208 }}, 209 .size_of_priv = sizeof(struct dibusb_state), 210 } 211 }, 212 213 .power_ctrl = dibusb_power_ctrl, 214 215 .rc.legacy = { 216 .rc_interval = DEFAULT_RC_INTERVAL, 217 .rc_map_table = rc_map_dibusb_table, 218 .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ 219 .rc_query = dibusb_rc_query, 220 }, 221 222 .i2c_algo = &dibusb_i2c_algo, 223 224 .generic_bulk_ctrl_endpoint = 0x01, 225 226 .num_device_descs = 9, 227 .devices = { 228 { "AVerMedia AverTV DVBT USB1.1", 229 { &dibusb_dib3000mb_table[0], NULL }, 230 { &dibusb_dib3000mb_table[1], NULL }, 231 }, 232 { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)", 233 { &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL}, 234 { &dibusb_dib3000mb_table[3], NULL }, 235 }, 236 { "DiBcom USB1.1 DVB-T reference design (MOD3000)", 237 { &dibusb_dib3000mb_table[5], NULL }, 238 { &dibusb_dib3000mb_table[6], NULL }, 239 }, 240 { "KWorld V-Stream XPERT DTV - DVB-T USB1.1", 241 { &dibusb_dib3000mb_table[7], NULL }, 242 { &dibusb_dib3000mb_table[8], NULL }, 243 }, 244 { "Grandtec USB1.1 DVB-T", 245 { &dibusb_dib3000mb_table[9], &dibusb_dib3000mb_table[11], NULL }, 246 { &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL }, 247 }, 248 { "Unknown USB1.1 DVB-T device ???? please report the name to the author", 249 { &dibusb_dib3000mb_table[13], NULL }, 250 { &dibusb_dib3000mb_table[14], NULL }, 251 }, 252 { "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device", 253 { &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL}, 254 { &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL}, 255 }, 256 { "Artec T1 USB1.1 TVBOX with AN2135", 257 { &dibusb_dib3000mb_table[19], NULL }, 258 { &dibusb_dib3000mb_table[20], NULL }, 259 }, 260 { "VideoWalker DVB-T USB", 261 { &dibusb_dib3000mb_table[25], NULL }, 262 { &dibusb_dib3000mb_table[26], NULL }, 263 }, 264 } 265 }; 266 267 static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { 268 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 269 .usb_ctrl = CYPRESS_AN2235, 270 271 .firmware = "dvb-usb-dibusb-an2235-01.fw", 272 273 .num_adapters = 1, 274 .adapter = { 275 { 276 .num_frontends = 1, 277 .fe = {{ 278 .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, 279 .pid_filter_count = 16, 280 281 .streaming_ctrl = dibusb_streaming_ctrl, 282 .pid_filter = dibusb_pid_filter, 283 .pid_filter_ctrl = dibusb_pid_filter_ctrl, 284 .frontend_attach = dibusb_dib3000mb_frontend_attach, 285 .tuner_attach = dibusb_tuner_probe_and_attach, 286 287 /* parameter for the MPEG2-data transfer */ 288 .stream = { 289 .type = USB_BULK, 290 .count = 7, 291 .endpoint = 0x02, 292 .u = { 293 .bulk = { 294 .buffersize = 4096, 295 } 296 } 297 }, 298 }}, 299 .size_of_priv = sizeof(struct dibusb_state), 300 }, 301 }, 302 .power_ctrl = dibusb_power_ctrl, 303 304 .rc.legacy = { 305 .rc_interval = DEFAULT_RC_INTERVAL, 306 .rc_map_table = rc_map_dibusb_table, 307 .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ 308 .rc_query = dibusb_rc_query, 309 }, 310 311 .i2c_algo = &dibusb_i2c_algo, 312 313 .generic_bulk_ctrl_endpoint = 0x01, 314 315 #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY 316 .num_device_descs = 2, 317 #else 318 .num_device_descs = 1, 319 #endif 320 .devices = { 321 { "Artec T1 USB1.1 TVBOX with AN2235", 322 { &dibusb_dib3000mb_table[21], NULL }, 323 { &dibusb_dib3000mb_table[22], NULL }, 324 }, 325 #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY 326 { "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)", 327 { &dibusb_dib3000mb_table[30], NULL }, 328 { NULL }, 329 }, 330 { NULL }, 331 #endif 332 } 333 }; 334 335 static struct dvb_usb_device_properties dibusb2_0b_properties = { 336 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 337 338 .usb_ctrl = CYPRESS_FX2, 339 340 .firmware = "dvb-usb-adstech-usb2-02.fw", 341 342 .num_adapters = 1, 343 .adapter = { 344 { 345 .num_frontends = 1, 346 .fe = {{ 347 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 348 .pid_filter_count = 16, 349 350 .streaming_ctrl = dibusb2_0_streaming_ctrl, 351 .pid_filter = dibusb_pid_filter, 352 .pid_filter_ctrl = dibusb_pid_filter_ctrl, 353 .frontend_attach = dibusb_dib3000mb_frontend_attach, 354 .tuner_attach = dibusb_thomson_tuner_attach, 355 356 /* parameter for the MPEG2-data transfer */ 357 .stream = { 358 .type = USB_BULK, 359 .count = 7, 360 .endpoint = 0x06, 361 .u = { 362 .bulk = { 363 .buffersize = 4096, 364 } 365 } 366 }, 367 }}, 368 .size_of_priv = sizeof(struct dibusb_state), 369 } 370 }, 371 .power_ctrl = dibusb2_0_power_ctrl, 372 373 .rc.legacy = { 374 .rc_interval = DEFAULT_RC_INTERVAL, 375 .rc_map_table = rc_map_dibusb_table, 376 .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ 377 .rc_query = dibusb_rc_query, 378 }, 379 380 .i2c_algo = &dibusb_i2c_algo, 381 382 .generic_bulk_ctrl_endpoint = 0x01, 383 384 .num_device_descs = 2, 385 .devices = { 386 { "KWorld/ADSTech Instant DVB-T USB2.0", 387 { &dibusb_dib3000mb_table[23], NULL }, 388 { &dibusb_dib3000mb_table[24], NULL }, 389 }, 390 { "KWorld Xpert DVB-T USB2.0", 391 { &dibusb_dib3000mb_table[27], NULL }, 392 { NULL } 393 }, 394 { NULL }, 395 } 396 }; 397 398 static struct dvb_usb_device_properties artec_t1_usb2_properties = { 399 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 400 401 .usb_ctrl = CYPRESS_FX2, 402 403 .firmware = "dvb-usb-dibusb-6.0.0.8.fw", 404 405 .num_adapters = 1, 406 .adapter = { 407 { 408 .num_frontends = 1, 409 .fe = {{ 410 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 411 .pid_filter_count = 16, 412 413 .streaming_ctrl = dibusb2_0_streaming_ctrl, 414 .pid_filter = dibusb_pid_filter, 415 .pid_filter_ctrl = dibusb_pid_filter_ctrl, 416 .frontend_attach = dibusb_dib3000mb_frontend_attach, 417 .tuner_attach = dibusb_tuner_probe_and_attach, 418 /* parameter for the MPEG2-data transfer */ 419 .stream = { 420 .type = USB_BULK, 421 .count = 7, 422 .endpoint = 0x06, 423 .u = { 424 .bulk = { 425 .buffersize = 4096, 426 } 427 } 428 }, 429 }}, 430 .size_of_priv = sizeof(struct dibusb_state), 431 } 432 }, 433 .power_ctrl = dibusb2_0_power_ctrl, 434 435 .rc.legacy = { 436 .rc_interval = DEFAULT_RC_INTERVAL, 437 .rc_map_table = rc_map_dibusb_table, 438 .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ 439 .rc_query = dibusb_rc_query, 440 }, 441 442 .i2c_algo = &dibusb_i2c_algo, 443 444 .generic_bulk_ctrl_endpoint = 0x01, 445 446 .num_device_descs = 1, 447 .devices = { 448 { "Artec T1 USB2.0", 449 { &dibusb_dib3000mb_table[28], NULL }, 450 { &dibusb_dib3000mb_table[29], NULL }, 451 }, 452 { NULL }, 453 } 454 }; 455 456 static struct usb_driver dibusb_driver = { 457 .name = "dvb_usb_dibusb_mb", 458 .probe = dibusb_probe, 459 .disconnect = dvb_usb_device_exit, 460 .id_table = dibusb_dib3000mb_table, 461 }; 462 463 module_usb_driver(dibusb_driver); 464 465 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); 466 MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)"); 467 MODULE_VERSION("1.0"); 468 MODULE_LICENSE("GPL"); 469