1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2af64fb3fSnibble.max /* 3af64fb3fSnibble.max * Driver for DVBSky USB2.0 receiver 4af64fb3fSnibble.max * 5af64fb3fSnibble.max * Copyright (C) 2013 Max nibble <nibble.max@gmail.com> 6af64fb3fSnibble.max */ 7af64fb3fSnibble.max 8af64fb3fSnibble.max #include "dvb_usb.h" 9af64fb3fSnibble.max #include "m88ds3103.h" 10f31a6386SAntti Palosaari #include "ts2020.h" 1124d333f3Snibble.max #include "sp2.h" 12b43a590dSNibble Max #include "si2168.h" 13b43a590dSNibble Max #include "si2157.h" 14af64fb3fSnibble.max 15af64fb3fSnibble.max #define DVBSKY_MSG_DELAY 0/*2000*/ 16af64fb3fSnibble.max #define DVBSKY_BUF_LEN 64 17af64fb3fSnibble.max 1869e7b650SOlli Salonen static int dvb_usb_dvbsky_disable_rc; 1969e7b650SOlli Salonen module_param_named(disable_rc, dvb_usb_dvbsky_disable_rc, int, 0644); 2069e7b650SOlli Salonen MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver."); 2169e7b650SOlli Salonen 22af64fb3fSnibble.max DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 23af64fb3fSnibble.max 24af64fb3fSnibble.max struct dvbsky_state { 25af64fb3fSnibble.max u8 ibuf[DVBSKY_BUF_LEN]; 26af64fb3fSnibble.max u8 obuf[DVBSKY_BUF_LEN]; 27af64fb3fSnibble.max u8 last_lock; 28b43a590dSNibble Max struct i2c_client *i2c_client_demod; 29af64fb3fSnibble.max struct i2c_client *i2c_client_tuner; 3024d333f3Snibble.max struct i2c_client *i2c_client_ci; 31af64fb3fSnibble.max 32af64fb3fSnibble.max /* fe hook functions*/ 33af64fb3fSnibble.max int (*fe_set_voltage)(struct dvb_frontend *fe, 340df289a2SMauro Carvalho Chehab enum fe_sec_voltage voltage); 35af64fb3fSnibble.max int (*fe_read_status)(struct dvb_frontend *fe, 360df289a2SMauro Carvalho Chehab enum fe_status *status); 37af64fb3fSnibble.max }; 38af64fb3fSnibble.max 39af64fb3fSnibble.max static int dvbsky_usb_generic_rw(struct dvb_usb_device *d, 40af64fb3fSnibble.max u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) 41af64fb3fSnibble.max { 42af64fb3fSnibble.max int ret; 43af64fb3fSnibble.max struct dvbsky_state *state = d_to_priv(d); 44af64fb3fSnibble.max 45af64fb3fSnibble.max mutex_lock(&d->usb_mutex); 46af64fb3fSnibble.max if (wlen != 0) 47af64fb3fSnibble.max memcpy(state->obuf, wbuf, wlen); 48af64fb3fSnibble.max 49af64fb3fSnibble.max ret = dvb_usbv2_generic_rw_locked(d, state->obuf, wlen, 50af64fb3fSnibble.max state->ibuf, rlen); 51af64fb3fSnibble.max 52af64fb3fSnibble.max if (!ret && (rlen != 0)) 53af64fb3fSnibble.max memcpy(rbuf, state->ibuf, rlen); 54af64fb3fSnibble.max 55af64fb3fSnibble.max mutex_unlock(&d->usb_mutex); 56af64fb3fSnibble.max return ret; 57af64fb3fSnibble.max } 58af64fb3fSnibble.max 59af64fb3fSnibble.max static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff) 60af64fb3fSnibble.max { 619afc8219SMauro Carvalho Chehab struct dvbsky_state *state = d_to_priv(d); 62cecf0bbbSAndrei Koshkosh static const u8 obuf_pre[3] = { 0x37, 0, 0 }; 63cecf0bbbSAndrei Koshkosh static const u8 obuf_post[3] = { 0x36, 3, 0 }; 64af64fb3fSnibble.max int ret; 65af64fb3fSnibble.max 66cecf0bbbSAndrei Koshkosh mutex_lock(&d->usb_mutex); 67cecf0bbbSAndrei Koshkosh memcpy(state->obuf, obuf_pre, 3); 68cecf0bbbSAndrei Koshkosh ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3); 69af64fb3fSnibble.max if (!ret && onoff) { 70af64fb3fSnibble.max msleep(20); 71cecf0bbbSAndrei Koshkosh memcpy(state->obuf, obuf_post, 3); 72cecf0bbbSAndrei Koshkosh ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3); 73af64fb3fSnibble.max } 74cecf0bbbSAndrei Koshkosh mutex_unlock(&d->usb_mutex); 75af64fb3fSnibble.max return ret; 76af64fb3fSnibble.max } 77af64fb3fSnibble.max 78af64fb3fSnibble.max static int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff) 79af64fb3fSnibble.max { 80af64fb3fSnibble.max struct dvb_usb_device *d = fe_to_d(fe); 81af64fb3fSnibble.max 82af64fb3fSnibble.max return dvbsky_stream_ctrl(d, (onoff == 0) ? 0 : 1); 83af64fb3fSnibble.max } 84af64fb3fSnibble.max 85af64fb3fSnibble.max /* GPIO */ 86af64fb3fSnibble.max static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value) 87af64fb3fSnibble.max { 88af64fb3fSnibble.max int ret; 89af64fb3fSnibble.max u8 obuf[3], ibuf[2]; 90af64fb3fSnibble.max 91af64fb3fSnibble.max obuf[0] = 0x0e; 92af64fb3fSnibble.max obuf[1] = gport; 93af64fb3fSnibble.max obuf[2] = value; 94af64fb3fSnibble.max ret = dvbsky_usb_generic_rw(d, obuf, 3, ibuf, 1); 95af64fb3fSnibble.max return ret; 96af64fb3fSnibble.max } 97af64fb3fSnibble.max 98af64fb3fSnibble.max /* I2C */ 99af64fb3fSnibble.max static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], 100af64fb3fSnibble.max int num) 101af64fb3fSnibble.max { 102af64fb3fSnibble.max struct dvb_usb_device *d = i2c_get_adapdata(adap); 103af64fb3fSnibble.max int ret = 0; 104af64fb3fSnibble.max u8 ibuf[64], obuf[64]; 105af64fb3fSnibble.max 106af64fb3fSnibble.max if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 107af64fb3fSnibble.max return -EAGAIN; 108af64fb3fSnibble.max 109af64fb3fSnibble.max if (num > 2) { 110af64fb3fSnibble.max dev_err(&d->udev->dev, 11140bba097SOlli Salonen "too many i2c messages[%d], max 2.", num); 112af64fb3fSnibble.max ret = -EOPNOTSUPP; 113af64fb3fSnibble.max goto i2c_error; 114af64fb3fSnibble.max } 115af64fb3fSnibble.max 116af64fb3fSnibble.max if (num == 1) { 117af64fb3fSnibble.max if (msg[0].len > 60) { 118af64fb3fSnibble.max dev_err(&d->udev->dev, 11940bba097SOlli Salonen "too many i2c bytes[%d], max 60.", 120af64fb3fSnibble.max msg[0].len); 121af64fb3fSnibble.max ret = -EOPNOTSUPP; 122af64fb3fSnibble.max goto i2c_error; 123af64fb3fSnibble.max } 124af64fb3fSnibble.max if (msg[0].flags & I2C_M_RD) { 125af64fb3fSnibble.max /* single read */ 126af64fb3fSnibble.max obuf[0] = 0x09; 127af64fb3fSnibble.max obuf[1] = 0; 128af64fb3fSnibble.max obuf[2] = msg[0].len; 129af64fb3fSnibble.max obuf[3] = msg[0].addr; 130af64fb3fSnibble.max ret = dvbsky_usb_generic_rw(d, obuf, 4, 131af64fb3fSnibble.max ibuf, msg[0].len + 1); 132af64fb3fSnibble.max if (!ret) 133af64fb3fSnibble.max memcpy(msg[0].buf, &ibuf[1], msg[0].len); 134af64fb3fSnibble.max } else { 135af64fb3fSnibble.max /* write */ 136af64fb3fSnibble.max obuf[0] = 0x08; 137af64fb3fSnibble.max obuf[1] = msg[0].addr; 138af64fb3fSnibble.max obuf[2] = msg[0].len; 139af64fb3fSnibble.max memcpy(&obuf[3], msg[0].buf, msg[0].len); 140af64fb3fSnibble.max ret = dvbsky_usb_generic_rw(d, obuf, 141af64fb3fSnibble.max msg[0].len + 3, ibuf, 1); 142af64fb3fSnibble.max } 143af64fb3fSnibble.max } else { 144af64fb3fSnibble.max if ((msg[0].len > 60) || (msg[1].len > 60)) { 145af64fb3fSnibble.max dev_err(&d->udev->dev, 14640bba097SOlli Salonen "too many i2c bytes[w-%d][r-%d], max 60.", 147af64fb3fSnibble.max msg[0].len, msg[1].len); 148af64fb3fSnibble.max ret = -EOPNOTSUPP; 149af64fb3fSnibble.max goto i2c_error; 150af64fb3fSnibble.max } 151af64fb3fSnibble.max /* write then read */ 152af64fb3fSnibble.max obuf[0] = 0x09; 153af64fb3fSnibble.max obuf[1] = msg[0].len; 154af64fb3fSnibble.max obuf[2] = msg[1].len; 155af64fb3fSnibble.max obuf[3] = msg[0].addr; 156af64fb3fSnibble.max memcpy(&obuf[4], msg[0].buf, msg[0].len); 157af64fb3fSnibble.max ret = dvbsky_usb_generic_rw(d, obuf, 158af64fb3fSnibble.max msg[0].len + 4, ibuf, msg[1].len + 1); 159af64fb3fSnibble.max if (!ret) 160af64fb3fSnibble.max memcpy(msg[1].buf, &ibuf[1], msg[1].len); 161af64fb3fSnibble.max } 162af64fb3fSnibble.max i2c_error: 163af64fb3fSnibble.max mutex_unlock(&d->i2c_mutex); 164af64fb3fSnibble.max return (ret) ? ret : num; 165af64fb3fSnibble.max } 166af64fb3fSnibble.max 167af64fb3fSnibble.max static u32 dvbsky_i2c_func(struct i2c_adapter *adapter) 168af64fb3fSnibble.max { 169af64fb3fSnibble.max return I2C_FUNC_I2C; 170af64fb3fSnibble.max } 171af64fb3fSnibble.max 172af64fb3fSnibble.max static struct i2c_algorithm dvbsky_i2c_algo = { 173af64fb3fSnibble.max .master_xfer = dvbsky_i2c_xfer, 174af64fb3fSnibble.max .functionality = dvbsky_i2c_func, 175af64fb3fSnibble.max }; 176af64fb3fSnibble.max 177af64fb3fSnibble.max #if IS_ENABLED(CONFIG_RC_CORE) 178af64fb3fSnibble.max static int dvbsky_rc_query(struct dvb_usb_device *d) 179af64fb3fSnibble.max { 180af64fb3fSnibble.max u32 code = 0xffff, scancode; 181af64fb3fSnibble.max u8 rc5_command, rc5_system; 182af64fb3fSnibble.max u8 obuf[2], ibuf[2], toggle; 183af64fb3fSnibble.max int ret; 184af64fb3fSnibble.max 185af64fb3fSnibble.max obuf[0] = 0x10; 186af64fb3fSnibble.max ret = dvbsky_usb_generic_rw(d, obuf, 1, ibuf, 2); 187af64fb3fSnibble.max if (ret == 0) 188af64fb3fSnibble.max code = (ibuf[0] << 8) | ibuf[1]; 189af64fb3fSnibble.max if (code != 0xffff) { 190af64fb3fSnibble.max dev_dbg(&d->udev->dev, "rc code: %x\n", code); 191af64fb3fSnibble.max rc5_command = code & 0x3F; 192af64fb3fSnibble.max rc5_system = (code & 0x7C0) >> 6; 193af64fb3fSnibble.max toggle = (code & 0x800) ? 1 : 0; 194af64fb3fSnibble.max scancode = rc5_system << 8 | rc5_command; 1956d741bfeSSean Young rc_keydown(d->rc_dev, RC_PROTO_RC5, scancode, toggle); 196af64fb3fSnibble.max } 197af64fb3fSnibble.max return 0; 198af64fb3fSnibble.max } 199af64fb3fSnibble.max 200af64fb3fSnibble.max static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) 201af64fb3fSnibble.max { 20269e7b650SOlli Salonen if (dvb_usb_dvbsky_disable_rc) { 20369e7b650SOlli Salonen rc->map_name = NULL; 20469e7b650SOlli Salonen return 0; 20569e7b650SOlli Salonen } 20669e7b650SOlli Salonen 2076d741bfeSSean Young rc->allowed_protos = RC_PROTO_BIT_RC5; 208af64fb3fSnibble.max rc->query = dvbsky_rc_query; 209af64fb3fSnibble.max rc->interval = 300; 210af64fb3fSnibble.max return 0; 211af64fb3fSnibble.max } 212af64fb3fSnibble.max #else 213af64fb3fSnibble.max #define dvbsky_get_rc_config NULL 214af64fb3fSnibble.max #endif 215af64fb3fSnibble.max 216af64fb3fSnibble.max static int dvbsky_usb_set_voltage(struct dvb_frontend *fe, 2170df289a2SMauro Carvalho Chehab enum fe_sec_voltage voltage) 218af64fb3fSnibble.max { 219af64fb3fSnibble.max struct dvb_usb_device *d = fe_to_d(fe); 220af64fb3fSnibble.max struct dvbsky_state *state = d_to_priv(d); 221af64fb3fSnibble.max u8 value; 222af64fb3fSnibble.max 223af64fb3fSnibble.max if (voltage == SEC_VOLTAGE_OFF) 224af64fb3fSnibble.max value = 0; 225af64fb3fSnibble.max else 226af64fb3fSnibble.max value = 1; 227af64fb3fSnibble.max dvbsky_gpio_ctrl(d, 0x80, value); 228af64fb3fSnibble.max 229af64fb3fSnibble.max return state->fe_set_voltage(fe, voltage); 230af64fb3fSnibble.max } 231af64fb3fSnibble.max 232af64fb3fSnibble.max static int dvbsky_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6]) 233af64fb3fSnibble.max { 234af64fb3fSnibble.max struct dvb_usb_device *d = adap_to_d(adap); 235af64fb3fSnibble.max u8 obuf[] = { 0x1e, 0x00 }; 236af64fb3fSnibble.max u8 ibuf[6] = { 0 }; 237af64fb3fSnibble.max struct i2c_msg msg[] = { 238af64fb3fSnibble.max { 239af64fb3fSnibble.max .addr = 0x51, 240af64fb3fSnibble.max .flags = 0, 241af64fb3fSnibble.max .buf = obuf, 242af64fb3fSnibble.max .len = 2, 243af64fb3fSnibble.max }, { 244af64fb3fSnibble.max .addr = 0x51, 245af64fb3fSnibble.max .flags = I2C_M_RD, 246af64fb3fSnibble.max .buf = ibuf, 247af64fb3fSnibble.max .len = 6, 248af64fb3fSnibble.max } 249af64fb3fSnibble.max }; 250af64fb3fSnibble.max 251af64fb3fSnibble.max if (i2c_transfer(&d->i2c_adap, msg, 2) == 2) 252af64fb3fSnibble.max memcpy(mac, ibuf, 6); 253af64fb3fSnibble.max 254af64fb3fSnibble.max return 0; 255af64fb3fSnibble.max } 256af64fb3fSnibble.max 2570df289a2SMauro Carvalho Chehab static int dvbsky_usb_read_status(struct dvb_frontend *fe, 2580df289a2SMauro Carvalho Chehab enum fe_status *status) 259af64fb3fSnibble.max { 260af64fb3fSnibble.max struct dvb_usb_device *d = fe_to_d(fe); 261af64fb3fSnibble.max struct dvbsky_state *state = d_to_priv(d); 262af64fb3fSnibble.max int ret; 263af64fb3fSnibble.max 264af64fb3fSnibble.max ret = state->fe_read_status(fe, status); 265af64fb3fSnibble.max 266af64fb3fSnibble.max /* it need resync slave fifo when signal change from unlock to lock.*/ 267af64fb3fSnibble.max if ((*status & FE_HAS_LOCK) && (!state->last_lock)) 268af64fb3fSnibble.max dvbsky_stream_ctrl(d, 1); 269af64fb3fSnibble.max 270af64fb3fSnibble.max state->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0; 271af64fb3fSnibble.max return ret; 272af64fb3fSnibble.max } 273af64fb3fSnibble.max 274af64fb3fSnibble.max static int dvbsky_s960_attach(struct dvb_usb_adapter *adap) 275af64fb3fSnibble.max { 276af64fb3fSnibble.max struct dvbsky_state *state = adap_to_priv(adap); 277af64fb3fSnibble.max struct dvb_usb_device *d = adap_to_d(adap); 2782c7e3ca8SMauro Carvalho Chehab struct i2c_adapter *i2c_adapter; 2792c7e3ca8SMauro Carvalho Chehab struct m88ds3103_platform_data m88ds3103_pdata = {}; 280f31a6386SAntti Palosaari struct ts2020_config ts2020_config = {}; 281af64fb3fSnibble.max 282af64fb3fSnibble.max /* attach demod */ 2832c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.clk = 27000000; 2842c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.i2c_wr_max = 33; 2852c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.clk_out = 0; 2862c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.ts_mode = M88DS3103_TS_CI; 2872c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.ts_clk = 16000; 2882c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.ts_clk_pol = 0; 2892c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.agc = 0x99; 2902c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.lnb_hv_pol = 1, 2912c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.lnb_en_pol = 1, 2922c7e3ca8SMauro Carvalho Chehab 2932c7e3ca8SMauro Carvalho Chehab state->i2c_client_demod = dvb_module_probe("m88ds3103", NULL, 294af64fb3fSnibble.max &d->i2c_adap, 2952c7e3ca8SMauro Carvalho Chehab 0x68, &m88ds3103_pdata); 2962c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_demod) 2972c7e3ca8SMauro Carvalho Chehab return -ENODEV; 2982c7e3ca8SMauro Carvalho Chehab 2992c7e3ca8SMauro Carvalho Chehab adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod); 3002c7e3ca8SMauro Carvalho Chehab i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod); 301af64fb3fSnibble.max 302af64fb3fSnibble.max /* attach tuner */ 303f31a6386SAntti Palosaari ts2020_config.fe = adap->fe[0]; 3040f91c9d6SDavid Howells ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm; 305af64fb3fSnibble.max 3062c7e3ca8SMauro Carvalho Chehab state->i2c_client_tuner = dvb_module_probe("ts2020", NULL, 3072c7e3ca8SMauro Carvalho Chehab i2c_adapter, 3082c7e3ca8SMauro Carvalho Chehab 0x60, &ts2020_config); 3092c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_tuner) { 3102c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_demod); 3112c7e3ca8SMauro Carvalho Chehab return -ENODEV; 312af64fb3fSnibble.max } 313af64fb3fSnibble.max 314af64fb3fSnibble.max /* delegate signal strength measurement to tuner */ 315af64fb3fSnibble.max adap->fe[0]->ops.read_signal_strength = 316af64fb3fSnibble.max adap->fe[0]->ops.tuner_ops.get_rf_strength; 317af64fb3fSnibble.max 318af64fb3fSnibble.max /* hook fe: need to resync the slave fifo when signal locks. */ 319af64fb3fSnibble.max state->fe_read_status = adap->fe[0]->ops.read_status; 320af64fb3fSnibble.max adap->fe[0]->ops.read_status = dvbsky_usb_read_status; 321af64fb3fSnibble.max 322af64fb3fSnibble.max /* hook fe: LNB off/on is control by Cypress usb chip. */ 323af64fb3fSnibble.max state->fe_set_voltage = adap->fe[0]->ops.set_voltage; 324af64fb3fSnibble.max adap->fe[0]->ops.set_voltage = dvbsky_usb_set_voltage; 325af64fb3fSnibble.max 3262c7e3ca8SMauro Carvalho Chehab return 0; 327af64fb3fSnibble.max } 328af64fb3fSnibble.max 32924d333f3Snibble.max static int dvbsky_usb_ci_set_voltage(struct dvb_frontend *fe, 3300df289a2SMauro Carvalho Chehab enum fe_sec_voltage voltage) 33124d333f3Snibble.max { 33224d333f3Snibble.max struct dvb_usb_device *d = fe_to_d(fe); 33324d333f3Snibble.max struct dvbsky_state *state = d_to_priv(d); 33424d333f3Snibble.max u8 value; 33524d333f3Snibble.max 33624d333f3Snibble.max if (voltage == SEC_VOLTAGE_OFF) 33724d333f3Snibble.max value = 0; 33824d333f3Snibble.max else 33924d333f3Snibble.max value = 1; 34024d333f3Snibble.max dvbsky_gpio_ctrl(d, 0x00, value); 34124d333f3Snibble.max 34224d333f3Snibble.max return state->fe_set_voltage(fe, voltage); 34324d333f3Snibble.max } 34424d333f3Snibble.max 34524d333f3Snibble.max static int dvbsky_ci_ctrl(void *priv, u8 read, int addr, 34624d333f3Snibble.max u8 data, int *mem) 34724d333f3Snibble.max { 34824d333f3Snibble.max struct dvb_usb_device *d = priv; 34924d333f3Snibble.max int ret = 0; 35024d333f3Snibble.max u8 command[4], respond[2], command_size, respond_size; 35124d333f3Snibble.max 35224d333f3Snibble.max command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/ 35324d333f3Snibble.max command[2] = (u8)(addr & 0xff); /*low part of address*/ 35424d333f3Snibble.max if (read) { 35524d333f3Snibble.max command[0] = 0x71; 35624d333f3Snibble.max command_size = 3; 35724d333f3Snibble.max respond_size = 2; 35824d333f3Snibble.max } else { 35924d333f3Snibble.max command[0] = 0x70; 36024d333f3Snibble.max command[3] = data; 36124d333f3Snibble.max command_size = 4; 36224d333f3Snibble.max respond_size = 1; 36324d333f3Snibble.max } 36424d333f3Snibble.max ret = dvbsky_usb_generic_rw(d, command, command_size, 36524d333f3Snibble.max respond, respond_size); 36624d333f3Snibble.max if (ret) 36724d333f3Snibble.max goto err; 36824d333f3Snibble.max if (read) 36924d333f3Snibble.max *mem = respond[1]; 37024d333f3Snibble.max return ret; 37124d333f3Snibble.max err: 37224d333f3Snibble.max dev_err(&d->udev->dev, "ci control failed=%d\n", ret); 37324d333f3Snibble.max return ret; 37424d333f3Snibble.max } 37524d333f3Snibble.max 37624d333f3Snibble.max static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap) 37724d333f3Snibble.max { 37824d333f3Snibble.max struct dvbsky_state *state = adap_to_priv(adap); 37924d333f3Snibble.max struct dvb_usb_device *d = adap_to_d(adap); 3802c7e3ca8SMauro Carvalho Chehab struct i2c_adapter *i2c_adapter; 3812c7e3ca8SMauro Carvalho Chehab struct m88ds3103_platform_data m88ds3103_pdata = {}; 382f31a6386SAntti Palosaari struct ts2020_config ts2020_config = {}; 3832c7e3ca8SMauro Carvalho Chehab struct sp2_config sp2_config = {}; 38424d333f3Snibble.max 38524d333f3Snibble.max /* attach demod */ 3862c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.clk = 27000000, 3872c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.i2c_wr_max = 33, 3882c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.clk_out = 0, 3892c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.ts_mode = M88DS3103_TS_CI, 3902c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.ts_clk = 10000, 3912c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.ts_clk_pol = 1, 3922c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.agc = 0x99, 3932c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.lnb_hv_pol = 0, 3942c7e3ca8SMauro Carvalho Chehab m88ds3103_pdata.lnb_en_pol = 1, 3952c7e3ca8SMauro Carvalho Chehab 3962c7e3ca8SMauro Carvalho Chehab state->i2c_client_demod = dvb_module_probe("m88ds3103", NULL, 39724d333f3Snibble.max &d->i2c_adap, 3982c7e3ca8SMauro Carvalho Chehab 0x68, &m88ds3103_pdata); 3992c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_demod) 4002c7e3ca8SMauro Carvalho Chehab return -ENODEV; 4012c7e3ca8SMauro Carvalho Chehab 4022c7e3ca8SMauro Carvalho Chehab adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod); 4032c7e3ca8SMauro Carvalho Chehab i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod); 40424d333f3Snibble.max 40524d333f3Snibble.max /* attach tuner */ 406f31a6386SAntti Palosaari ts2020_config.fe = adap->fe[0]; 4070f91c9d6SDavid Howells ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm; 40824d333f3Snibble.max 4092c7e3ca8SMauro Carvalho Chehab state->i2c_client_tuner = dvb_module_probe("ts2020", NULL, 4102c7e3ca8SMauro Carvalho Chehab i2c_adapter, 4112c7e3ca8SMauro Carvalho Chehab 0x60, &ts2020_config); 4122c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_tuner) { 4132c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_demod); 4142c7e3ca8SMauro Carvalho Chehab return -ENODEV; 41524d333f3Snibble.max } 41624d333f3Snibble.max 41724d333f3Snibble.max /* attach ci controller */ 41824d333f3Snibble.max sp2_config.dvb_adap = &adap->dvb_adap; 41924d333f3Snibble.max sp2_config.priv = d; 42024d333f3Snibble.max sp2_config.ci_control = dvbsky_ci_ctrl; 42124d333f3Snibble.max 4222c7e3ca8SMauro Carvalho Chehab state->i2c_client_ci = dvb_module_probe("sp2", NULL, 4232c7e3ca8SMauro Carvalho Chehab &d->i2c_adap, 4242c7e3ca8SMauro Carvalho Chehab 0x40, &sp2_config); 4252c7e3ca8SMauro Carvalho Chehab 4262c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_ci) { 4272c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_tuner); 4282c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_demod); 4292c7e3ca8SMauro Carvalho Chehab return -ENODEV; 43024d333f3Snibble.max } 43124d333f3Snibble.max 43224d333f3Snibble.max /* delegate signal strength measurement to tuner */ 43324d333f3Snibble.max adap->fe[0]->ops.read_signal_strength = 43424d333f3Snibble.max adap->fe[0]->ops.tuner_ops.get_rf_strength; 43524d333f3Snibble.max 43624d333f3Snibble.max /* hook fe: need to resync the slave fifo when signal locks. */ 43724d333f3Snibble.max state->fe_read_status = adap->fe[0]->ops.read_status; 43824d333f3Snibble.max adap->fe[0]->ops.read_status = dvbsky_usb_read_status; 43924d333f3Snibble.max 44024d333f3Snibble.max /* hook fe: LNB off/on is control by Cypress usb chip. */ 44124d333f3Snibble.max state->fe_set_voltage = adap->fe[0]->ops.set_voltage; 44224d333f3Snibble.max adap->fe[0]->ops.set_voltage = dvbsky_usb_ci_set_voltage; 44324d333f3Snibble.max 4442c7e3ca8SMauro Carvalho Chehab return 0; 44524d333f3Snibble.max } 44624d333f3Snibble.max 447b43a590dSNibble Max static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap) 448b43a590dSNibble Max { 449b43a590dSNibble Max struct dvbsky_state *state = adap_to_priv(adap); 450b43a590dSNibble Max struct dvb_usb_device *d = adap_to_d(adap); 451b43a590dSNibble Max struct i2c_adapter *i2c_adapter; 4522c7e3ca8SMauro Carvalho Chehab struct si2168_config si2168_config = {}; 4532c7e3ca8SMauro Carvalho Chehab struct si2157_config si2157_config = {}; 4542c7e3ca8SMauro Carvalho Chehab struct sp2_config sp2_config = {}; 455b43a590dSNibble Max 456b43a590dSNibble Max /* attach demod */ 457b43a590dSNibble Max si2168_config.i2c_adapter = &i2c_adapter; 458b43a590dSNibble Max si2168_config.fe = &adap->fe[0]; 459b43a590dSNibble Max si2168_config.ts_mode = SI2168_TS_PARALLEL; 460b43a590dSNibble Max 4612c7e3ca8SMauro Carvalho Chehab state->i2c_client_demod = dvb_module_probe("si2168", NULL, 4622c7e3ca8SMauro Carvalho Chehab &d->i2c_adap, 4632c7e3ca8SMauro Carvalho Chehab 0x64, &si2168_config); 4642c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_demod) 4652c7e3ca8SMauro Carvalho Chehab return -ENODEV; 466b43a590dSNibble Max 467b43a590dSNibble Max /* attach tuner */ 468b43a590dSNibble Max si2157_config.fe = adap->fe[0]; 469ee3c3e46SOlli Salonen si2157_config.if_port = 1; 470b43a590dSNibble Max 4712c7e3ca8SMauro Carvalho Chehab state->i2c_client_tuner = dvb_module_probe("si2157", NULL, 4722c7e3ca8SMauro Carvalho Chehab i2c_adapter, 4732c7e3ca8SMauro Carvalho Chehab 0x60, &si2157_config); 4742c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_tuner) { 4752c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_demod); 4762c7e3ca8SMauro Carvalho Chehab return -ENODEV; 4772c7e3ca8SMauro Carvalho Chehab } 478b43a590dSNibble Max 479b43a590dSNibble Max /* attach ci controller */ 480b43a590dSNibble Max sp2_config.dvb_adap = &adap->dvb_adap; 481b43a590dSNibble Max sp2_config.priv = d; 482b43a590dSNibble Max sp2_config.ci_control = dvbsky_ci_ctrl; 483b43a590dSNibble Max 4842c7e3ca8SMauro Carvalho Chehab state->i2c_client_ci = dvb_module_probe("sp2", NULL, 4852c7e3ca8SMauro Carvalho Chehab &d->i2c_adap, 4862c7e3ca8SMauro Carvalho Chehab 0x40, &sp2_config); 487b43a590dSNibble Max 4882c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_ci) { 4892c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_tuner); 4902c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_demod); 4912c7e3ca8SMauro Carvalho Chehab return -ENODEV; 4922c7e3ca8SMauro Carvalho Chehab } 493b43a590dSNibble Max 4942c7e3ca8SMauro Carvalho Chehab return 0; 495b43a590dSNibble Max } 496b43a590dSNibble Max 4970a5a4f32SNibble Max static int dvbsky_t330_attach(struct dvb_usb_adapter *adap) 4980a5a4f32SNibble Max { 4990a5a4f32SNibble Max struct dvbsky_state *state = adap_to_priv(adap); 5000a5a4f32SNibble Max struct dvb_usb_device *d = adap_to_d(adap); 5010a5a4f32SNibble Max struct i2c_adapter *i2c_adapter; 5022c7e3ca8SMauro Carvalho Chehab struct si2168_config si2168_config = {}; 5032c7e3ca8SMauro Carvalho Chehab struct si2157_config si2157_config = {}; 5040a5a4f32SNibble Max 5050a5a4f32SNibble Max /* attach demod */ 5060a5a4f32SNibble Max si2168_config.i2c_adapter = &i2c_adapter; 5070a5a4f32SNibble Max si2168_config.fe = &adap->fe[0]; 508c060f932SOlli Salonen si2168_config.ts_mode = SI2168_TS_PARALLEL; 509c060f932SOlli Salonen si2168_config.ts_clock_gapped = true; 5100a5a4f32SNibble Max 5112c7e3ca8SMauro Carvalho Chehab state->i2c_client_demod = dvb_module_probe("si2168", NULL, 5122c7e3ca8SMauro Carvalho Chehab &d->i2c_adap, 5132c7e3ca8SMauro Carvalho Chehab 0x64, &si2168_config); 5142c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_demod) 5152c7e3ca8SMauro Carvalho Chehab return -ENODEV; 5160a5a4f32SNibble Max 5170a5a4f32SNibble Max /* attach tuner */ 5180a5a4f32SNibble Max si2157_config.fe = adap->fe[0]; 519ee3c3e46SOlli Salonen si2157_config.if_port = 1; 5200a5a4f32SNibble Max 5212c7e3ca8SMauro Carvalho Chehab state->i2c_client_tuner = dvb_module_probe("si2157", NULL, 5222c7e3ca8SMauro Carvalho Chehab i2c_adapter, 5232c7e3ca8SMauro Carvalho Chehab 0x60, &si2157_config); 5242c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_tuner) { 5252c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_demod); 5262c7e3ca8SMauro Carvalho Chehab return -ENODEV; 5272c7e3ca8SMauro Carvalho Chehab } 5280a5a4f32SNibble Max 5292c7e3ca8SMauro Carvalho Chehab return 0; 5300a5a4f32SNibble Max } 5310a5a4f32SNibble Max 53257422405SStefan Brüns static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap) 53357422405SStefan Brüns { 53457422405SStefan Brüns struct dvbsky_state *state = adap_to_priv(adap); 53557422405SStefan Brüns struct dvb_usb_device *d = adap_to_d(adap); 53657422405SStefan Brüns struct i2c_adapter *i2c_adapter; 5372c7e3ca8SMauro Carvalho Chehab struct si2168_config si2168_config = {}; 5382c7e3ca8SMauro Carvalho Chehab struct si2157_config si2157_config = {}; 53957422405SStefan Brüns 54057422405SStefan Brüns /* attach demod */ 54157422405SStefan Brüns si2168_config.i2c_adapter = &i2c_adapter; 54257422405SStefan Brüns si2168_config.fe = &adap->fe[0]; 54357422405SStefan Brüns si2168_config.ts_mode = SI2168_TS_PARALLEL; 54466193b24SJan Pieter van Woerkom if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2) 54566193b24SJan Pieter van Woerkom si2168_config.ts_mode |= SI2168_TS_CLK_MANUAL; 54657422405SStefan Brüns si2168_config.ts_clock_inv = 1; 54757422405SStefan Brüns 5482c7e3ca8SMauro Carvalho Chehab state->i2c_client_demod = dvb_module_probe("si2168", NULL, 5492c7e3ca8SMauro Carvalho Chehab &d->i2c_adap, 5502c7e3ca8SMauro Carvalho Chehab 0x64, &si2168_config); 5512c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_demod) 5522c7e3ca8SMauro Carvalho Chehab return -ENODEV; 55357422405SStefan Brüns 55457422405SStefan Brüns /* attach tuner */ 55557422405SStefan Brüns si2157_config.fe = adap->fe[0]; 556a9547e52SJan Pieter van Woerkom if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230) { 557a9547e52SJan Pieter van Woerkom si2157_config.if_port = 1; 558a9547e52SJan Pieter van Woerkom state->i2c_client_tuner = dvb_module_probe("si2157", NULL, 559a9547e52SJan Pieter van Woerkom i2c_adapter, 560a9547e52SJan Pieter van Woerkom 0x60, 561a9547e52SJan Pieter van Woerkom &si2157_config); 562a9547e52SJan Pieter van Woerkom } else { 56357422405SStefan Brüns si2157_config.if_port = 0; 5642c7e3ca8SMauro Carvalho Chehab state->i2c_client_tuner = dvb_module_probe("si2157", "si2141", 5652c7e3ca8SMauro Carvalho Chehab i2c_adapter, 566a9547e52SJan Pieter van Woerkom 0x60, 567a9547e52SJan Pieter van Woerkom &si2157_config); 568a9547e52SJan Pieter van Woerkom } 5692c7e3ca8SMauro Carvalho Chehab if (!state->i2c_client_tuner) { 5702c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_demod); 57157422405SStefan Brüns return -ENODEV; 57257422405SStefan Brüns } 57357422405SStefan Brüns 5742c7e3ca8SMauro Carvalho Chehab return 0; 5752c7e3ca8SMauro Carvalho Chehab } 5762c7e3ca8SMauro Carvalho Chehab 57757422405SStefan Brüns 578af64fb3fSnibble.max static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name) 579af64fb3fSnibble.max { 580af64fb3fSnibble.max dvbsky_gpio_ctrl(d, 0x04, 1); 581af64fb3fSnibble.max msleep(20); 582af64fb3fSnibble.max dvbsky_gpio_ctrl(d, 0x83, 0); 583af64fb3fSnibble.max dvbsky_gpio_ctrl(d, 0xc0, 1); 584af64fb3fSnibble.max msleep(100); 585af64fb3fSnibble.max dvbsky_gpio_ctrl(d, 0x83, 1); 586af64fb3fSnibble.max dvbsky_gpio_ctrl(d, 0xc0, 0); 587af64fb3fSnibble.max msleep(50); 588af64fb3fSnibble.max 589af64fb3fSnibble.max return WARM; 590af64fb3fSnibble.max } 591af64fb3fSnibble.max 592af64fb3fSnibble.max static int dvbsky_init(struct dvb_usb_device *d) 593af64fb3fSnibble.max { 594af64fb3fSnibble.max struct dvbsky_state *state = d_to_priv(d); 595af64fb3fSnibble.max 596af64fb3fSnibble.max /* use default interface */ 597af64fb3fSnibble.max /* 598af64fb3fSnibble.max ret = usb_set_interface(d->udev, 0, 0); 599af64fb3fSnibble.max if (ret) 600af64fb3fSnibble.max return ret; 601af64fb3fSnibble.max */ 6029afc8219SMauro Carvalho Chehab 603af64fb3fSnibble.max state->last_lock = 0; 604af64fb3fSnibble.max 605af64fb3fSnibble.max return 0; 606af64fb3fSnibble.max } 607af64fb3fSnibble.max 608fdfa59cdSStefan Brüns static int dvbsky_frontend_detach(struct dvb_usb_adapter *adap) 609af64fb3fSnibble.max { 610fdfa59cdSStefan Brüns struct dvb_usb_device *d = adap_to_d(adap); 611af64fb3fSnibble.max struct dvbsky_state *state = d_to_priv(d); 612fdfa59cdSStefan Brüns 613fdfa59cdSStefan Brüns dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); 614af64fb3fSnibble.max 6152c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_tuner); 6162c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_demod); 6172c7e3ca8SMauro Carvalho Chehab dvb_module_release(state->i2c_client_ci); 61814f4eaedSMauro Carvalho Chehab 619fdfa59cdSStefan Brüns return 0; 620af64fb3fSnibble.max } 621af64fb3fSnibble.max 622af64fb3fSnibble.max /* DVB USB Driver stuff */ 623af64fb3fSnibble.max static struct dvb_usb_device_properties dvbsky_s960_props = { 624af64fb3fSnibble.max .driver_name = KBUILD_MODNAME, 625af64fb3fSnibble.max .owner = THIS_MODULE, 626af64fb3fSnibble.max .adapter_nr = adapter_nr, 627af64fb3fSnibble.max .size_of_priv = sizeof(struct dvbsky_state), 628af64fb3fSnibble.max 629af64fb3fSnibble.max .generic_bulk_ctrl_endpoint = 0x01, 630af64fb3fSnibble.max .generic_bulk_ctrl_endpoint_response = 0x81, 631af64fb3fSnibble.max .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 632af64fb3fSnibble.max 633af64fb3fSnibble.max .i2c_algo = &dvbsky_i2c_algo, 634af64fb3fSnibble.max .frontend_attach = dvbsky_s960_attach, 635fdfa59cdSStefan Brüns .frontend_detach = dvbsky_frontend_detach, 636af64fb3fSnibble.max .init = dvbsky_init, 637af64fb3fSnibble.max .get_rc_config = dvbsky_get_rc_config, 638af64fb3fSnibble.max .streaming_ctrl = dvbsky_streaming_ctrl, 639af64fb3fSnibble.max .identify_state = dvbsky_identify_state, 640af64fb3fSnibble.max .read_mac_address = dvbsky_read_mac_addr, 641af64fb3fSnibble.max 642af64fb3fSnibble.max .num_adapters = 1, 643af64fb3fSnibble.max .adapter = { 644af64fb3fSnibble.max { 645af64fb3fSnibble.max .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 646af64fb3fSnibble.max } 647af64fb3fSnibble.max } 648af64fb3fSnibble.max }; 649af64fb3fSnibble.max 65024d333f3Snibble.max static struct dvb_usb_device_properties dvbsky_s960c_props = { 65124d333f3Snibble.max .driver_name = KBUILD_MODNAME, 65224d333f3Snibble.max .owner = THIS_MODULE, 65324d333f3Snibble.max .adapter_nr = adapter_nr, 65424d333f3Snibble.max .size_of_priv = sizeof(struct dvbsky_state), 65524d333f3Snibble.max 65624d333f3Snibble.max .generic_bulk_ctrl_endpoint = 0x01, 65724d333f3Snibble.max .generic_bulk_ctrl_endpoint_response = 0x81, 65824d333f3Snibble.max .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 65924d333f3Snibble.max 66024d333f3Snibble.max .i2c_algo = &dvbsky_i2c_algo, 66124d333f3Snibble.max .frontend_attach = dvbsky_s960c_attach, 662fdfa59cdSStefan Brüns .frontend_detach = dvbsky_frontend_detach, 66324d333f3Snibble.max .init = dvbsky_init, 66424d333f3Snibble.max .get_rc_config = dvbsky_get_rc_config, 66524d333f3Snibble.max .streaming_ctrl = dvbsky_streaming_ctrl, 66624d333f3Snibble.max .identify_state = dvbsky_identify_state, 66724d333f3Snibble.max .read_mac_address = dvbsky_read_mac_addr, 66824d333f3Snibble.max 66924d333f3Snibble.max .num_adapters = 1, 67024d333f3Snibble.max .adapter = { 67124d333f3Snibble.max { 67224d333f3Snibble.max .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 67324d333f3Snibble.max } 67424d333f3Snibble.max } 67524d333f3Snibble.max }; 67624d333f3Snibble.max 677b43a590dSNibble Max static struct dvb_usb_device_properties dvbsky_t680c_props = { 678b43a590dSNibble Max .driver_name = KBUILD_MODNAME, 679b43a590dSNibble Max .owner = THIS_MODULE, 680b43a590dSNibble Max .adapter_nr = adapter_nr, 681b43a590dSNibble Max .size_of_priv = sizeof(struct dvbsky_state), 682b43a590dSNibble Max 683b43a590dSNibble Max .generic_bulk_ctrl_endpoint = 0x01, 684b43a590dSNibble Max .generic_bulk_ctrl_endpoint_response = 0x81, 685b43a590dSNibble Max .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 686b43a590dSNibble Max 687b43a590dSNibble Max .i2c_algo = &dvbsky_i2c_algo, 688b43a590dSNibble Max .frontend_attach = dvbsky_t680c_attach, 689fdfa59cdSStefan Brüns .frontend_detach = dvbsky_frontend_detach, 690b43a590dSNibble Max .init = dvbsky_init, 691b43a590dSNibble Max .get_rc_config = dvbsky_get_rc_config, 692b43a590dSNibble Max .streaming_ctrl = dvbsky_streaming_ctrl, 693b43a590dSNibble Max .identify_state = dvbsky_identify_state, 694b43a590dSNibble Max .read_mac_address = dvbsky_read_mac_addr, 695b43a590dSNibble Max 696b43a590dSNibble Max .num_adapters = 1, 697b43a590dSNibble Max .adapter = { 698b43a590dSNibble Max { 699b43a590dSNibble Max .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 700b43a590dSNibble Max } 701b43a590dSNibble Max } 702b43a590dSNibble Max }; 703b43a590dSNibble Max 7040a5a4f32SNibble Max static struct dvb_usb_device_properties dvbsky_t330_props = { 7050a5a4f32SNibble Max .driver_name = KBUILD_MODNAME, 7060a5a4f32SNibble Max .owner = THIS_MODULE, 7070a5a4f32SNibble Max .adapter_nr = adapter_nr, 7080a5a4f32SNibble Max .size_of_priv = sizeof(struct dvbsky_state), 7090a5a4f32SNibble Max 7100a5a4f32SNibble Max .generic_bulk_ctrl_endpoint = 0x01, 7110a5a4f32SNibble Max .generic_bulk_ctrl_endpoint_response = 0x81, 7120a5a4f32SNibble Max .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 7130a5a4f32SNibble Max 7140a5a4f32SNibble Max .i2c_algo = &dvbsky_i2c_algo, 7150a5a4f32SNibble Max .frontend_attach = dvbsky_t330_attach, 716fdfa59cdSStefan Brüns .frontend_detach = dvbsky_frontend_detach, 7170a5a4f32SNibble Max .init = dvbsky_init, 7180a5a4f32SNibble Max .get_rc_config = dvbsky_get_rc_config, 7190a5a4f32SNibble Max .streaming_ctrl = dvbsky_streaming_ctrl, 7200a5a4f32SNibble Max .identify_state = dvbsky_identify_state, 7210a5a4f32SNibble Max .read_mac_address = dvbsky_read_mac_addr, 7220a5a4f32SNibble Max 7230a5a4f32SNibble Max .num_adapters = 1, 7240a5a4f32SNibble Max .adapter = { 7250a5a4f32SNibble Max { 7260a5a4f32SNibble Max .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 7270a5a4f32SNibble Max } 7280a5a4f32SNibble Max } 7290a5a4f32SNibble Max }; 7300a5a4f32SNibble Max 73157422405SStefan Brüns static struct dvb_usb_device_properties mygica_t230c_props = { 73257422405SStefan Brüns .driver_name = KBUILD_MODNAME, 73357422405SStefan Brüns .owner = THIS_MODULE, 73457422405SStefan Brüns .adapter_nr = adapter_nr, 73557422405SStefan Brüns .size_of_priv = sizeof(struct dvbsky_state), 73657422405SStefan Brüns 73757422405SStefan Brüns .generic_bulk_ctrl_endpoint = 0x01, 73857422405SStefan Brüns .generic_bulk_ctrl_endpoint_response = 0x81, 73957422405SStefan Brüns .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, 74057422405SStefan Brüns 74157422405SStefan Brüns .i2c_algo = &dvbsky_i2c_algo, 74257422405SStefan Brüns .frontend_attach = dvbsky_mygica_t230c_attach, 743fdfa59cdSStefan Brüns .frontend_detach = dvbsky_frontend_detach, 74457422405SStefan Brüns .init = dvbsky_init, 74557422405SStefan Brüns .get_rc_config = dvbsky_get_rc_config, 74657422405SStefan Brüns .streaming_ctrl = dvbsky_streaming_ctrl, 74757422405SStefan Brüns .identify_state = dvbsky_identify_state, 74857422405SStefan Brüns 74957422405SStefan Brüns .num_adapters = 1, 75057422405SStefan Brüns .adapter = { 75157422405SStefan Brüns { 75257422405SStefan Brüns .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), 75357422405SStefan Brüns } 75457422405SStefan Brüns } 75557422405SStefan Brüns }; 75657422405SStefan Brüns 757af64fb3fSnibble.max static const struct usb_device_id dvbsky_id_table[] = { 758af64fb3fSnibble.max { DVB_USB_DEVICE(0x0572, 0x6831, 759af64fb3fSnibble.max &dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) }, 76024d333f3Snibble.max { DVB_USB_DEVICE(0x0572, 0x960c, 76124d333f3Snibble.max &dvbsky_s960c_props, "DVBSky S960CI", RC_MAP_DVBSKY) }, 762b43a590dSNibble Max { DVB_USB_DEVICE(0x0572, 0x680c, 763b43a590dSNibble Max &dvbsky_t680c_props, "DVBSky T680CI", RC_MAP_DVBSKY) }, 7640a5a4f32SNibble Max { DVB_USB_DEVICE(0x0572, 0x0320, 7650a5a4f32SNibble Max &dvbsky_t330_props, "DVBSky T330", RC_MAP_DVBSKY) }, 766134e7e1cSNibble Max { DVB_USB_DEVICE(USB_VID_TECHNOTREND, 767134e7e1cSNibble Max USB_PID_TECHNOTREND_TVSTICK_CT2_4400, 768134e7e1cSNibble Max &dvbsky_t330_props, "TechnoTrend TVStick CT2-4400", 769134e7e1cSNibble Max RC_MAP_TT_1500) }, 770134e7e1cSNibble Max { DVB_USB_DEVICE(USB_VID_TECHNOTREND, 771134e7e1cSNibble Max USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI, 772134e7e1cSNibble Max &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI", 773134e7e1cSNibble Max RC_MAP_TT_1500) }, 774d309c8bbSTorbjörn Jansson { DVB_USB_DEVICE(USB_VID_TECHNOTREND, 775d309c8bbSTorbjörn Jansson USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2, 776d309c8bbSTorbjörn Jansson &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI v1.1", 777d309c8bbSTorbjörn Jansson RC_MAP_TT_1500) }, 77882b65714SOlli Salonen { DVB_USB_DEVICE(USB_VID_TECHNOTREND, 77982b65714SOlli Salonen USB_PID_TECHNOTREND_CONNECT_S2_4650_CI, 78082b65714SOlli Salonen &dvbsky_s960c_props, "TechnoTrend TT-connect S2-4650 CI", 78182b65714SOlli Salonen RC_MAP_TT_1500) }, 7822788052aSErik Andresen { DVB_USB_DEVICE(USB_VID_TERRATEC, 7832788052aSErik Andresen USB_PID_TERRATEC_H7_3, 7842788052aSErik Andresen &dvbsky_t680c_props, "Terratec H7 Rev.4", 7852788052aSErik Andresen RC_MAP_TT_1500) }, 786c5d89a49SBenjamin Larsson { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4, 787c5d89a49SBenjamin Larsson &dvbsky_s960_props, "Terratec Cinergy S2 Rev.4", 788c5d89a49SBenjamin Larsson RC_MAP_DVBSKY) }, 789a9547e52SJan Pieter van Woerkom { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230, 790a9547e52SJan Pieter van Woerkom &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230", 791a9547e52SJan Pieter van Woerkom RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, 79257422405SStefan Brüns { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C, 79357422405SStefan Brüns &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C", 79457422405SStefan Brüns RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, 795*14494583SThomas Voegtle { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C_LITE, 796*14494583SThomas Voegtle &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C Lite", 797*14494583SThomas Voegtle NULL) }, 79866193b24SJan Pieter van Woerkom { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2, 79966193b24SJan Pieter van Woerkom &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C v2", 80066193b24SJan Pieter van Woerkom RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, 801af64fb3fSnibble.max { } 802af64fb3fSnibble.max }; 803af64fb3fSnibble.max MODULE_DEVICE_TABLE(usb, dvbsky_id_table); 804af64fb3fSnibble.max 805af64fb3fSnibble.max static struct usb_driver dvbsky_usb_driver = { 806af64fb3fSnibble.max .name = KBUILD_MODNAME, 807af64fb3fSnibble.max .id_table = dvbsky_id_table, 808af64fb3fSnibble.max .probe = dvb_usbv2_probe, 809af64fb3fSnibble.max .disconnect = dvb_usbv2_disconnect, 810af64fb3fSnibble.max .suspend = dvb_usbv2_suspend, 811af64fb3fSnibble.max .resume = dvb_usbv2_resume, 812af64fb3fSnibble.max .reset_resume = dvb_usbv2_reset_resume, 813af64fb3fSnibble.max .no_dynamic_id = 1, 814af64fb3fSnibble.max .soft_unbind = 1, 815af64fb3fSnibble.max }; 816af64fb3fSnibble.max 817af64fb3fSnibble.max module_usb_driver(dvbsky_usb_driver); 818af64fb3fSnibble.max 819af64fb3fSnibble.max MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>"); 820af64fb3fSnibble.max MODULE_DESCRIPTION("Driver for DVBSky USB"); 821af64fb3fSnibble.max MODULE_LICENSE("GPL"); 822