diff options
| author | Olli Salonen <olli.salonen@iki.fi> | 2014-07-13 09:52:22 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-07-14 20:07:07 -0400 |
| commit | 26c42b0dd5fa552bf26451cbd1d4c70fb6b95b67 (patch) | |
| tree | 9ed52c022eae5bc1168054838d2a5adfa337cb40 | |
| parent | a1dad50d8cdce0be71489c7544ffcd36cf80e994 (diff) | |
[media] cxusb: TechnoTrend CT2-4400 USB DVB-T2/C tuner support
USB ID 0b48:3014.
USB interface: Cypress CY7C68013A-56LTXC
Demodulator: Silicon Labs Si2168-30
Tuner: Silicon Labs Si2158-20
Cc: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Olli Salonen <olli.salonen@iki.fi>
Reviewed-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Antti Palosaari <crope@iki.fi>
Reviewed-by: Michael Ira Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
| -rw-r--r-- | drivers/media/dvb-core/dvb-usb-ids.h | 1 | ||||
| -rw-r--r-- | drivers/media/usb/dvb-usb/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/media/usb/dvb-usb/cxusb.c | 191 | ||||
| -rw-r--r-- | drivers/media/usb/dvb-usb/cxusb.h | 2 |
4 files changed, 196 insertions, 1 deletions
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 11d2bea23b02..f8e31509f12e 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h | |||
| @@ -244,6 +244,7 @@ | |||
| 244 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 | 244 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 |
| 245 | #define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM 0x3009 | 245 | #define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM 0x3009 |
| 246 | #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d | 246 | #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d |
| 247 | #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014 | ||
| 247 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a | 248 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a |
| 248 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 | 249 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 |
| 249 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 | 250 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 |
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig index c5d95662e2e1..10aef2188fbe 100644 --- a/drivers/media/usb/dvb-usb/Kconfig +++ b/drivers/media/usb/dvb-usb/Kconfig | |||
| @@ -117,10 +117,12 @@ config DVB_USB_CXUSB | |||
| 117 | select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT | 117 | select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT |
| 118 | select DVB_ATBM8830 if MEDIA_SUBDRV_AUTOSELECT | 118 | select DVB_ATBM8830 if MEDIA_SUBDRV_AUTOSELECT |
| 119 | select DVB_LGS8GXX if MEDIA_SUBDRV_AUTOSELECT | 119 | select DVB_LGS8GXX if MEDIA_SUBDRV_AUTOSELECT |
| 120 | select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT | ||
| 120 | select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT | 121 | select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT |
| 121 | select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT | 122 | select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT |
| 122 | select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT | 123 | select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT |
| 123 | select MEDIA_TUNER_MAX2165 if MEDIA_SUBDRV_AUTOSELECT | 124 | select MEDIA_TUNER_MAX2165 if MEDIA_SUBDRV_AUTOSELECT |
| 125 | select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT | ||
| 124 | help | 126 | help |
| 125 | Say Y here to support the Conexant USB2.0 hybrid reference design. | 127 | Say Y here to support the Conexant USB2.0 hybrid reference design. |
| 126 | Currently, only DVB and ATSC modes are supported, analog mode | 128 | Currently, only DVB and ATSC modes are supported, analog mode |
| @@ -128,6 +130,7 @@ config DVB_USB_CXUSB | |||
| 128 | 130 | ||
| 129 | Medion MD95700 hybrid USB2.0 device. | 131 | Medion MD95700 hybrid USB2.0 device. |
| 130 | DViCO FusionHDTV (Bluebird) USB2.0 devices | 132 | DViCO FusionHDTV (Bluebird) USB2.0 devices |
| 133 | TechnoTrend TVStick CT2-4400 | ||
| 131 | 134 | ||
| 132 | config DVB_USB_M920X | 135 | config DVB_USB_M920X |
| 133 | tristate "Uli m920x DVB-T USB2.0 support" | 136 | tristate "Uli m920x DVB-T USB2.0 support" |
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 6acde5ee4324..d60e36d5103a 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c | |||
| @@ -42,6 +42,8 @@ | |||
| 42 | #include "dib0070.h" | 42 | #include "dib0070.h" |
| 43 | #include "lgs8gxx.h" | 43 | #include "lgs8gxx.h" |
| 44 | #include "atbm8830.h" | 44 | #include "atbm8830.h" |
| 45 | #include "si2168.h" | ||
| 46 | #include "si2157.h" | ||
| 45 | 47 | ||
| 46 | /* Max transfer size done by I2C transfer functions */ | 48 | /* Max transfer size done by I2C transfer functions */ |
| 47 | #define MAX_XFER_SIZE 64 | 49 | #define MAX_XFER_SIZE 64 |
| @@ -144,6 +146,22 @@ static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d, | |||
| 144 | } | 146 | } |
| 145 | } | 147 | } |
| 146 | 148 | ||
| 149 | static int cxusb_tt_ct2_4400_gpio_tuner(struct dvb_usb_device *d, int onoff) | ||
| 150 | { | ||
| 151 | u8 o[2], i; | ||
| 152 | int rc; | ||
| 153 | |||
| 154 | o[0] = 0x83; | ||
| 155 | o[1] = onoff; | ||
| 156 | rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); | ||
| 157 | |||
| 158 | if (rc) { | ||
| 159 | deb_info("gpio_write failed.\n"); | ||
| 160 | return -EIO; | ||
| 161 | } | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 147 | /* I2C */ | 165 | /* I2C */ |
| 148 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | 166 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
| 149 | int num) | 167 | int num) |
| @@ -505,6 +523,30 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, | |||
| 505 | return 0; | 523 | return 0; |
| 506 | } | 524 | } |
| 507 | 525 | ||
| 526 | static int cxusb_tt_ct2_4400_rc_query(struct dvb_usb_device *d) | ||
| 527 | { | ||
| 528 | u8 i[2]; | ||
| 529 | int ret; | ||
| 530 | u32 cmd, keycode; | ||
| 531 | u8 rc5_cmd, rc5_addr, rc5_toggle; | ||
| 532 | |||
| 533 | ret = cxusb_ctrl_msg(d, 0x10, NULL, 0, i, 2); | ||
| 534 | if (ret) | ||
| 535 | return ret; | ||
| 536 | |||
| 537 | cmd = (i[0] << 8) | i[1]; | ||
| 538 | |||
| 539 | if (cmd != 0xffff) { | ||
| 540 | rc5_cmd = cmd & 0x3F; /* bits 1-6 for command */ | ||
| 541 | rc5_addr = (cmd & 0x07C0) >> 6; /* bits 7-11 for address */ | ||
| 542 | rc5_toggle = (cmd & 0x0800) >> 11; /* bit 12 for toggle */ | ||
| 543 | keycode = (rc5_addr << 8) | rc5_cmd; | ||
| 544 | rc_keydown(d->rc_dev, keycode, rc5_toggle); | ||
| 545 | } | ||
| 546 | |||
| 547 | return 0; | ||
| 548 | } | ||
| 549 | |||
| 508 | static struct rc_map_table rc_map_dvico_mce_table[] = { | 550 | static struct rc_map_table rc_map_dvico_mce_table[] = { |
| 509 | { 0xfe02, KEY_TV }, | 551 | { 0xfe02, KEY_TV }, |
| 510 | { 0xfe0e, KEY_MP3 }, | 552 | { 0xfe0e, KEY_MP3 }, |
| @@ -1301,6 +1343,73 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 1301 | return 0; | 1343 | return 0; |
| 1302 | } | 1344 | } |
| 1303 | 1345 | ||
| 1346 | static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap) | ||
| 1347 | { | ||
| 1348 | struct dvb_usb_device *d = adap->dev; | ||
| 1349 | struct cxusb_state *st = d->priv; | ||
| 1350 | struct i2c_adapter *adapter; | ||
| 1351 | struct i2c_client *client_demod; | ||
| 1352 | struct i2c_client *client_tuner; | ||
| 1353 | struct i2c_board_info info; | ||
| 1354 | struct si2168_config si2168_config; | ||
| 1355 | struct si2157_config si2157_config; | ||
| 1356 | |||
| 1357 | /* reset the tuner */ | ||
| 1358 | if (cxusb_tt_ct2_4400_gpio_tuner(d, 0) < 0) { | ||
| 1359 | err("clear tuner gpio failed"); | ||
| 1360 | return -EIO; | ||
| 1361 | } | ||
| 1362 | msleep(100); | ||
| 1363 | if (cxusb_tt_ct2_4400_gpio_tuner(d, 1) < 0) { | ||
| 1364 | err("set tuner gpio failed"); | ||
| 1365 | return -EIO; | ||
| 1366 | } | ||
| 1367 | msleep(100); | ||
| 1368 | |||
| 1369 | /* attach frontend */ | ||
| 1370 | si2168_config.i2c_adapter = &adapter; | ||
| 1371 | si2168_config.fe = &adap->fe_adap[0].fe; | ||
| 1372 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
| 1373 | strlcpy(info.type, "si2168", I2C_NAME_SIZE); | ||
| 1374 | info.addr = 0x64; | ||
| 1375 | info.platform_data = &si2168_config; | ||
| 1376 | request_module(info.type); | ||
| 1377 | client_demod = i2c_new_device(&d->i2c_adap, &info); | ||
| 1378 | if (client_demod == NULL || client_demod->dev.driver == NULL) | ||
| 1379 | return -ENODEV; | ||
| 1380 | |||
| 1381 | if (!try_module_get(client_demod->dev.driver->owner)) { | ||
| 1382 | i2c_unregister_device(client_demod); | ||
| 1383 | return -ENODEV; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | st->i2c_client_demod = client_demod; | ||
| 1387 | |||
| 1388 | /* attach tuner */ | ||
| 1389 | si2157_config.fe = adap->fe_adap[0].fe; | ||
| 1390 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
| 1391 | strlcpy(info.type, "si2157", I2C_NAME_SIZE); | ||
| 1392 | info.addr = 0x60; | ||
| 1393 | info.platform_data = &si2157_config; | ||
| 1394 | request_module(info.type); | ||
| 1395 | client_tuner = i2c_new_device(adapter, &info); | ||
| 1396 | if (client_tuner == NULL || client_tuner->dev.driver == NULL) { | ||
| 1397 | module_put(client_demod->dev.driver->owner); | ||
| 1398 | i2c_unregister_device(client_demod); | ||
| 1399 | return -ENODEV; | ||
| 1400 | } | ||
| 1401 | if (!try_module_get(client_tuner->dev.driver->owner)) { | ||
| 1402 | i2c_unregister_device(client_tuner); | ||
| 1403 | module_put(client_demod->dev.driver->owner); | ||
| 1404 | i2c_unregister_device(client_demod); | ||
| 1405 | return -ENODEV; | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | st->i2c_client_tuner = client_tuner; | ||
| 1409 | |||
| 1410 | return 0; | ||
| 1411 | } | ||
| 1412 | |||
| 1304 | /* | 1413 | /* |
| 1305 | * DViCO has shipped two devices with the same USB ID, but only one of them | 1414 | * DViCO has shipped two devices with the same USB ID, but only one of them |
| 1306 | * needs a firmware download. Check the device class details to see if they | 1415 | * needs a firmware download. Check the device class details to see if they |
| @@ -1382,6 +1491,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope | |||
| 1382 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; | 1491 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; |
| 1383 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties; | 1492 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties; |
| 1384 | static struct dvb_usb_device_properties cxusb_mygica_d689_properties; | 1493 | static struct dvb_usb_device_properties cxusb_mygica_d689_properties; |
| 1494 | static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties; | ||
| 1385 | 1495 | ||
| 1386 | static int cxusb_probe(struct usb_interface *intf, | 1496 | static int cxusb_probe(struct usb_interface *intf, |
| 1387 | const struct usb_device_id *id) | 1497 | const struct usb_device_id *id) |
| @@ -1412,12 +1522,37 @@ static int cxusb_probe(struct usb_interface *intf, | |||
| 1412 | THIS_MODULE, NULL, adapter_nr) || | 1522 | THIS_MODULE, NULL, adapter_nr) || |
| 1413 | 0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, | 1523 | 0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, |
| 1414 | THIS_MODULE, NULL, adapter_nr) || | 1524 | THIS_MODULE, NULL, adapter_nr) || |
| 1525 | 0 == dvb_usb_device_init(intf, &cxusb_tt_ct2_4400_properties, | ||
| 1526 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1415 | 0) | 1527 | 0) |
| 1416 | return 0; | 1528 | return 0; |
| 1417 | 1529 | ||
| 1418 | return -EINVAL; | 1530 | return -EINVAL; |
| 1419 | } | 1531 | } |
| 1420 | 1532 | ||
| 1533 | static void cxusb_disconnect(struct usb_interface *intf) | ||
| 1534 | { | ||
| 1535 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
| 1536 | struct cxusb_state *st = d->priv; | ||
| 1537 | struct i2c_client *client; | ||
| 1538 | |||
| 1539 | /* remove I2C client for tuner */ | ||
| 1540 | client = st->i2c_client_tuner; | ||
| 1541 | if (client) { | ||
| 1542 | module_put(client->dev.driver->owner); | ||
| 1543 | i2c_unregister_device(client); | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | /* remove I2C client for demodulator */ | ||
| 1547 | client = st->i2c_client_demod; | ||
| 1548 | if (client) { | ||
| 1549 | module_put(client->dev.driver->owner); | ||
| 1550 | i2c_unregister_device(client); | ||
| 1551 | } | ||
| 1552 | |||
| 1553 | dvb_usb_device_exit(intf); | ||
| 1554 | } | ||
| 1555 | |||
| 1421 | static struct usb_device_id cxusb_table [] = { | 1556 | static struct usb_device_id cxusb_table [] = { |
| 1422 | { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, | 1557 | { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, |
| 1423 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, | 1558 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, |
| @@ -1439,6 +1574,7 @@ static struct usb_device_id cxusb_table [] = { | |||
| 1439 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, | 1574 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, |
| 1440 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, | 1575 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, |
| 1441 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) }, | 1576 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) }, |
| 1577 | { USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) }, | ||
| 1442 | {} /* Terminating entry */ | 1578 | {} /* Terminating entry */ |
| 1443 | }; | 1579 | }; |
| 1444 | MODULE_DEVICE_TABLE (usb, cxusb_table); | 1580 | MODULE_DEVICE_TABLE (usb, cxusb_table); |
| @@ -2085,10 +2221,63 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = { | |||
| 2085 | } | 2221 | } |
| 2086 | }; | 2222 | }; |
| 2087 | 2223 | ||
| 2224 | static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = { | ||
| 2225 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 2226 | |||
| 2227 | .usb_ctrl = CYPRESS_FX2, | ||
| 2228 | |||
| 2229 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 2230 | |||
| 2231 | .num_adapters = 1, | ||
| 2232 | .adapter = { | ||
| 2233 | { | ||
| 2234 | .num_frontends = 1, | ||
| 2235 | .fe = {{ | ||
| 2236 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 2237 | /* both frontend and tuner attached in the | ||
| 2238 | same function */ | ||
| 2239 | .frontend_attach = cxusb_tt_ct2_4400_attach, | ||
| 2240 | |||
| 2241 | /* parameter for the MPEG2-data transfer */ | ||
| 2242 | .stream = { | ||
| 2243 | .type = USB_BULK, | ||
| 2244 | .count = 8, | ||
| 2245 | .endpoint = 0x82, | ||
| 2246 | .u = { | ||
| 2247 | .bulk = { | ||
| 2248 | .buffersize = 4096, | ||
| 2249 | } | ||
| 2250 | } | ||
| 2251 | }, | ||
| 2252 | } }, | ||
| 2253 | }, | ||
| 2254 | }, | ||
| 2255 | |||
| 2256 | .i2c_algo = &cxusb_i2c_algo, | ||
| 2257 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 2258 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
| 2259 | |||
| 2260 | .rc.core = { | ||
| 2261 | .rc_codes = RC_MAP_TT_1500, | ||
| 2262 | .allowed_protos = RC_BIT_RC5, | ||
| 2263 | .rc_query = cxusb_tt_ct2_4400_rc_query, | ||
| 2264 | .rc_interval = 150, | ||
| 2265 | }, | ||
| 2266 | |||
| 2267 | .num_device_descs = 1, | ||
| 2268 | .devices = { | ||
| 2269 | { | ||
| 2270 | "TechnoTrend TVStick CT2-4400", | ||
| 2271 | { NULL }, | ||
| 2272 | { &cxusb_table[20], NULL }, | ||
| 2273 | }, | ||
| 2274 | } | ||
| 2275 | }; | ||
| 2276 | |||
| 2088 | static struct usb_driver cxusb_driver = { | 2277 | static struct usb_driver cxusb_driver = { |
| 2089 | .name = "dvb_usb_cxusb", | 2278 | .name = "dvb_usb_cxusb", |
| 2090 | .probe = cxusb_probe, | 2279 | .probe = cxusb_probe, |
| 2091 | .disconnect = dvb_usb_device_exit, | 2280 | .disconnect = cxusb_disconnect, |
| 2092 | .id_table = cxusb_table, | 2281 | .id_table = cxusb_table, |
| 2093 | }; | 2282 | }; |
| 2094 | 2283 | ||
diff --git a/drivers/media/usb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h index 1a51eafd31b9..527ff7905e15 100644 --- a/drivers/media/usb/dvb-usb/cxusb.h +++ b/drivers/media/usb/dvb-usb/cxusb.h | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | 30 | ||
| 31 | struct cxusb_state { | 31 | struct cxusb_state { |
| 32 | u8 gpio_write_state[3]; | 32 | u8 gpio_write_state[3]; |
| 33 | struct i2c_client *i2c_client_demod; | ||
| 34 | struct i2c_client *i2c_client_tuner; | ||
| 33 | }; | 35 | }; |
| 34 | 36 | ||
| 35 | #endif | 37 | #endif |
