490 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* DVB USB compliant linux driver for mobile DVB-T USB devices based on3 * 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 has8 * Copyright (C) 2004 Amaury Demol for DiBcom9 *10 * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information11 */12#include "dibusb.h"13 14DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);15 16static 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 24static 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 41static 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 52static 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 tuner64 * (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures65 * this out. */66static 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 */102static struct dvb_usb_device_properties dibusb1_1_properties;103static struct dvb_usb_device_properties dibusb1_1_an2235_properties;104static struct dvb_usb_device_properties dibusb2_0b_properties;105static struct dvb_usb_device_properties artec_t1_usb2_properties;106 107static 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 */124enum {125 WIDEVIEW_DVBT_USB_COLD,126 WIDEVIEW_DVBT_USB_WARM,127 COMPRO_DVBU2000_COLD,128 COMPRO_DVBU2000_WARM,129 COMPRO_DVBU2000_UNK_COLD,130 DIBCOM_MOD3000_COLD,131 DIBCOM_MOD3000_WARM,132 EMPIA_VSTREAM_COLD,133 EMPIA_VSTREAM_WARM,134 GRANDTEC_DVBT_USB_COLD,135 GRANDTEC_DVBT_USB_WARM,136 GRANDTEC_MOD3000_COLD,137 GRANDTEC_MOD3000_WARM,138 UNK_HYPER_PALTEK_COLD,139 UNK_HYPER_PALTEK_WARM,140 VISIONPLUS_VP7041_COLD,141 VISIONPLUS_VP7041_WARM,142 TWINHAN_VP7041_COLD,143 TWINHAN_VP7041_WARM,144 ULTIMA_TVBOX_COLD,145 ULTIMA_TVBOX_WARM,146 ULTIMA_TVBOX_AN2235_COLD,147 ULTIMA_TVBOX_AN2235_WARM,148 ADSTECH_USB2_COLD,149 ADSTECH_USB2_WARM,150 KYE_DVB_T_COLD,151 KYE_DVB_T_WARM,152 KWORLD_VSTREAM_COLD,153 ULTIMA_TVBOX_USB2_COLD,154 ULTIMA_TVBOX_USB2_WARM,155 ULTIMA_TVBOX_ANCHOR_COLD,156};157 158static struct usb_device_id dibusb_dib3000mb_table[] = {159 DVB_USB_DEV(WIDEVIEW, WIDEVIEW_DVBT_USB_COLD),160 DVB_USB_DEV(WIDEVIEW, WIDEVIEW_DVBT_USB_WARM),161 DVB_USB_DEV(COMPRO, COMPRO_DVBU2000_COLD),162 DVB_USB_DEV(COMPRO, COMPRO_DVBU2000_WARM),163 DVB_USB_DEV(COMPRO_UNK, COMPRO_DVBU2000_UNK_COLD),164 DVB_USB_DEV(DIBCOM, DIBCOM_MOD3000_COLD),165 DVB_USB_DEV(DIBCOM, DIBCOM_MOD3000_WARM),166 DVB_USB_DEV(EMPIA, EMPIA_VSTREAM_COLD),167 DVB_USB_DEV(EMPIA, EMPIA_VSTREAM_WARM),168 DVB_USB_DEV(GRANDTEC, GRANDTEC_DVBT_USB_COLD),169 DVB_USB_DEV(GRANDTEC, GRANDTEC_DVBT_USB_WARM),170 DVB_USB_DEV(GRANDTEC, GRANDTEC_MOD3000_COLD),171 DVB_USB_DEV(GRANDTEC, GRANDTEC_MOD3000_WARM),172 DVB_USB_DEV(HYPER_PALTEK, UNK_HYPER_PALTEK_COLD),173 DVB_USB_DEV(HYPER_PALTEK, UNK_HYPER_PALTEK_WARM),174 DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7041_COLD),175 DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7041_WARM),176 DVB_USB_DEV(TWINHAN, TWINHAN_VP7041_COLD),177 DVB_USB_DEV(TWINHAN, TWINHAN_VP7041_WARM),178 DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_COLD),179 DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_WARM),180 DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_AN2235_COLD),181 DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_AN2235_WARM),182 DVB_USB_DEV(ADSTECH, ADSTECH_USB2_COLD),183 DVB_USB_DEV(ADSTECH, ADSTECH_USB2_WARM),184 DVB_USB_DEV(KYE, KYE_DVB_T_COLD),185 DVB_USB_DEV(KYE, KYE_DVB_T_WARM),186 DVB_USB_DEV(KWORLD, KWORLD_VSTREAM_COLD),187 DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_USB2_COLD),188 DVB_USB_DEV(ULTIMA_ELECTRONIC, ULTIMA_TVBOX_USB2_WARM),189#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY190 DVB_USB_DEV(ANCHOR, ULTIMA_TVBOX_ANCHOR_COLD),191#endif192 { }193};194 195MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);196 197static struct dvb_usb_device_properties dibusb1_1_properties = {198 .caps = DVB_USB_IS_AN_I2C_ADAPTER,199 200 .usb_ctrl = CYPRESS_AN2135,201 202 .firmware = "dvb-usb-dibusb-5.0.0.11.fw",203 204 .num_adapters = 1,205 .adapter = {206 {207 .num_frontends = 1,208 .fe = {{209 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,210 .pid_filter_count = 16,211 212 .streaming_ctrl = dibusb_streaming_ctrl,213 .pid_filter = dibusb_pid_filter,214 .pid_filter_ctrl = dibusb_pid_filter_ctrl,215 .frontend_attach = dibusb_dib3000mb_frontend_attach,216 .tuner_attach = dibusb_tuner_probe_and_attach,217 218 /* parameter for the MPEG2-data transfer */219 .stream = {220 .type = USB_BULK,221 .count = 7,222 .endpoint = 0x02,223 .u = {224 .bulk = {225 .buffersize = 4096,226 }227 }228 },229 }},230 .size_of_priv = sizeof(struct dibusb_state),231 }232 },233 234 .power_ctrl = dibusb_power_ctrl,235 236 .rc.legacy = {237 .rc_interval = DEFAULT_RC_INTERVAL,238 .rc_map_table = rc_map_dibusb_table,239 .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */240 .rc_query = dibusb_rc_query,241 },242 243 .i2c_algo = &dibusb_i2c_algo,244 245 .generic_bulk_ctrl_endpoint = 0x01,246 247 .num_device_descs = 9,248 .devices = {249 { "AVerMedia AverTV DVBT USB1.1",250 { &dibusb_dib3000mb_table[WIDEVIEW_DVBT_USB_COLD], NULL },251 { &dibusb_dib3000mb_table[WIDEVIEW_DVBT_USB_WARM], NULL },252 },253 { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",254 { &dibusb_dib3000mb_table[COMPRO_DVBU2000_COLD], &dibusb_dib3000mb_table[COMPRO_DVBU2000_UNK_COLD], NULL},255 { &dibusb_dib3000mb_table[COMPRO_DVBU2000_WARM], NULL },256 },257 { "DiBcom USB1.1 DVB-T reference design (MOD3000)",258 { &dibusb_dib3000mb_table[DIBCOM_MOD3000_COLD], NULL },259 { &dibusb_dib3000mb_table[DIBCOM_MOD3000_WARM], NULL },260 },261 { "KWorld V-Stream XPERT DTV - DVB-T USB1.1",262 { &dibusb_dib3000mb_table[EMPIA_VSTREAM_COLD], NULL },263 { &dibusb_dib3000mb_table[EMPIA_VSTREAM_WARM], NULL },264 },265 { "Grandtec USB1.1 DVB-T",266 { &dibusb_dib3000mb_table[GRANDTEC_DVBT_USB_COLD], &dibusb_dib3000mb_table[GRANDTEC_MOD3000_COLD], NULL },267 { &dibusb_dib3000mb_table[GRANDTEC_DVBT_USB_WARM], &dibusb_dib3000mb_table[GRANDTEC_MOD3000_WARM], NULL },268 },269 { "Unknown USB1.1 DVB-T device ???? please report the name to the author",270 { &dibusb_dib3000mb_table[UNK_HYPER_PALTEK_COLD], NULL },271 { &dibusb_dib3000mb_table[UNK_HYPER_PALTEK_WARM], NULL },272 },273 { "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device",274 { &dibusb_dib3000mb_table[VISIONPLUS_VP7041_COLD], &dibusb_dib3000mb_table[TWINHAN_VP7041_COLD], NULL},275 { &dibusb_dib3000mb_table[VISIONPLUS_VP7041_WARM], &dibusb_dib3000mb_table[TWINHAN_VP7041_WARM], NULL},276 },277 { "Artec T1 USB1.1 TVBOX with AN2135",278 { &dibusb_dib3000mb_table[ULTIMA_TVBOX_COLD], NULL },279 { &dibusb_dib3000mb_table[ULTIMA_TVBOX_WARM], NULL },280 },281 { "VideoWalker DVB-T USB",282 { &dibusb_dib3000mb_table[KYE_DVB_T_COLD], NULL },283 { &dibusb_dib3000mb_table[KYE_DVB_T_WARM], NULL },284 },285 }286};287 288static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {289 .caps = DVB_USB_IS_AN_I2C_ADAPTER,290 .usb_ctrl = CYPRESS_AN2235,291 292 .firmware = "dvb-usb-dibusb-an2235-01.fw",293 294 .num_adapters = 1,295 .adapter = {296 {297 .num_frontends = 1,298 .fe = {{299 .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,300 .pid_filter_count = 16,301 302 .streaming_ctrl = dibusb_streaming_ctrl,303 .pid_filter = dibusb_pid_filter,304 .pid_filter_ctrl = dibusb_pid_filter_ctrl,305 .frontend_attach = dibusb_dib3000mb_frontend_attach,306 .tuner_attach = dibusb_tuner_probe_and_attach,307 308 /* parameter for the MPEG2-data transfer */309 .stream = {310 .type = USB_BULK,311 .count = 7,312 .endpoint = 0x02,313 .u = {314 .bulk = {315 .buffersize = 4096,316 }317 }318 },319 }},320 .size_of_priv = sizeof(struct dibusb_state),321 },322 },323 .power_ctrl = dibusb_power_ctrl,324 325 .rc.legacy = {326 .rc_interval = DEFAULT_RC_INTERVAL,327 .rc_map_table = rc_map_dibusb_table,328 .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */329 .rc_query = dibusb_rc_query,330 },331 332 .i2c_algo = &dibusb_i2c_algo,333 334 .generic_bulk_ctrl_endpoint = 0x01,335 336#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY337 .num_device_descs = 2,338#else339 .num_device_descs = 1,340#endif341 .devices = {342 { "Artec T1 USB1.1 TVBOX with AN2235",343 { &dibusb_dib3000mb_table[ULTIMA_TVBOX_AN2235_COLD], NULL },344 { &dibusb_dib3000mb_table[ULTIMA_TVBOX_AN2235_WARM], NULL },345 },346#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY347 { "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",348 { &dibusb_dib3000mb_table[ULTIMA_TVBOX_ANCHOR_COLD], NULL },349 { NULL },350 },351 { NULL },352#endif353 }354};355 356static struct dvb_usb_device_properties dibusb2_0b_properties = {357 .caps = DVB_USB_IS_AN_I2C_ADAPTER,358 359 .usb_ctrl = CYPRESS_FX2,360 361 .firmware = "dvb-usb-adstech-usb2-02.fw",362 363 .num_adapters = 1,364 .adapter = {365 {366 .num_frontends = 1,367 .fe = {{368 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,369 .pid_filter_count = 16,370 371 .streaming_ctrl = dibusb2_0_streaming_ctrl,372 .pid_filter = dibusb_pid_filter,373 .pid_filter_ctrl = dibusb_pid_filter_ctrl,374 .frontend_attach = dibusb_dib3000mb_frontend_attach,375 .tuner_attach = dibusb_thomson_tuner_attach,376 377 /* parameter for the MPEG2-data transfer */378 .stream = {379 .type = USB_BULK,380 .count = 7,381 .endpoint = 0x06,382 .u = {383 .bulk = {384 .buffersize = 4096,385 }386 }387 },388 }},389 .size_of_priv = sizeof(struct dibusb_state),390 }391 },392 .power_ctrl = dibusb2_0_power_ctrl,393 394 .rc.legacy = {395 .rc_interval = DEFAULT_RC_INTERVAL,396 .rc_map_table = rc_map_dibusb_table,397 .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */398 .rc_query = dibusb_rc_query,399 },400 401 .i2c_algo = &dibusb_i2c_algo,402 403 .generic_bulk_ctrl_endpoint = 0x01,404 405 .num_device_descs = 2,406 .devices = {407 { "KWorld/ADSTech Instant DVB-T USB2.0",408 { &dibusb_dib3000mb_table[ADSTECH_USB2_COLD], NULL },409 { &dibusb_dib3000mb_table[ADSTECH_USB2_WARM], NULL },410 },411 { "KWorld Xpert DVB-T USB2.0",412 { &dibusb_dib3000mb_table[KWORLD_VSTREAM_COLD], NULL },413 { NULL }414 },415 { NULL },416 }417};418 419static struct dvb_usb_device_properties artec_t1_usb2_properties = {420 .caps = DVB_USB_IS_AN_I2C_ADAPTER,421 422 .usb_ctrl = CYPRESS_FX2,423 424 .firmware = "dvb-usb-dibusb-6.0.0.8.fw",425 426 .num_adapters = 1,427 .adapter = {428 {429 .num_frontends = 1,430 .fe = {{431 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,432 .pid_filter_count = 16,433 434 .streaming_ctrl = dibusb2_0_streaming_ctrl,435 .pid_filter = dibusb_pid_filter,436 .pid_filter_ctrl = dibusb_pid_filter_ctrl,437 .frontend_attach = dibusb_dib3000mb_frontend_attach,438 .tuner_attach = dibusb_tuner_probe_and_attach,439 /* parameter for the MPEG2-data transfer */440 .stream = {441 .type = USB_BULK,442 .count = 7,443 .endpoint = 0x06,444 .u = {445 .bulk = {446 .buffersize = 4096,447 }448 }449 },450 }},451 .size_of_priv = sizeof(struct dibusb_state),452 }453 },454 .power_ctrl = dibusb2_0_power_ctrl,455 456 .rc.legacy = {457 .rc_interval = DEFAULT_RC_INTERVAL,458 .rc_map_table = rc_map_dibusb_table,459 .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */460 .rc_query = dibusb_rc_query,461 },462 463 .i2c_algo = &dibusb_i2c_algo,464 465 .generic_bulk_ctrl_endpoint = 0x01,466 467 .num_device_descs = 1,468 .devices = {469 { "Artec T1 USB2.0",470 { &dibusb_dib3000mb_table[ULTIMA_TVBOX_USB2_COLD], NULL },471 { &dibusb_dib3000mb_table[ULTIMA_TVBOX_USB2_WARM], NULL },472 },473 { NULL },474 }475};476 477static struct usb_driver dibusb_driver = {478 .name = "dvb_usb_dibusb_mb",479 .probe = dibusb_probe,480 .disconnect = dvb_usb_device_exit,481 .id_table = dibusb_dib3000mb_table,482};483 484module_usb_driver(dibusb_driver);485 486MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");487MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)");488MODULE_VERSION("1.0");489MODULE_LICENSE("GPL");490