18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for DVBSky USB2.0 receiver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013 Max nibble <nibble.max@gmail.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "dvb_usb.h" 98c2ecf20Sopenharmony_ci#include "m88ds3103.h" 108c2ecf20Sopenharmony_ci#include "ts2020.h" 118c2ecf20Sopenharmony_ci#include "sp2.h" 128c2ecf20Sopenharmony_ci#include "si2168.h" 138c2ecf20Sopenharmony_ci#include "si2157.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define DVBSKY_MSG_DELAY 0/*2000*/ 168c2ecf20Sopenharmony_ci#define DVBSKY_BUF_LEN 64 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic int dvb_usb_dvbsky_disable_rc; 198c2ecf20Sopenharmony_cimodule_param_named(disable_rc, dvb_usb_dvbsky_disable_rc, int, 0644); 208c2ecf20Sopenharmony_ciMODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver."); 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct dvbsky_state { 258c2ecf20Sopenharmony_ci u8 ibuf[DVBSKY_BUF_LEN]; 268c2ecf20Sopenharmony_ci u8 obuf[DVBSKY_BUF_LEN]; 278c2ecf20Sopenharmony_ci u8 last_lock; 288c2ecf20Sopenharmony_ci struct i2c_client *i2c_client_demod; 298c2ecf20Sopenharmony_ci struct i2c_client *i2c_client_tuner; 308c2ecf20Sopenharmony_ci struct i2c_client *i2c_client_ci; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci /* fe hook functions*/ 338c2ecf20Sopenharmony_ci int (*fe_set_voltage)(struct dvb_frontend *fe, 348c2ecf20Sopenharmony_ci enum fe_sec_voltage voltage); 358c2ecf20Sopenharmony_ci int (*fe_read_status)(struct dvb_frontend *fe, 368c2ecf20Sopenharmony_ci enum fe_status *status); 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int dvbsky_usb_generic_rw(struct dvb_usb_device *d, 408c2ecf20Sopenharmony_ci u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci int ret; 438c2ecf20Sopenharmony_ci struct dvbsky_state *state = d_to_priv(d); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci mutex_lock(&d->usb_mutex); 468c2ecf20Sopenharmony_ci if (wlen != 0) 478c2ecf20Sopenharmony_ci memcpy(state->obuf, wbuf, wlen); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci ret = dvb_usbv2_generic_rw_locked(d, state->obuf, wlen, 508c2ecf20Sopenharmony_ci state->ibuf, rlen); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (!ret && (rlen != 0)) 538c2ecf20Sopenharmony_ci memcpy(rbuf, state->ibuf, rlen); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci mutex_unlock(&d->usb_mutex); 568c2ecf20Sopenharmony_ci return ret; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci struct dvbsky_state *state = d_to_priv(d); 628c2ecf20Sopenharmony_ci static const u8 obuf_pre[3] = { 0x37, 0, 0 }; 638c2ecf20Sopenharmony_ci static const u8 obuf_post[3] = { 0x36, 3, 0 }; 648c2ecf20Sopenharmony_ci int ret; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci mutex_lock(&d->usb_mutex); 678c2ecf20Sopenharmony_ci memcpy(state->obuf, obuf_pre, 3); 688c2ecf20Sopenharmony_ci ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3); 698c2ecf20Sopenharmony_ci if (!ret && onoff) { 708c2ecf20Sopenharmony_ci msleep(20); 718c2ecf20Sopenharmony_ci memcpy(state->obuf, obuf_post, 3); 728c2ecf20Sopenharmony_ci ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3); 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci mutex_unlock(&d->usb_mutex); 758c2ecf20Sopenharmony_ci return ret; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct dvb_usb_device *d = fe_to_d(fe); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci return dvbsky_stream_ctrl(d, (onoff == 0) ? 0 : 1); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* GPIO */ 868c2ecf20Sopenharmony_cistatic int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci int ret; 898c2ecf20Sopenharmony_ci u8 obuf[3], ibuf[2]; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci obuf[0] = 0x0e; 928c2ecf20Sopenharmony_ci obuf[1] = gport; 938c2ecf20Sopenharmony_ci obuf[2] = value; 948c2ecf20Sopenharmony_ci ret = dvbsky_usb_generic_rw(d, obuf, 3, ibuf, 1); 958c2ecf20Sopenharmony_ci return ret; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/* I2C */ 998c2ecf20Sopenharmony_cistatic int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], 1008c2ecf20Sopenharmony_ci int num) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci struct dvb_usb_device *d = i2c_get_adapdata(adap); 1038c2ecf20Sopenharmony_ci int ret = 0; 1048c2ecf20Sopenharmony_ci u8 ibuf[64], obuf[64]; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 1078c2ecf20Sopenharmony_ci return -EAGAIN; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if (num > 2) { 1108c2ecf20Sopenharmony_ci dev_err(&d->udev->dev, 1118c2ecf20Sopenharmony_ci "too many i2c messages[%d], max 2.", num); 1128c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 1138c2ecf20Sopenharmony_ci goto i2c_error; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (num == 1) { 1178c2ecf20Sopenharmony_ci if (msg[0].len > 60) { 1188c2ecf20Sopenharmony_ci dev_err(&d->udev->dev, 1198c2ecf20Sopenharmony_ci "too many i2c bytes[%d], max 60.", 1208c2ecf20Sopenharmony_ci msg[0].len); 1218c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 1228c2ecf20Sopenharmony_ci goto i2c_error; 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci if (msg[0].flags & I2C_M_RD) { 1258c2ecf20Sopenharmony_ci /* single read */ 1268c2ecf20Sopenharmony_ci obuf[0] = 0x09; 1278c2ecf20Sopenharmony_ci obuf[1] = 0; 1288c2ecf20Sopenharmony_ci obuf[2] = msg[0].len; 1298c2ecf20Sopenharmony_ci obuf[3] = msg[0].addr; 1308c2ecf20Sopenharmony_ci ret = dvbsky_usb_generic_rw(d, obuf, 4, 1318c2ecf20Sopenharmony_ci ibuf, msg[0].len + 1); 1328c2ecf20Sopenharmony_ci if (!ret) 1338c2ecf20Sopenharmony_ci memcpy(msg[0].buf, &ibuf[1], msg[0].len); 1348c2ecf20Sopenharmony_ci } else { 1358c2ecf20Sopenharmony_ci /* write */ 1368c2ecf20Sopenharmony_ci obuf[0] = 0x08; 1378c2ecf20Sopenharmony_ci obuf[1] = msg[0].addr; 1388c2ecf20Sopenharmony_ci obuf[2] = msg[0].len; 1398c2ecf20Sopenharmony_ci memcpy(&obuf[3], msg[0].buf, msg[0].len); 1408c2ecf20Sopenharmony_ci ret = dvbsky_usb_generic_rw(d, obuf, 1418c2ecf20Sopenharmony_ci msg[0].len + 3, ibuf, 1); 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci } else { 1448c2ecf20Sopenharmony_ci if ((msg[0].len > 60) || (msg[1].len > 60)) { 1458c2ecf20Sopenharmony_ci dev_err(&d->udev->dev, 1468c2ecf20Sopenharmony_ci "too many i2c bytes[w-%d][r-%d], max 60.", 1478c2ecf20Sopenharmony_ci msg[0].len, msg[1].len); 1488c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 1498c2ecf20Sopenharmony_ci goto i2c_error; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci /* write then read */ 1528c2ecf20Sopenharmony_ci obuf[0] = 0x09; 1538c2ecf20Sopenharmony_ci obuf[1] = msg[0].len; 1548c2ecf20Sopenharmony_ci obuf[2] = msg[1].len; 1558c2ecf20Sopenharmony_ci obuf[3] = msg[0].addr; 1568c2ecf20Sopenharmony_ci memcpy(&obuf[4], msg[0].buf, msg[0].len); 1578c2ecf20Sopenharmony_ci ret = dvbsky_usb_generic_rw(d, obuf, 1588c2ecf20Sopenharmony_ci msg[0].len + 4, ibuf, msg[1].len + 1); 1598c2ecf20Sopenharmony_ci if (!ret) 1608c2ecf20Sopenharmony_ci memcpy(msg[1].buf, &ibuf[1], msg[1].len); 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_cii2c_error: 1638c2ecf20Sopenharmony_ci mutex_unlock(&d->i2c_mutex); 1648c2ecf20Sopenharmony_ci return (ret) ? ret : num; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic u32 dvbsky_i2c_func(struct i2c_adapter *adapter) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci return I2C_FUNC_I2C; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic struct i2c_algorithm dvbsky_i2c_algo = { 1738c2ecf20Sopenharmony_ci .master_xfer = dvbsky_i2c_xfer, 1748c2ecf20Sopenharmony_ci .functionality = dvbsky_i2c_func, 1758c2ecf20Sopenharmony_ci}; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_RC_CORE) 1788c2ecf20Sopenharmony_cistatic int dvbsky_rc_query(struct dvb_usb_device *d) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci u32 code = 0xffff, scancode; 1818c2ecf20Sopenharmony_ci u8 rc5_command, rc5_system; 1828c2ecf20Sopenharmony_ci u8 obuf[2], ibuf[2], toggle; 1838c2ecf20Sopenharmony_ci int ret; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci obuf[0] = 0x10; 1868c2ecf20Sopenharmony_ci ret = dvbsky_usb_generic_rw(d, obuf, 1, ibuf, 2); 1878c2ecf20Sopenharmony_ci if (ret == 0) 1888c2ecf20Sopenharmony_ci code = (ibuf[0] << 8) | ibuf[1]; 1898c2ecf20Sopenharmony_ci if (code != 0xffff) { 1908c2ecf20Sopenharmony_ci dev_dbg(&d->udev->dev, "rc code: %x\n", code); 1918c2ecf20Sopenharmony_ci rc5_command = code & 0x3F; 1928c2ecf20Sopenharmony_ci rc5_system = (code & 0x7C0) >> 6; 1938c2ecf20Sopenharmony_ci toggle = (code & 0x800) ? 1 : 0; 1948c2ecf20Sopenharmony_ci scancode = rc5_system << 8 | rc5_command; 1958c2ecf20Sopenharmony_ci rc_keydown(d->rc_dev, RC_PROTO_RC5, scancode, toggle); 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci return 0; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci if (dvb_usb_dvbsky_disable_rc) { 2038c2ecf20Sopenharmony_ci rc->map_name = NULL; 2048c2ecf20Sopenharmony_ci return 0; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci rc->allowed_protos = RC_PROTO_BIT_RC5; 2088c2ecf20Sopenharmony_ci rc->query = dvbsky_rc_query; 2098c2ecf20Sopenharmony_ci rc->interval = 300; 2108c2ecf20Sopenharmony_ci return 0; 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci#else 2138c2ecf20Sopenharmony_ci #define dvbsky_get_rc_config NULL 2148c2ecf20Sopenharmony_ci#endif 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic int dvbsky_usb_set_voltage(struct dvb_frontend *fe, 2178c2ecf20Sopenharmony_ci enum fe_sec_voltage voltage) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci struct dvb_usb_device *d = fe_to_d(fe); 2208c2ecf20Sopenharmony_ci struct dvbsky_state *state = d_to_priv(d); 2218c2ecf20Sopenharmony_ci u8 value; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci if (voltage == SEC_VOLTAGE_OFF) 2248c2ecf20Sopenharmony_ci value = 0; 2258c2ecf20Sopenharmony_ci else 2268c2ecf20Sopenharmony_ci value = 1; 2278c2ecf20Sopenharmony_ci dvbsky_gpio_ctrl(d, 0x80, value); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci return state->fe_set_voltage(fe, voltage); 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic int dvbsky_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6]) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 2358c2ecf20Sopenharmony_ci u8 obuf[] = { 0x1e, 0x00 }; 2368c2ecf20Sopenharmony_ci u8 ibuf[6] = { 0 }; 2378c2ecf20Sopenharmony_ci struct i2c_msg msg[] = { 2388c2ecf20Sopenharmony_ci { 2398c2ecf20Sopenharmony_ci .addr = 0x51, 2408c2ecf20Sopenharmony_ci .flags = 0, 2418c2ecf20Sopenharmony_ci .buf = obuf, 2428c2ecf20Sopenharmony_ci .len = 2, 2438c2ecf20Sopenharmony_ci }, { 2448c2ecf20Sopenharmony_ci .addr = 0x51, 2458c2ecf20Sopenharmony_ci .flags = I2C_M_RD, 2468c2ecf20Sopenharmony_ci .buf = ibuf, 2478c2ecf20Sopenharmony_ci .len = 6, 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci }; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (i2c_transfer(&d->i2c_adap, msg, 2) == 2) 2528c2ecf20Sopenharmony_ci memcpy(mac, ibuf, 6); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci return 0; 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic int dvbsky_usb_read_status(struct dvb_frontend *fe, 2588c2ecf20Sopenharmony_ci enum fe_status *status) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci struct dvb_usb_device *d = fe_to_d(fe); 2618c2ecf20Sopenharmony_ci struct dvbsky_state *state = d_to_priv(d); 2628c2ecf20Sopenharmony_ci int ret; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci ret = state->fe_read_status(fe, status); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* it need resync slave fifo when signal change from unlock to lock.*/ 2678c2ecf20Sopenharmony_ci if ((*status & FE_HAS_LOCK) && (!state->last_lock)) 2688c2ecf20Sopenharmony_ci dvbsky_stream_ctrl(d, 1); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci state->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0; 2718c2ecf20Sopenharmony_ci return ret; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic int dvbsky_s960_attach(struct dvb_usb_adapter *adap) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct dvbsky_state *state = adap_to_priv(adap); 2778c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 2788c2ecf20Sopenharmony_ci struct i2c_adapter *i2c_adapter; 2798c2ecf20Sopenharmony_ci struct m88ds3103_platform_data m88ds3103_pdata = {}; 2808c2ecf20Sopenharmony_ci struct ts2020_config ts2020_config = {}; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* attach demod */ 2838c2ecf20Sopenharmony_ci m88ds3103_pdata.clk = 27000000; 2848c2ecf20Sopenharmony_ci m88ds3103_pdata.i2c_wr_max = 33; 2858c2ecf20Sopenharmony_ci m88ds3103_pdata.clk_out = 0; 2868c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_mode = M88DS3103_TS_CI; 2878c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_clk = 16000; 2888c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_clk_pol = 0; 2898c2ecf20Sopenharmony_ci m88ds3103_pdata.agc = 0x99; 2908c2ecf20Sopenharmony_ci m88ds3103_pdata.lnb_hv_pol = 1, 2918c2ecf20Sopenharmony_ci m88ds3103_pdata.lnb_en_pol = 1, 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci state->i2c_client_demod = dvb_module_probe("m88ds3103", NULL, 2948c2ecf20Sopenharmony_ci &d->i2c_adap, 2958c2ecf20Sopenharmony_ci 0x68, &m88ds3103_pdata); 2968c2ecf20Sopenharmony_ci if (!state->i2c_client_demod) 2978c2ecf20Sopenharmony_ci return -ENODEV; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod); 3008c2ecf20Sopenharmony_ci i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci /* attach tuner */ 3038c2ecf20Sopenharmony_ci ts2020_config.fe = adap->fe[0]; 3048c2ecf20Sopenharmony_ci ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci state->i2c_client_tuner = dvb_module_probe("ts2020", NULL, 3078c2ecf20Sopenharmony_ci i2c_adapter, 3088c2ecf20Sopenharmony_ci 0x60, &ts2020_config); 3098c2ecf20Sopenharmony_ci if (!state->i2c_client_tuner) { 3108c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_demod); 3118c2ecf20Sopenharmony_ci return -ENODEV; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci /* delegate signal strength measurement to tuner */ 3158c2ecf20Sopenharmony_ci adap->fe[0]->ops.read_signal_strength = 3168c2ecf20Sopenharmony_ci adap->fe[0]->ops.tuner_ops.get_rf_strength; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* hook fe: need to resync the slave fifo when signal locks. */ 3198c2ecf20Sopenharmony_ci state->fe_read_status = adap->fe[0]->ops.read_status; 3208c2ecf20Sopenharmony_ci adap->fe[0]->ops.read_status = dvbsky_usb_read_status; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* hook fe: LNB off/on is control by Cypress usb chip. */ 3238c2ecf20Sopenharmony_ci state->fe_set_voltage = adap->fe[0]->ops.set_voltage; 3248c2ecf20Sopenharmony_ci adap->fe[0]->ops.set_voltage = dvbsky_usb_set_voltage; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci return 0; 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic int dvbsky_usb_ci_set_voltage(struct dvb_frontend *fe, 3308c2ecf20Sopenharmony_ci enum fe_sec_voltage voltage) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci struct dvb_usb_device *d = fe_to_d(fe); 3338c2ecf20Sopenharmony_ci struct dvbsky_state *state = d_to_priv(d); 3348c2ecf20Sopenharmony_ci u8 value; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (voltage == SEC_VOLTAGE_OFF) 3378c2ecf20Sopenharmony_ci value = 0; 3388c2ecf20Sopenharmony_ci else 3398c2ecf20Sopenharmony_ci value = 1; 3408c2ecf20Sopenharmony_ci dvbsky_gpio_ctrl(d, 0x00, value); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci return state->fe_set_voltage(fe, voltage); 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic int dvbsky_ci_ctrl(void *priv, u8 read, int addr, 3468c2ecf20Sopenharmony_ci u8 data, int *mem) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci struct dvb_usb_device *d = priv; 3498c2ecf20Sopenharmony_ci int ret = 0; 3508c2ecf20Sopenharmony_ci u8 command[4], respond[2], command_size, respond_size; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/ 3538c2ecf20Sopenharmony_ci command[2] = (u8)(addr & 0xff); /*low part of address*/ 3548c2ecf20Sopenharmony_ci if (read) { 3558c2ecf20Sopenharmony_ci command[0] = 0x71; 3568c2ecf20Sopenharmony_ci command_size = 3; 3578c2ecf20Sopenharmony_ci respond_size = 2; 3588c2ecf20Sopenharmony_ci } else { 3598c2ecf20Sopenharmony_ci command[0] = 0x70; 3608c2ecf20Sopenharmony_ci command[3] = data; 3618c2ecf20Sopenharmony_ci command_size = 4; 3628c2ecf20Sopenharmony_ci respond_size = 1; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci ret = dvbsky_usb_generic_rw(d, command, command_size, 3658c2ecf20Sopenharmony_ci respond, respond_size); 3668c2ecf20Sopenharmony_ci if (ret) 3678c2ecf20Sopenharmony_ci goto err; 3688c2ecf20Sopenharmony_ci if (read) 3698c2ecf20Sopenharmony_ci *mem = respond[1]; 3708c2ecf20Sopenharmony_ci return ret; 3718c2ecf20Sopenharmony_cierr: 3728c2ecf20Sopenharmony_ci dev_err(&d->udev->dev, "ci control failed=%d\n", ret); 3738c2ecf20Sopenharmony_ci return ret; 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic int dvbsky_s960c_attach(struct dvb_usb_adapter *adap) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci struct dvbsky_state *state = adap_to_priv(adap); 3798c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 3808c2ecf20Sopenharmony_ci struct i2c_adapter *i2c_adapter; 3818c2ecf20Sopenharmony_ci struct m88ds3103_platform_data m88ds3103_pdata = {}; 3828c2ecf20Sopenharmony_ci struct ts2020_config ts2020_config = {}; 3838c2ecf20Sopenharmony_ci struct sp2_config sp2_config = {}; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci /* attach demod */ 3868c2ecf20Sopenharmony_ci m88ds3103_pdata.clk = 27000000, 3878c2ecf20Sopenharmony_ci m88ds3103_pdata.i2c_wr_max = 33, 3888c2ecf20Sopenharmony_ci m88ds3103_pdata.clk_out = 0, 3898c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_mode = M88DS3103_TS_CI, 3908c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_clk = 10000, 3918c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_clk_pol = 1, 3928c2ecf20Sopenharmony_ci m88ds3103_pdata.agc = 0x99, 3938c2ecf20Sopenharmony_ci m88ds3103_pdata.lnb_hv_pol = 0, 3948c2ecf20Sopenharmony_ci m88ds3103_pdata.lnb_en_pol = 1, 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci state->i2c_client_demod = dvb_module_probe("m88ds3103", NULL, 3978c2ecf20Sopenharmony_ci &d->i2c_adap, 3988c2ecf20Sopenharmony_ci 0x68, &m88ds3103_pdata); 3998c2ecf20Sopenharmony_ci if (!state->i2c_client_demod) 4008c2ecf20Sopenharmony_ci return -ENODEV; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod); 4038c2ecf20Sopenharmony_ci i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci /* attach tuner */ 4068c2ecf20Sopenharmony_ci ts2020_config.fe = adap->fe[0]; 4078c2ecf20Sopenharmony_ci ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci state->i2c_client_tuner = dvb_module_probe("ts2020", NULL, 4108c2ecf20Sopenharmony_ci i2c_adapter, 4118c2ecf20Sopenharmony_ci 0x60, &ts2020_config); 4128c2ecf20Sopenharmony_ci if (!state->i2c_client_tuner) { 4138c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_demod); 4148c2ecf20Sopenharmony_ci return -ENODEV; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci /* attach ci controller */ 4188c2ecf20Sopenharmony_ci sp2_config.dvb_adap = &adap->dvb_adap; 4198c2ecf20Sopenharmony_ci sp2_config.priv = d; 4208c2ecf20Sopenharmony_ci sp2_config.ci_control = dvbsky_ci_ctrl; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci state->i2c_client_ci = dvb_module_probe("sp2", NULL, 4238c2ecf20Sopenharmony_ci &d->i2c_adap, 4248c2ecf20Sopenharmony_ci 0x40, &sp2_config); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if (!state->i2c_client_ci) { 4278c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_tuner); 4288c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_demod); 4298c2ecf20Sopenharmony_ci return -ENODEV; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci /* delegate signal strength measurement to tuner */ 4338c2ecf20Sopenharmony_ci adap->fe[0]->ops.read_signal_strength = 4348c2ecf20Sopenharmony_ci adap->fe[0]->ops.tuner_ops.get_rf_strength; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci /* hook fe: need to resync the slave fifo when signal locks. */ 4378c2ecf20Sopenharmony_ci state->fe_read_status = adap->fe[0]->ops.read_status; 4388c2ecf20Sopenharmony_ci adap->fe[0]->ops.read_status = dvbsky_usb_read_status; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci /* hook fe: LNB off/on is control by Cypress usb chip. */ 4418c2ecf20Sopenharmony_ci state->fe_set_voltage = adap->fe[0]->ops.set_voltage; 4428c2ecf20Sopenharmony_ci adap->fe[0]->ops.set_voltage = dvbsky_usb_ci_set_voltage; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci return 0; 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistatic int dvbsky_t680c_attach(struct dvb_usb_adapter *adap) 4488c2ecf20Sopenharmony_ci{ 4498c2ecf20Sopenharmony_ci struct dvbsky_state *state = adap_to_priv(adap); 4508c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 4518c2ecf20Sopenharmony_ci struct i2c_adapter *i2c_adapter; 4528c2ecf20Sopenharmony_ci struct si2168_config si2168_config = {}; 4538c2ecf20Sopenharmony_ci struct si2157_config si2157_config = {}; 4548c2ecf20Sopenharmony_ci struct sp2_config sp2_config = {}; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci /* attach demod */ 4578c2ecf20Sopenharmony_ci si2168_config.i2c_adapter = &i2c_adapter; 4588c2ecf20Sopenharmony_ci si2168_config.fe = &adap->fe[0]; 4598c2ecf20Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_PARALLEL; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci state->i2c_client_demod = dvb_module_probe("si2168", NULL, 4628c2ecf20Sopenharmony_ci &d->i2c_adap, 4638c2ecf20Sopenharmony_ci 0x64, &si2168_config); 4648c2ecf20Sopenharmony_ci if (!state->i2c_client_demod) 4658c2ecf20Sopenharmony_ci return -ENODEV; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci /* attach tuner */ 4688c2ecf20Sopenharmony_ci si2157_config.fe = adap->fe[0]; 4698c2ecf20Sopenharmony_ci si2157_config.if_port = 1; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci state->i2c_client_tuner = dvb_module_probe("si2157", NULL, 4728c2ecf20Sopenharmony_ci i2c_adapter, 4738c2ecf20Sopenharmony_ci 0x60, &si2157_config); 4748c2ecf20Sopenharmony_ci if (!state->i2c_client_tuner) { 4758c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_demod); 4768c2ecf20Sopenharmony_ci return -ENODEV; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci /* attach ci controller */ 4808c2ecf20Sopenharmony_ci sp2_config.dvb_adap = &adap->dvb_adap; 4818c2ecf20Sopenharmony_ci sp2_config.priv = d; 4828c2ecf20Sopenharmony_ci sp2_config.ci_control = dvbsky_ci_ctrl; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci state->i2c_client_ci = dvb_module_probe("sp2", NULL, 4858c2ecf20Sopenharmony_ci &d->i2c_adap, 4868c2ecf20Sopenharmony_ci 0x40, &sp2_config); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci if (!state->i2c_client_ci) { 4898c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_tuner); 4908c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_demod); 4918c2ecf20Sopenharmony_ci return -ENODEV; 4928c2ecf20Sopenharmony_ci } 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci return 0; 4958c2ecf20Sopenharmony_ci} 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistatic int dvbsky_t330_attach(struct dvb_usb_adapter *adap) 4988c2ecf20Sopenharmony_ci{ 4998c2ecf20Sopenharmony_ci struct dvbsky_state *state = adap_to_priv(adap); 5008c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 5018c2ecf20Sopenharmony_ci struct i2c_adapter *i2c_adapter; 5028c2ecf20Sopenharmony_ci struct si2168_config si2168_config = {}; 5038c2ecf20Sopenharmony_ci struct si2157_config si2157_config = {}; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* attach demod */ 5068c2ecf20Sopenharmony_ci si2168_config.i2c_adapter = &i2c_adapter; 5078c2ecf20Sopenharmony_ci si2168_config.fe = &adap->fe[0]; 5088c2ecf20Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_PARALLEL; 5098c2ecf20Sopenharmony_ci si2168_config.ts_clock_gapped = true; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci state->i2c_client_demod = dvb_module_probe("si2168", NULL, 5128c2ecf20Sopenharmony_ci &d->i2c_adap, 5138c2ecf20Sopenharmony_ci 0x64, &si2168_config); 5148c2ecf20Sopenharmony_ci if (!state->i2c_client_demod) 5158c2ecf20Sopenharmony_ci return -ENODEV; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci /* attach tuner */ 5188c2ecf20Sopenharmony_ci si2157_config.fe = adap->fe[0]; 5198c2ecf20Sopenharmony_ci si2157_config.if_port = 1; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci state->i2c_client_tuner = dvb_module_probe("si2157", NULL, 5228c2ecf20Sopenharmony_ci i2c_adapter, 5238c2ecf20Sopenharmony_ci 0x60, &si2157_config); 5248c2ecf20Sopenharmony_ci if (!state->i2c_client_tuner) { 5258c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_demod); 5268c2ecf20Sopenharmony_ci return -ENODEV; 5278c2ecf20Sopenharmony_ci } 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci return 0; 5308c2ecf20Sopenharmony_ci} 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_cistatic int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap) 5338c2ecf20Sopenharmony_ci{ 5348c2ecf20Sopenharmony_ci struct dvbsky_state *state = adap_to_priv(adap); 5358c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 5368c2ecf20Sopenharmony_ci struct i2c_adapter *i2c_adapter; 5378c2ecf20Sopenharmony_ci struct si2168_config si2168_config = {}; 5388c2ecf20Sopenharmony_ci struct si2157_config si2157_config = {}; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci /* attach demod */ 5418c2ecf20Sopenharmony_ci si2168_config.i2c_adapter = &i2c_adapter; 5428c2ecf20Sopenharmony_ci si2168_config.fe = &adap->fe[0]; 5438c2ecf20Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_PARALLEL; 5448c2ecf20Sopenharmony_ci if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2) 5458c2ecf20Sopenharmony_ci si2168_config.ts_mode |= SI2168_TS_CLK_MANUAL; 5468c2ecf20Sopenharmony_ci si2168_config.ts_clock_inv = 1; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci state->i2c_client_demod = dvb_module_probe("si2168", NULL, 5498c2ecf20Sopenharmony_ci &d->i2c_adap, 5508c2ecf20Sopenharmony_ci 0x64, &si2168_config); 5518c2ecf20Sopenharmony_ci if (!state->i2c_client_demod) 5528c2ecf20Sopenharmony_ci return -ENODEV; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* attach tuner */ 5558c2ecf20Sopenharmony_ci si2157_config.fe = adap->fe[0]; 5568c2ecf20Sopenharmony_ci if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230) { 5578c2ecf20Sopenharmony_ci si2157_config.if_port = 1; 5588c2ecf20Sopenharmony_ci state->i2c_client_tuner = dvb_module_probe("si2157", NULL, 5598c2ecf20Sopenharmony_ci i2c_adapter, 5608c2ecf20Sopenharmony_ci 0x60, 5618c2ecf20Sopenharmony_ci &si2157_config); 5628c2ecf20Sopenharmony_ci } else { 5638c2ecf20Sopenharmony_ci si2157_config.if_port = 0; 5648c2ecf20Sopenharmony_ci state->i2c_client_tuner = dvb_module_probe("si2157", "si2141", 5658c2ecf20Sopenharmony_ci i2c_adapter, 5668c2ecf20Sopenharmony_ci 0x60, 5678c2ecf20Sopenharmony_ci &si2157_config); 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci if (!state->i2c_client_tuner) { 5708c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_demod); 5718c2ecf20Sopenharmony_ci return -ENODEV; 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci return 0; 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cistatic int dvbsky_identify_state(struct dvb_usb_device *d, const char **name) 5798c2ecf20Sopenharmony_ci{ 5808c2ecf20Sopenharmony_ci dvbsky_gpio_ctrl(d, 0x04, 1); 5818c2ecf20Sopenharmony_ci msleep(20); 5828c2ecf20Sopenharmony_ci dvbsky_gpio_ctrl(d, 0x83, 0); 5838c2ecf20Sopenharmony_ci dvbsky_gpio_ctrl(d, 0xc0, 1); 5848c2ecf20Sopenharmony_ci msleep(100); 5858c2ecf20Sopenharmony_ci dvbsky_gpio_ctrl(d, 0x83, 1); 5868c2ecf20Sopenharmony_ci dvbsky_gpio_ctrl(d, 0xc0, 0); 5878c2ecf20Sopenharmony_ci msleep(50); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci return WARM; 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_cistatic int dvbsky_init(struct dvb_usb_device *d) 5938c2ecf20Sopenharmony_ci{ 5948c2ecf20Sopenharmony_ci struct dvbsky_state *state = d_to_priv(d); 5958c2ecf20Sopenharmony_ci state->last_lock = 0; 5968c2ecf20Sopenharmony_ci return 0; 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_cistatic int dvbsky_frontend_detach(struct dvb_usb_adapter *adap) 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 6028c2ecf20Sopenharmony_ci struct dvbsky_state *state = d_to_priv(d); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_tuner); 6078c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_demod); 6088c2ecf20Sopenharmony_ci dvb_module_release(state->i2c_client_ci); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci return 0; 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci/* DVB USB Driver stuff */ 6148c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties dvbsky_s960_props = { 6158c2ecf20Sopenharmony_ci .driver_name = KBUILD_MODNAME, 6168c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6178c2ecf20Sopenharmony_ci .adapter_nr = adapter_nr, 6188c2ecf20Sopenharmony_ci .size_of_priv = sizeof(struct dvbsky_state), 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 6218c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint_response = 0x81, 6228c2ecf20Sopenharmony_ci .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci .i2c_algo = &dvbsky_i2c_algo, 6258c2ecf20Sopenharmony_ci .frontend_attach = dvbsky_s960_attach, 6268c2ecf20Sopenharmony_ci .frontend_detach = dvbsky_frontend_detach, 6278c2ecf20Sopenharmony_ci .init = dvbsky_init, 6288c2ecf20Sopenharmony_ci .get_rc_config = dvbsky_get_rc_config, 6298c2ecf20Sopenharmony_ci .streaming_ctrl = dvbsky_streaming_ctrl, 6308c2ecf20Sopenharmony_ci .identify_state = dvbsky_identify_state, 6318c2ecf20Sopenharmony_ci .read_mac_address = dvbsky_read_mac_addr, 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci .num_adapters = 1, 6348c2ecf20Sopenharmony_ci .adapter = { 6358c2ecf20Sopenharmony_ci { 6368c2ecf20Sopenharmony_ci .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci } 6398c2ecf20Sopenharmony_ci}; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties dvbsky_s960c_props = { 6428c2ecf20Sopenharmony_ci .driver_name = KBUILD_MODNAME, 6438c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6448c2ecf20Sopenharmony_ci .adapter_nr = adapter_nr, 6458c2ecf20Sopenharmony_ci .size_of_priv = sizeof(struct dvbsky_state), 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 6488c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint_response = 0x81, 6498c2ecf20Sopenharmony_ci .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci .i2c_algo = &dvbsky_i2c_algo, 6528c2ecf20Sopenharmony_ci .frontend_attach = dvbsky_s960c_attach, 6538c2ecf20Sopenharmony_ci .frontend_detach = dvbsky_frontend_detach, 6548c2ecf20Sopenharmony_ci .init = dvbsky_init, 6558c2ecf20Sopenharmony_ci .get_rc_config = dvbsky_get_rc_config, 6568c2ecf20Sopenharmony_ci .streaming_ctrl = dvbsky_streaming_ctrl, 6578c2ecf20Sopenharmony_ci .identify_state = dvbsky_identify_state, 6588c2ecf20Sopenharmony_ci .read_mac_address = dvbsky_read_mac_addr, 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci .num_adapters = 1, 6618c2ecf20Sopenharmony_ci .adapter = { 6628c2ecf20Sopenharmony_ci { 6638c2ecf20Sopenharmony_ci .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 6648c2ecf20Sopenharmony_ci } 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci}; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties dvbsky_t680c_props = { 6698c2ecf20Sopenharmony_ci .driver_name = KBUILD_MODNAME, 6708c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6718c2ecf20Sopenharmony_ci .adapter_nr = adapter_nr, 6728c2ecf20Sopenharmony_ci .size_of_priv = sizeof(struct dvbsky_state), 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 6758c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint_response = 0x81, 6768c2ecf20Sopenharmony_ci .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci .i2c_algo = &dvbsky_i2c_algo, 6798c2ecf20Sopenharmony_ci .frontend_attach = dvbsky_t680c_attach, 6808c2ecf20Sopenharmony_ci .frontend_detach = dvbsky_frontend_detach, 6818c2ecf20Sopenharmony_ci .init = dvbsky_init, 6828c2ecf20Sopenharmony_ci .get_rc_config = dvbsky_get_rc_config, 6838c2ecf20Sopenharmony_ci .streaming_ctrl = dvbsky_streaming_ctrl, 6848c2ecf20Sopenharmony_ci .identify_state = dvbsky_identify_state, 6858c2ecf20Sopenharmony_ci .read_mac_address = dvbsky_read_mac_addr, 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci .num_adapters = 1, 6888c2ecf20Sopenharmony_ci .adapter = { 6898c2ecf20Sopenharmony_ci { 6908c2ecf20Sopenharmony_ci .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci}; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties dvbsky_t330_props = { 6968c2ecf20Sopenharmony_ci .driver_name = KBUILD_MODNAME, 6978c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6988c2ecf20Sopenharmony_ci .adapter_nr = adapter_nr, 6998c2ecf20Sopenharmony_ci .size_of_priv = sizeof(struct dvbsky_state), 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 7028c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint_response = 0x81, 7038c2ecf20Sopenharmony_ci .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci .i2c_algo = &dvbsky_i2c_algo, 7068c2ecf20Sopenharmony_ci .frontend_attach = dvbsky_t330_attach, 7078c2ecf20Sopenharmony_ci .frontend_detach = dvbsky_frontend_detach, 7088c2ecf20Sopenharmony_ci .init = dvbsky_init, 7098c2ecf20Sopenharmony_ci .get_rc_config = dvbsky_get_rc_config, 7108c2ecf20Sopenharmony_ci .streaming_ctrl = dvbsky_streaming_ctrl, 7118c2ecf20Sopenharmony_ci .identify_state = dvbsky_identify_state, 7128c2ecf20Sopenharmony_ci .read_mac_address = dvbsky_read_mac_addr, 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci .num_adapters = 1, 7158c2ecf20Sopenharmony_ci .adapter = { 7168c2ecf20Sopenharmony_ci { 7178c2ecf20Sopenharmony_ci .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 7188c2ecf20Sopenharmony_ci } 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci}; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties mygica_t230c_props = { 7238c2ecf20Sopenharmony_ci .driver_name = KBUILD_MODNAME, 7248c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 7258c2ecf20Sopenharmony_ci .adapter_nr = adapter_nr, 7268c2ecf20Sopenharmony_ci .size_of_priv = sizeof(struct dvbsky_state), 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 7298c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint_response = 0x81, 7308c2ecf20Sopenharmony_ci .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci .i2c_algo = &dvbsky_i2c_algo, 7338c2ecf20Sopenharmony_ci .frontend_attach = dvbsky_mygica_t230c_attach, 7348c2ecf20Sopenharmony_ci .frontend_detach = dvbsky_frontend_detach, 7358c2ecf20Sopenharmony_ci .init = dvbsky_init, 7368c2ecf20Sopenharmony_ci .get_rc_config = dvbsky_get_rc_config, 7378c2ecf20Sopenharmony_ci .streaming_ctrl = dvbsky_streaming_ctrl, 7388c2ecf20Sopenharmony_ci .identify_state = dvbsky_identify_state, 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci .num_adapters = 1, 7418c2ecf20Sopenharmony_ci .adapter = { 7428c2ecf20Sopenharmony_ci { 7438c2ecf20Sopenharmony_ci .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci } 7468c2ecf20Sopenharmony_ci}; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_cistatic const struct usb_device_id dvbsky_id_table[] = { 7498c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(0x0572, 0x6831, 7508c2ecf20Sopenharmony_ci &dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) }, 7518c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(0x0572, 0x960c, 7528c2ecf20Sopenharmony_ci &dvbsky_s960c_props, "DVBSky S960CI", RC_MAP_DVBSKY) }, 7538c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(0x0572, 0x680c, 7548c2ecf20Sopenharmony_ci &dvbsky_t680c_props, "DVBSky T680CI", RC_MAP_DVBSKY) }, 7558c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(0x0572, 0x0320, 7568c2ecf20Sopenharmony_ci &dvbsky_t330_props, "DVBSky T330", RC_MAP_DVBSKY) }, 7578c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TECHNOTREND, 7588c2ecf20Sopenharmony_ci USB_PID_TECHNOTREND_TVSTICK_CT2_4400, 7598c2ecf20Sopenharmony_ci &dvbsky_t330_props, "TechnoTrend TVStick CT2-4400", 7608c2ecf20Sopenharmony_ci RC_MAP_TT_1500) }, 7618c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TECHNOTREND, 7628c2ecf20Sopenharmony_ci USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI, 7638c2ecf20Sopenharmony_ci &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI", 7648c2ecf20Sopenharmony_ci RC_MAP_TT_1500) }, 7658c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TECHNOTREND, 7668c2ecf20Sopenharmony_ci USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2, 7678c2ecf20Sopenharmony_ci &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI v1.1", 7688c2ecf20Sopenharmony_ci RC_MAP_TT_1500) }, 7698c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TECHNOTREND, 7708c2ecf20Sopenharmony_ci USB_PID_TECHNOTREND_CONNECT_S2_4650_CI, 7718c2ecf20Sopenharmony_ci &dvbsky_s960c_props, "TechnoTrend TT-connect S2-4650 CI", 7728c2ecf20Sopenharmony_ci RC_MAP_TT_1500) }, 7738c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TERRATEC, 7748c2ecf20Sopenharmony_ci USB_PID_TERRATEC_H7_3, 7758c2ecf20Sopenharmony_ci &dvbsky_t680c_props, "Terratec H7 Rev.4", 7768c2ecf20Sopenharmony_ci RC_MAP_TT_1500) }, 7778c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4, 7788c2ecf20Sopenharmony_ci &dvbsky_s960_props, "Terratec Cinergy S2 Rev.4", 7798c2ecf20Sopenharmony_ci RC_MAP_DVBSKY) }, 7808c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230, 7818c2ecf20Sopenharmony_ci &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230", 7828c2ecf20Sopenharmony_ci RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, 7838c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C, 7848c2ecf20Sopenharmony_ci &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C", 7858c2ecf20Sopenharmony_ci RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, 7868c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C_LITE, 7878c2ecf20Sopenharmony_ci &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C Lite", 7888c2ecf20Sopenharmony_ci NULL) }, 7898c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2, 7908c2ecf20Sopenharmony_ci &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C v2", 7918c2ecf20Sopenharmony_ci RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, 7928c2ecf20Sopenharmony_ci { } 7938c2ecf20Sopenharmony_ci}; 7948c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, dvbsky_id_table); 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_cistatic struct usb_driver dvbsky_usb_driver = { 7978c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 7988c2ecf20Sopenharmony_ci .id_table = dvbsky_id_table, 7998c2ecf20Sopenharmony_ci .probe = dvb_usbv2_probe, 8008c2ecf20Sopenharmony_ci .disconnect = dvb_usbv2_disconnect, 8018c2ecf20Sopenharmony_ci .suspend = dvb_usbv2_suspend, 8028c2ecf20Sopenharmony_ci .resume = dvb_usbv2_resume, 8038c2ecf20Sopenharmony_ci .reset_resume = dvb_usbv2_reset_resume, 8048c2ecf20Sopenharmony_ci .no_dynamic_id = 1, 8058c2ecf20Sopenharmony_ci .soft_unbind = 1, 8068c2ecf20Sopenharmony_ci}; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_cimodule_usb_driver(dvbsky_usb_driver); 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ciMODULE_AUTHOR("Max nibble <nibble.max@gmail.com>"); 8118c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Driver for DVBSky USB"); 8128c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 813