diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb/cxusb.c')
-rw-r--r-- | drivers/media/usb/dvb-usb/cxusb.c | 130 |
1 files changed, 128 insertions, 2 deletions
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 16bc579d1404..356abb369c20 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include "atbm8830.h" | 44 | #include "atbm8830.h" |
45 | #include "si2168.h" | 45 | #include "si2168.h" |
46 | #include "si2157.h" | 46 | #include "si2157.h" |
47 | #include "sp2.h" | ||
47 | 48 | ||
48 | /* Max transfer size done by I2C transfer functions */ | 49 | /* Max transfer size done by I2C transfer functions */ |
49 | #define MAX_XFER_SIZE 80 | 50 | #define MAX_XFER_SIZE 80 |
@@ -175,7 +176,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
175 | 176 | ||
176 | for (i = 0; i < num; i++) { | 177 | for (i = 0; i < num; i++) { |
177 | 178 | ||
178 | if (d->udev->descriptor.idVendor == USB_VID_MEDION) | 179 | if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_MEDION) |
179 | switch (msg[i].addr) { | 180 | switch (msg[i].addr) { |
180 | case 0x63: | 181 | case 0x63: |
181 | cxusb_gpio_tuner(d, 0); | 182 | cxusb_gpio_tuner(d, 0); |
@@ -672,6 +673,70 @@ static struct rc_map_table rc_map_d680_dmb_table[] = { | |||
672 | { 0x0025, KEY_POWER }, | 673 | { 0x0025, KEY_POWER }, |
673 | }; | 674 | }; |
674 | 675 | ||
676 | static int cxusb_tt_ct2_4400_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | ||
677 | { | ||
678 | u8 wbuf[2]; | ||
679 | u8 rbuf[6]; | ||
680 | int ret; | ||
681 | struct i2c_msg msg[] = { | ||
682 | { | ||
683 | .addr = 0x51, | ||
684 | .flags = 0, | ||
685 | .buf = wbuf, | ||
686 | .len = 2, | ||
687 | }, { | ||
688 | .addr = 0x51, | ||
689 | .flags = I2C_M_RD, | ||
690 | .buf = rbuf, | ||
691 | .len = 6, | ||
692 | } | ||
693 | }; | ||
694 | |||
695 | wbuf[0] = 0x1e; | ||
696 | wbuf[1] = 0x00; | ||
697 | ret = cxusb_i2c_xfer(&d->i2c_adap, msg, 2); | ||
698 | |||
699 | if (ret == 2) { | ||
700 | memcpy(mac, rbuf, 6); | ||
701 | return 0; | ||
702 | } else { | ||
703 | if (ret < 0) | ||
704 | return ret; | ||
705 | return -EIO; | ||
706 | } | ||
707 | } | ||
708 | |||
709 | static int cxusb_tt_ct2_4650_ci_ctrl(void *priv, u8 read, int addr, | ||
710 | u8 data, int *mem) | ||
711 | { | ||
712 | struct dvb_usb_device *d = priv; | ||
713 | u8 wbuf[3]; | ||
714 | u8 rbuf[2]; | ||
715 | int ret; | ||
716 | |||
717 | wbuf[0] = (addr >> 8) & 0xff; | ||
718 | wbuf[1] = addr & 0xff; | ||
719 | |||
720 | if (read) { | ||
721 | ret = cxusb_ctrl_msg(d, CMD_SP2_CI_READ, wbuf, 2, rbuf, 2); | ||
722 | } else { | ||
723 | wbuf[2] = data; | ||
724 | ret = cxusb_ctrl_msg(d, CMD_SP2_CI_WRITE, wbuf, 3, rbuf, 1); | ||
725 | } | ||
726 | |||
727 | if (ret) | ||
728 | goto err; | ||
729 | |||
730 | if (read) | ||
731 | *mem = rbuf[1]; | ||
732 | |||
733 | return 0; | ||
734 | err: | ||
735 | deb_info("%s: ci usb write returned %d\n", __func__, ret); | ||
736 | return ret; | ||
737 | |||
738 | } | ||
739 | |||
675 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) | 740 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) |
676 | { | 741 | { |
677 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; | 742 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; |
@@ -1350,9 +1415,12 @@ static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap) | |||
1350 | struct i2c_adapter *adapter; | 1415 | struct i2c_adapter *adapter; |
1351 | struct i2c_client *client_demod; | 1416 | struct i2c_client *client_demod; |
1352 | struct i2c_client *client_tuner; | 1417 | struct i2c_client *client_tuner; |
1418 | struct i2c_client *client_ci; | ||
1353 | struct i2c_board_info info; | 1419 | struct i2c_board_info info; |
1354 | struct si2168_config si2168_config; | 1420 | struct si2168_config si2168_config; |
1355 | struct si2157_config si2157_config; | 1421 | struct si2157_config si2157_config; |
1422 | struct sp2_config sp2_config; | ||
1423 | u8 o[2], i; | ||
1356 | 1424 | ||
1357 | /* reset the tuner */ | 1425 | /* reset the tuner */ |
1358 | if (cxusb_tt_ct2_4400_gpio_tuner(d, 0) < 0) { | 1426 | if (cxusb_tt_ct2_4400_gpio_tuner(d, 0) < 0) { |
@@ -1369,6 +1437,7 @@ static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap) | |||
1369 | /* attach frontend */ | 1437 | /* attach frontend */ |
1370 | si2168_config.i2c_adapter = &adapter; | 1438 | si2168_config.i2c_adapter = &adapter; |
1371 | si2168_config.fe = &adap->fe_adap[0].fe; | 1439 | si2168_config.fe = &adap->fe_adap[0].fe; |
1440 | si2168_config.ts_mode = SI2168_TS_PARALLEL; | ||
1372 | memset(&info, 0, sizeof(struct i2c_board_info)); | 1441 | memset(&info, 0, sizeof(struct i2c_board_info)); |
1373 | strlcpy(info.type, "si2168", I2C_NAME_SIZE); | 1442 | strlcpy(info.type, "si2168", I2C_NAME_SIZE); |
1374 | info.addr = 0x64; | 1443 | info.addr = 0x64; |
@@ -1408,6 +1477,48 @@ static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap) | |||
1408 | 1477 | ||
1409 | st->i2c_client_tuner = client_tuner; | 1478 | st->i2c_client_tuner = client_tuner; |
1410 | 1479 | ||
1480 | /* initialize CI */ | ||
1481 | if (d->udev->descriptor.idProduct == | ||
1482 | USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI) { | ||
1483 | |||
1484 | memcpy(o, "\xc0\x01", 2); | ||
1485 | cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); | ||
1486 | msleep(100); | ||
1487 | |||
1488 | memcpy(o, "\xc0\x00", 2); | ||
1489 | cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); | ||
1490 | msleep(100); | ||
1491 | |||
1492 | memset(&sp2_config, 0, sizeof(sp2_config)); | ||
1493 | sp2_config.dvb_adap = &adap->dvb_adap; | ||
1494 | sp2_config.priv = d; | ||
1495 | sp2_config.ci_control = cxusb_tt_ct2_4650_ci_ctrl; | ||
1496 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
1497 | strlcpy(info.type, "sp2", I2C_NAME_SIZE); | ||
1498 | info.addr = 0x40; | ||
1499 | info.platform_data = &sp2_config; | ||
1500 | request_module(info.type); | ||
1501 | client_ci = i2c_new_device(&d->i2c_adap, &info); | ||
1502 | if (client_ci == NULL || client_ci->dev.driver == NULL) { | ||
1503 | module_put(client_tuner->dev.driver->owner); | ||
1504 | i2c_unregister_device(client_tuner); | ||
1505 | module_put(client_demod->dev.driver->owner); | ||
1506 | i2c_unregister_device(client_demod); | ||
1507 | return -ENODEV; | ||
1508 | } | ||
1509 | if (!try_module_get(client_ci->dev.driver->owner)) { | ||
1510 | i2c_unregister_device(client_ci); | ||
1511 | module_put(client_tuner->dev.driver->owner); | ||
1512 | i2c_unregister_device(client_tuner); | ||
1513 | module_put(client_demod->dev.driver->owner); | ||
1514 | i2c_unregister_device(client_demod); | ||
1515 | return -ENODEV; | ||
1516 | } | ||
1517 | |||
1518 | st->i2c_client_ci = client_ci; | ||
1519 | |||
1520 | } | ||
1521 | |||
1411 | return 0; | 1522 | return 0; |
1412 | } | 1523 | } |
1413 | 1524 | ||
@@ -1537,6 +1648,13 @@ static void cxusb_disconnect(struct usb_interface *intf) | |||
1537 | struct cxusb_state *st = d->priv; | 1648 | struct cxusb_state *st = d->priv; |
1538 | struct i2c_client *client; | 1649 | struct i2c_client *client; |
1539 | 1650 | ||
1651 | /* remove I2C client for CI */ | ||
1652 | client = st->i2c_client_ci; | ||
1653 | if (client) { | ||
1654 | module_put(client->dev.driver->owner); | ||
1655 | i2c_unregister_device(client); | ||
1656 | } | ||
1657 | |||
1540 | /* remove I2C client for tuner */ | 1658 | /* remove I2C client for tuner */ |
1541 | client = st->i2c_client_tuner; | 1659 | client = st->i2c_client_tuner; |
1542 | if (client) { | 1660 | if (client) { |
@@ -1576,6 +1694,7 @@ static struct usb_device_id cxusb_table [] = { | |||
1576 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, | 1694 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, |
1577 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) }, | 1695 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) }, |
1578 | { USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) }, | 1696 | { USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) }, |
1697 | { USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI) }, | ||
1579 | {} /* Terminating entry */ | 1698 | {} /* Terminating entry */ |
1580 | }; | 1699 | }; |
1581 | MODULE_DEVICE_TABLE (usb, cxusb_table); | 1700 | MODULE_DEVICE_TABLE (usb, cxusb_table); |
@@ -2230,6 +2349,8 @@ static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = { | |||
2230 | .size_of_priv = sizeof(struct cxusb_state), | 2349 | .size_of_priv = sizeof(struct cxusb_state), |
2231 | 2350 | ||
2232 | .num_adapters = 1, | 2351 | .num_adapters = 1, |
2352 | .read_mac_address = cxusb_tt_ct2_4400_read_mac_address, | ||
2353 | |||
2233 | .adapter = { | 2354 | .adapter = { |
2234 | { | 2355 | { |
2235 | .num_frontends = 1, | 2356 | .num_frontends = 1, |
@@ -2265,13 +2386,18 @@ static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = { | |||
2265 | .rc_interval = 150, | 2386 | .rc_interval = 150, |
2266 | }, | 2387 | }, |
2267 | 2388 | ||
2268 | .num_device_descs = 1, | 2389 | .num_device_descs = 2, |
2269 | .devices = { | 2390 | .devices = { |
2270 | { | 2391 | { |
2271 | "TechnoTrend TVStick CT2-4400", | 2392 | "TechnoTrend TVStick CT2-4400", |
2272 | { NULL }, | 2393 | { NULL }, |
2273 | { &cxusb_table[20], NULL }, | 2394 | { &cxusb_table[20], NULL }, |
2274 | }, | 2395 | }, |
2396 | { | ||
2397 | "TechnoTrend TT-connect CT2-4650 CI", | ||
2398 | { NULL }, | ||
2399 | { &cxusb_table[21], NULL }, | ||
2400 | }, | ||
2275 | } | 2401 | } |
2276 | }; | 2402 | }; |
2277 | 2403 | ||