| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* DVB USB framework compliant Linux driver for the |
|---|
| 2 | 3 | * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, |
|---|
| 3 | 4 | * TeVii S421, S480, S482, S600, S630, S632, S650, S660, S662, |
|---|
| .. | .. |
|---|
| 7 | 8 | * Terratec Cinergy S2 cards |
|---|
| 8 | 9 | * Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by) |
|---|
| 9 | 10 | * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 11 | | - * under the terms of the GNU General Public License as published by the |
|---|
| 12 | | - * Free Software Foundation, version 2. |
|---|
| 13 | | - * |
|---|
| 14 | | - * see Documentation/media/dvb-drivers/dvb-usb.rst for more information |
|---|
| 11 | + * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information |
|---|
| 15 | 12 | */ |
|---|
| 16 | 13 | #include <media/dvb-usb-ids.h> |
|---|
| 17 | 14 | #include "dw2102.h" |
|---|
| .. | .. |
|---|
| 958 | 955 | } |
|---|
| 959 | 956 | |
|---|
| 960 | 957 | static int su3000_identify_state(struct usb_device *udev, |
|---|
| 961 | | - struct dvb_usb_device_properties *props, |
|---|
| 962 | | - struct dvb_usb_device_description **desc, |
|---|
| 958 | + const struct dvb_usb_device_properties *props, |
|---|
| 959 | + const struct dvb_usb_device_description **desc, |
|---|
| 963 | 960 | int *cold) |
|---|
| 964 | 961 | { |
|---|
| 965 | 962 | info("%s", __func__); |
|---|
| .. | .. |
|---|
| 1527 | 1524 | return -EIO; |
|---|
| 1528 | 1525 | } |
|---|
| 1529 | 1526 | |
|---|
| 1527 | +static int tt_s2_4600_frontend_attach_probe_demod(struct dvb_usb_device *d, |
|---|
| 1528 | + const int probe_addr) |
|---|
| 1529 | +{ |
|---|
| 1530 | + struct dw2102_state *state = d->priv; |
|---|
| 1531 | + |
|---|
| 1532 | + state->data[0] = 0x9; |
|---|
| 1533 | + state->data[1] = 0x1; |
|---|
| 1534 | + state->data[2] = 0x1; |
|---|
| 1535 | + state->data[3] = probe_addr; |
|---|
| 1536 | + state->data[4] = 0x0; |
|---|
| 1537 | + |
|---|
| 1538 | + if (dvb_usb_generic_rw(d, state->data, 5, state->data, 2, 0) < 0) { |
|---|
| 1539 | + err("i2c probe for address 0x%x failed.", probe_addr); |
|---|
| 1540 | + return 0; |
|---|
| 1541 | + } |
|---|
| 1542 | + |
|---|
| 1543 | + if (state->data[0] != 8) /* fail(7) or error, no device at address */ |
|---|
| 1544 | + return 0; |
|---|
| 1545 | + |
|---|
| 1546 | + /* probing successful */ |
|---|
| 1547 | + return 1; |
|---|
| 1548 | +} |
|---|
| 1549 | + |
|---|
| 1530 | 1550 | static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap) |
|---|
| 1531 | 1551 | { |
|---|
| 1532 | 1552 | struct dvb_usb_device *d = adap->dev; |
|---|
| .. | .. |
|---|
| 1536 | 1556 | struct i2c_board_info board_info; |
|---|
| 1537 | 1557 | struct m88ds3103_platform_data m88ds3103_pdata = {}; |
|---|
| 1538 | 1558 | struct ts2020_config ts2020_config = {}; |
|---|
| 1559 | + int demod_addr; |
|---|
| 1539 | 1560 | |
|---|
| 1540 | 1561 | mutex_lock(&d->data_mutex); |
|---|
| 1541 | 1562 | |
|---|
| .. | .. |
|---|
| 1573 | 1594 | if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0) |
|---|
| 1574 | 1595 | err("command 0x51 transfer failed."); |
|---|
| 1575 | 1596 | |
|---|
| 1597 | + /* probe for demodulator i2c address */ |
|---|
| 1598 | + demod_addr = -1; |
|---|
| 1599 | + if (tt_s2_4600_frontend_attach_probe_demod(d, 0x68)) |
|---|
| 1600 | + demod_addr = 0x68; |
|---|
| 1601 | + else if (tt_s2_4600_frontend_attach_probe_demod(d, 0x69)) |
|---|
| 1602 | + demod_addr = 0x69; |
|---|
| 1603 | + else if (tt_s2_4600_frontend_attach_probe_demod(d, 0x6a)) |
|---|
| 1604 | + demod_addr = 0x6a; |
|---|
| 1605 | + |
|---|
| 1576 | 1606 | mutex_unlock(&d->data_mutex); |
|---|
| 1607 | + |
|---|
| 1608 | + if (demod_addr < 0) { |
|---|
| 1609 | + err("probing for demodulator failed. Is the external power switched on?"); |
|---|
| 1610 | + return -ENODEV; |
|---|
| 1611 | + } |
|---|
| 1577 | 1612 | |
|---|
| 1578 | 1613 | /* attach demod */ |
|---|
| 1579 | 1614 | m88ds3103_pdata.clk = 27000000; |
|---|
| .. | .. |
|---|
| 1589 | 1624 | m88ds3103_pdata.lnb_hv_pol = 1; |
|---|
| 1590 | 1625 | m88ds3103_pdata.lnb_en_pol = 0; |
|---|
| 1591 | 1626 | memset(&board_info, 0, sizeof(board_info)); |
|---|
| 1592 | | - strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); |
|---|
| 1593 | | - board_info.addr = 0x68; |
|---|
| 1627 | + if (demod_addr == 0x6a) |
|---|
| 1628 | + strscpy(board_info.type, "m88ds3103b", I2C_NAME_SIZE); |
|---|
| 1629 | + else |
|---|
| 1630 | + strscpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); |
|---|
| 1631 | + board_info.addr = demod_addr; |
|---|
| 1594 | 1632 | board_info.platform_data = &m88ds3103_pdata; |
|---|
| 1595 | 1633 | request_module("m88ds3103"); |
|---|
| 1596 | | - client = i2c_new_device(&d->i2c_adap, &board_info); |
|---|
| 1597 | | - if (client == NULL || client->dev.driver == NULL) |
|---|
| 1634 | + client = i2c_new_client_device(&d->i2c_adap, &board_info); |
|---|
| 1635 | + if (!i2c_client_has_driver(client)) |
|---|
| 1598 | 1636 | return -ENODEV; |
|---|
| 1599 | 1637 | if (!try_module_get(client->dev.driver->owner)) { |
|---|
| 1600 | 1638 | i2c_unregister_device(client); |
|---|
| .. | .. |
|---|
| 1608 | 1646 | /* attach tuner */ |
|---|
| 1609 | 1647 | ts2020_config.fe = adap->fe_adap[0].fe; |
|---|
| 1610 | 1648 | memset(&board_info, 0, sizeof(board_info)); |
|---|
| 1611 | | - strlcpy(board_info.type, "ts2022", I2C_NAME_SIZE); |
|---|
| 1649 | + strscpy(board_info.type, "ts2022", I2C_NAME_SIZE); |
|---|
| 1612 | 1650 | board_info.addr = 0x60; |
|---|
| 1613 | 1651 | board_info.platform_data = &ts2020_config; |
|---|
| 1614 | 1652 | request_module("ts2020"); |
|---|
| 1615 | | - client = i2c_new_device(i2c_adapter, &board_info); |
|---|
| 1653 | + client = i2c_new_client_device(i2c_adapter, &board_info); |
|---|
| 1616 | 1654 | |
|---|
| 1617 | | - if (client == NULL || client->dev.driver == NULL) { |
|---|
| 1655 | + if (!i2c_client_has_driver(client)) { |
|---|
| 1618 | 1656 | dvb_frontend_detach(adap->fe_adap[0].fe); |
|---|
| 1619 | 1657 | return -ENODEV; |
|---|
| 1620 | 1658 | } |
|---|
| .. | .. |
|---|
| 1741 | 1779 | TERRATEC_CINERGY_S2_R2, |
|---|
| 1742 | 1780 | TERRATEC_CINERGY_S2_R3, |
|---|
| 1743 | 1781 | TERRATEC_CINERGY_S2_R4, |
|---|
| 1782 | + TERRATEC_CINERGY_S2_1, |
|---|
| 1783 | + TERRATEC_CINERGY_S2_2, |
|---|
| 1744 | 1784 | GOTVIEW_SAT_HD, |
|---|
| 1745 | 1785 | GENIATECH_T220, |
|---|
| 1746 | 1786 | TECHNOTREND_S2_4600, |
|---|
| .. | .. |
|---|
| 1768 | 1808 | [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)}, |
|---|
| 1769 | 1809 | [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)}, |
|---|
| 1770 | 1810 | [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, |
|---|
| 1771 | | - [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R2)}, |
|---|
| 1772 | | - [TERRATEC_CINERGY_S2_R3] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R3)}, |
|---|
| 1773 | | - [TERRATEC_CINERGY_S2_R4] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4)}, |
|---|
| 1811 | + [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, |
|---|
| 1812 | + USB_PID_TERRATEC_CINERGY_S2_R2)}, |
|---|
| 1813 | + [TERRATEC_CINERGY_S2_R3] = {USB_DEVICE(USB_VID_TERRATEC, |
|---|
| 1814 | + USB_PID_TERRATEC_CINERGY_S2_R3)}, |
|---|
| 1815 | + [TERRATEC_CINERGY_S2_R4] = {USB_DEVICE(USB_VID_TERRATEC, |
|---|
| 1816 | + USB_PID_TERRATEC_CINERGY_S2_R4)}, |
|---|
| 1817 | + [TERRATEC_CINERGY_S2_1] = {USB_DEVICE(USB_VID_TERRATEC_2, |
|---|
| 1818 | + USB_PID_TERRATEC_CINERGY_S2_1)}, |
|---|
| 1819 | + [TERRATEC_CINERGY_S2_2] = {USB_DEVICE(USB_VID_TERRATEC_2, |
|---|
| 1820 | + USB_PID_TERRATEC_CINERGY_S2_2)}, |
|---|
| 1774 | 1821 | [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, |
|---|
| 1775 | 1822 | [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, |
|---|
| 1776 | 1823 | [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND, |
|---|
| .. | .. |
|---|
| 1839 | 1886 | switch (le16_to_cpu(dev->descriptor.idProduct)) { |
|---|
| 1840 | 1887 | case USB_PID_TEVII_S650: |
|---|
| 1841 | 1888 | dw2104_properties.rc.core.rc_codes = RC_MAP_TEVII_NEC; |
|---|
| 1842 | | - /* fall through */ |
|---|
| 1889 | + fallthrough; |
|---|
| 1843 | 1890 | case USB_PID_DW2104: |
|---|
| 1844 | 1891 | reset = 1; |
|---|
| 1845 | 1892 | dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, |
|---|
| 1846 | 1893 | DW210X_WRITE_MSG); |
|---|
| 1847 | | - /* fall through */ |
|---|
| 1894 | + fallthrough; |
|---|
| 1848 | 1895 | case USB_PID_DW3101: |
|---|
| 1849 | 1896 | reset = 0; |
|---|
| 1850 | 1897 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, |
|---|
| .. | .. |
|---|
| 1877 | 1924 | break; |
|---|
| 1878 | 1925 | } |
|---|
| 1879 | 1926 | } |
|---|
| 1880 | | - /* fall through */ |
|---|
| 1927 | + fallthrough; |
|---|
| 1881 | 1928 | case 0x2101: |
|---|
| 1882 | 1929 | dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, |
|---|
| 1883 | 1930 | DW210X_READ_MSG); |
|---|
| .. | .. |
|---|
| 2290 | 2337 | }}, |
|---|
| 2291 | 2338 | } |
|---|
| 2292 | 2339 | }, |
|---|
| 2293 | | - .num_device_descs = 6, |
|---|
| 2340 | + .num_device_descs = 8, |
|---|
| 2294 | 2341 | .devices = { |
|---|
| 2295 | 2342 | { "SU3000HD DVB-S USB2.0", |
|---|
| 2296 | 2343 | { &dw2102_table[GENIATECH_SU3000], NULL }, |
|---|
| .. | .. |
|---|
| 2312 | 2359 | { &dw2102_table[TERRATEC_CINERGY_S2_R3], NULL }, |
|---|
| 2313 | 2360 | { NULL }, |
|---|
| 2314 | 2361 | }, |
|---|
| 2362 | + { "Terratec Cinergy S2 PCIe Dual Port 1", |
|---|
| 2363 | + { &dw2102_table[TERRATEC_CINERGY_S2_1], NULL }, |
|---|
| 2364 | + { NULL }, |
|---|
| 2365 | + }, |
|---|
| 2366 | + { "Terratec Cinergy S2 PCIe Dual Port 2", |
|---|
| 2367 | + { &dw2102_table[TERRATEC_CINERGY_S2_2], NULL }, |
|---|
| 2368 | + { NULL }, |
|---|
| 2369 | + }, |
|---|
| 2315 | 2370 | { "GOTVIEW Satellite HD", |
|---|
| 2316 | 2371 | { &dw2102_table[GOTVIEW_SAT_HD], NULL }, |
|---|
| 2317 | 2372 | { NULL }, |
|---|