Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Driver for DVBSky USB2.0 receiver
0004  *
0005  * Copyright (C) 2013 Max nibble <nibble.max@gmail.com>
0006  */
0007 
0008 #include "dvb_usb.h"
0009 #include "m88ds3103.h"
0010 #include "ts2020.h"
0011 #include "sp2.h"
0012 #include "si2168.h"
0013 #include "si2157.h"
0014 
0015 #define DVBSKY_MSG_DELAY    0/*2000*/
0016 #define DVBSKY_BUF_LEN  64
0017 
0018 static int dvb_usb_dvbsky_disable_rc;
0019 module_param_named(disable_rc, dvb_usb_dvbsky_disable_rc, int, 0644);
0020 MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver.");
0021 
0022 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0023 
0024 struct dvbsky_state {
0025     u8 ibuf[DVBSKY_BUF_LEN];
0026     u8 obuf[DVBSKY_BUF_LEN];
0027     u8 last_lock;
0028     struct i2c_client *i2c_client_demod;
0029     struct i2c_client *i2c_client_tuner;
0030     struct i2c_client *i2c_client_ci;
0031 
0032     /* fe hook functions*/
0033     int (*fe_set_voltage)(struct dvb_frontend *fe,
0034         enum fe_sec_voltage voltage);
0035     int (*fe_read_status)(struct dvb_frontend *fe,
0036         enum fe_status *status);
0037 };
0038 
0039 static int dvbsky_usb_generic_rw(struct dvb_usb_device *d,
0040         u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
0041 {
0042     int ret;
0043     struct dvbsky_state *state = d_to_priv(d);
0044 
0045     mutex_lock(&d->usb_mutex);
0046     if (wlen != 0)
0047         memcpy(state->obuf, wbuf, wlen);
0048 
0049     ret = dvb_usbv2_generic_rw_locked(d, state->obuf, wlen,
0050             state->ibuf, rlen);
0051 
0052     if (!ret && (rlen != 0))
0053         memcpy(rbuf, state->ibuf, rlen);
0054 
0055     mutex_unlock(&d->usb_mutex);
0056     return ret;
0057 }
0058 
0059 static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff)
0060 {
0061     struct dvbsky_state *state = d_to_priv(d);
0062     static const u8 obuf_pre[3] = { 0x37, 0, 0 };
0063     static const u8 obuf_post[3] = { 0x36, 3, 0 };
0064     int ret;
0065 
0066     mutex_lock(&d->usb_mutex);
0067     memcpy(state->obuf, obuf_pre, 3);
0068     ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3);
0069     if (!ret && onoff) {
0070         msleep(20);
0071         memcpy(state->obuf, obuf_post, 3);
0072         ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3);
0073     }
0074     mutex_unlock(&d->usb_mutex);
0075     return ret;
0076 }
0077 
0078 static int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff)
0079 {
0080     struct dvb_usb_device *d = fe_to_d(fe);
0081 
0082     return dvbsky_stream_ctrl(d, (onoff == 0) ? 0 : 1);
0083 }
0084 
0085 /* GPIO */
0086 static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value)
0087 {
0088     int ret;
0089     u8 obuf[3], ibuf[2];
0090 
0091     obuf[0] = 0x0e;
0092     obuf[1] = gport;
0093     obuf[2] = value;
0094     ret = dvbsky_usb_generic_rw(d, obuf, 3, ibuf, 1);
0095     return ret;
0096 }
0097 
0098 /* I2C */
0099 static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
0100     int num)
0101 {
0102     struct dvb_usb_device *d = i2c_get_adapdata(adap);
0103     int ret = 0;
0104     u8 ibuf[64], obuf[64];
0105 
0106     if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
0107         return -EAGAIN;
0108 
0109     if (num > 2) {
0110         dev_err(&d->udev->dev,
0111         "too many i2c messages[%d], max 2.", num);
0112         ret = -EOPNOTSUPP;
0113         goto i2c_error;
0114     }
0115 
0116     if (num == 1) {
0117         if (msg[0].len > 60) {
0118             dev_err(&d->udev->dev,
0119             "too many i2c bytes[%d], max 60.",
0120             msg[0].len);
0121             ret = -EOPNOTSUPP;
0122             goto i2c_error;
0123         }
0124         if (msg[0].flags & I2C_M_RD) {
0125             /* single read */
0126             obuf[0] = 0x09;
0127             obuf[1] = 0;
0128             obuf[2] = msg[0].len;
0129             obuf[3] = msg[0].addr;
0130             ret = dvbsky_usb_generic_rw(d, obuf, 4,
0131                     ibuf, msg[0].len + 1);
0132             if (!ret)
0133                 memcpy(msg[0].buf, &ibuf[1], msg[0].len);
0134         } else {
0135             /* write */
0136             obuf[0] = 0x08;
0137             obuf[1] = msg[0].addr;
0138             obuf[2] = msg[0].len;
0139             memcpy(&obuf[3], msg[0].buf, msg[0].len);
0140             ret = dvbsky_usb_generic_rw(d, obuf,
0141                     msg[0].len + 3, ibuf, 1);
0142         }
0143     } else {
0144         if ((msg[0].len > 60) || (msg[1].len > 60)) {
0145             dev_err(&d->udev->dev,
0146             "too many i2c bytes[w-%d][r-%d], max 60.",
0147             msg[0].len, msg[1].len);
0148             ret = -EOPNOTSUPP;
0149             goto i2c_error;
0150         }
0151         /* write then read */
0152         obuf[0] = 0x09;
0153         obuf[1] = msg[0].len;
0154         obuf[2] = msg[1].len;
0155         obuf[3] = msg[0].addr;
0156         memcpy(&obuf[4], msg[0].buf, msg[0].len);
0157         ret = dvbsky_usb_generic_rw(d, obuf,
0158             msg[0].len + 4, ibuf, msg[1].len + 1);
0159         if (!ret)
0160             memcpy(msg[1].buf, &ibuf[1], msg[1].len);
0161     }
0162 i2c_error:
0163     mutex_unlock(&d->i2c_mutex);
0164     return (ret) ? ret : num;
0165 }
0166 
0167 static u32 dvbsky_i2c_func(struct i2c_adapter *adapter)
0168 {
0169     return I2C_FUNC_I2C;
0170 }
0171 
0172 static struct i2c_algorithm dvbsky_i2c_algo = {
0173     .master_xfer   = dvbsky_i2c_xfer,
0174     .functionality = dvbsky_i2c_func,
0175 };
0176 
0177 #if IS_ENABLED(CONFIG_RC_CORE)
0178 static int dvbsky_rc_query(struct dvb_usb_device *d)
0179 {
0180     u32 code = 0xffff, scancode;
0181     u8 rc5_command, rc5_system;
0182     u8 obuf[2], ibuf[2], toggle;
0183     int ret;
0184 
0185     obuf[0] = 0x10;
0186     ret = dvbsky_usb_generic_rw(d, obuf, 1, ibuf, 2);
0187     if (ret == 0)
0188         code = (ibuf[0] << 8) | ibuf[1];
0189     if (code != 0xffff) {
0190         dev_dbg(&d->udev->dev, "rc code: %x\n", code);
0191         rc5_command = code & 0x3F;
0192         rc5_system = (code & 0x7C0) >> 6;
0193         toggle = (code & 0x800) ? 1 : 0;
0194         scancode = rc5_system << 8 | rc5_command;
0195         rc_keydown(d->rc_dev, RC_PROTO_RC5, scancode, toggle);
0196     }
0197     return 0;
0198 }
0199 
0200 static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
0201 {
0202     if (dvb_usb_dvbsky_disable_rc) {
0203         rc->map_name = NULL;
0204         return 0;
0205     }
0206 
0207     rc->allowed_protos = RC_PROTO_BIT_RC5;
0208     rc->query          = dvbsky_rc_query;
0209     rc->interval       = 300;
0210     return 0;
0211 }
0212 #else
0213     #define dvbsky_get_rc_config NULL
0214 #endif
0215 
0216 static int dvbsky_usb_set_voltage(struct dvb_frontend *fe,
0217     enum fe_sec_voltage voltage)
0218 {
0219     struct dvb_usb_device *d = fe_to_d(fe);
0220     struct dvbsky_state *state = d_to_priv(d);
0221     u8 value;
0222 
0223     if (voltage == SEC_VOLTAGE_OFF)
0224         value = 0;
0225     else
0226         value = 1;
0227     dvbsky_gpio_ctrl(d, 0x80, value);
0228 
0229     return state->fe_set_voltage(fe, voltage);
0230 }
0231 
0232 static int dvbsky_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6])
0233 {
0234     struct dvb_usb_device *d = adap_to_d(adap);
0235     u8 obuf[] = { 0x1e, 0x00 };
0236     u8 ibuf[6] = { 0 };
0237     struct i2c_msg msg[] = {
0238         {
0239             .addr = 0x51,
0240             .flags = 0,
0241             .buf = obuf,
0242             .len = 2,
0243         }, {
0244             .addr = 0x51,
0245             .flags = I2C_M_RD,
0246             .buf = ibuf,
0247             .len = 6,
0248         }
0249     };
0250 
0251     if (i2c_transfer(&d->i2c_adap, msg, 2) == 2)
0252         memcpy(mac, ibuf, 6);
0253 
0254     return 0;
0255 }
0256 
0257 static int dvbsky_usb_read_status(struct dvb_frontend *fe,
0258                   enum fe_status *status)
0259 {
0260     struct dvb_usb_device *d = fe_to_d(fe);
0261     struct dvbsky_state *state = d_to_priv(d);
0262     int ret;
0263 
0264     ret = state->fe_read_status(fe, status);
0265 
0266     /* it need resync slave fifo when signal change from unlock to lock.*/
0267     if ((*status & FE_HAS_LOCK) && (!state->last_lock))
0268         dvbsky_stream_ctrl(d, 1);
0269 
0270     state->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0;
0271     return ret;
0272 }
0273 
0274 static int dvbsky_s960_attach(struct dvb_usb_adapter *adap)
0275 {
0276     struct dvbsky_state *state = adap_to_priv(adap);
0277     struct dvb_usb_device *d = adap_to_d(adap);
0278     struct i2c_adapter *i2c_adapter;
0279     struct m88ds3103_platform_data m88ds3103_pdata = {};
0280     struct ts2020_config ts2020_config = {};
0281 
0282     /* attach demod */
0283     m88ds3103_pdata.clk = 27000000;
0284     m88ds3103_pdata.i2c_wr_max = 33;
0285     m88ds3103_pdata.clk_out = 0;
0286     m88ds3103_pdata.ts_mode = M88DS3103_TS_CI;
0287     m88ds3103_pdata.ts_clk = 16000;
0288     m88ds3103_pdata.ts_clk_pol = 0;
0289     m88ds3103_pdata.agc = 0x99;
0290     m88ds3103_pdata.lnb_hv_pol = 1;
0291     m88ds3103_pdata.lnb_en_pol = 1;
0292 
0293     state->i2c_client_demod = dvb_module_probe("m88ds3103", NULL,
0294                            &d->i2c_adap,
0295                            0x68, &m88ds3103_pdata);
0296     if (!state->i2c_client_demod)
0297         return -ENODEV;
0298 
0299     adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod);
0300     i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod);
0301 
0302     /* attach tuner */
0303     ts2020_config.fe = adap->fe[0];
0304     ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm;
0305 
0306     state->i2c_client_tuner = dvb_module_probe("ts2020", NULL,
0307                            i2c_adapter,
0308                            0x60, &ts2020_config);
0309     if (!state->i2c_client_tuner) {
0310         dvb_module_release(state->i2c_client_demod);
0311         return -ENODEV;
0312     }
0313 
0314     /* delegate signal strength measurement to tuner */
0315     adap->fe[0]->ops.read_signal_strength =
0316             adap->fe[0]->ops.tuner_ops.get_rf_strength;
0317 
0318     /* hook fe: need to resync the slave fifo when signal locks. */
0319     state->fe_read_status = adap->fe[0]->ops.read_status;
0320     adap->fe[0]->ops.read_status = dvbsky_usb_read_status;
0321 
0322     /* hook fe: LNB off/on is control by Cypress usb chip. */
0323     state->fe_set_voltage = adap->fe[0]->ops.set_voltage;
0324     adap->fe[0]->ops.set_voltage = dvbsky_usb_set_voltage;
0325 
0326     return 0;
0327 }
0328 
0329 static int dvbsky_usb_ci_set_voltage(struct dvb_frontend *fe,
0330     enum fe_sec_voltage voltage)
0331 {
0332     struct dvb_usb_device *d = fe_to_d(fe);
0333     struct dvbsky_state *state = d_to_priv(d);
0334     u8 value;
0335 
0336     if (voltage == SEC_VOLTAGE_OFF)
0337         value = 0;
0338     else
0339         value = 1;
0340     dvbsky_gpio_ctrl(d, 0x00, value);
0341 
0342     return state->fe_set_voltage(fe, voltage);
0343 }
0344 
0345 static int dvbsky_ci_ctrl(void *priv, u8 read, int addr,
0346                     u8 data, int *mem)
0347 {
0348     struct dvb_usb_device *d = priv;
0349     int ret = 0;
0350     u8 command[4], respond[2], command_size, respond_size;
0351 
0352     command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/
0353     command[2] = (u8)(addr & 0xff); /*low part of address*/
0354     if (read) {
0355         command[0] = 0x71;
0356         command_size = 3;
0357         respond_size = 2;
0358     } else {
0359         command[0] = 0x70;
0360         command[3] = data;
0361         command_size = 4;
0362         respond_size = 1;
0363     }
0364     ret = dvbsky_usb_generic_rw(d, command, command_size,
0365             respond, respond_size);
0366     if (ret)
0367         goto err;
0368     if (read)
0369         *mem = respond[1];
0370     return ret;
0371 err:
0372     dev_err(&d->udev->dev, "ci control failed=%d\n", ret);
0373     return ret;
0374 }
0375 
0376 static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap)
0377 {
0378     struct dvbsky_state *state = adap_to_priv(adap);
0379     struct dvb_usb_device *d = adap_to_d(adap);
0380     struct i2c_adapter *i2c_adapter;
0381     struct m88ds3103_platform_data m88ds3103_pdata = {};
0382     struct ts2020_config ts2020_config = {};
0383     struct sp2_config sp2_config = {};
0384 
0385     /* attach demod */
0386     m88ds3103_pdata.clk = 27000000;
0387     m88ds3103_pdata.i2c_wr_max = 33;
0388     m88ds3103_pdata.clk_out = 0;
0389     m88ds3103_pdata.ts_mode = M88DS3103_TS_CI;
0390     m88ds3103_pdata.ts_clk = 10000;
0391     m88ds3103_pdata.ts_clk_pol = 1;
0392     m88ds3103_pdata.agc = 0x99;
0393     m88ds3103_pdata.lnb_hv_pol = 0;
0394     m88ds3103_pdata.lnb_en_pol = 1;
0395 
0396     state->i2c_client_demod = dvb_module_probe("m88ds3103", NULL,
0397                            &d->i2c_adap,
0398                            0x68, &m88ds3103_pdata);
0399     if (!state->i2c_client_demod)
0400         return -ENODEV;
0401 
0402     adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod);
0403     i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod);
0404 
0405     /* attach tuner */
0406     ts2020_config.fe = adap->fe[0];
0407     ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm;
0408 
0409     state->i2c_client_tuner = dvb_module_probe("ts2020", NULL,
0410                            i2c_adapter,
0411                            0x60, &ts2020_config);
0412     if (!state->i2c_client_tuner) {
0413         dvb_module_release(state->i2c_client_demod);
0414         return -ENODEV;
0415     }
0416 
0417     /* attach ci controller */
0418     sp2_config.dvb_adap = &adap->dvb_adap;
0419     sp2_config.priv = d;
0420     sp2_config.ci_control = dvbsky_ci_ctrl;
0421 
0422     state->i2c_client_ci = dvb_module_probe("sp2", NULL,
0423                         &d->i2c_adap,
0424                         0x40, &sp2_config);
0425 
0426     if (!state->i2c_client_ci) {
0427         dvb_module_release(state->i2c_client_tuner);
0428         dvb_module_release(state->i2c_client_demod);
0429         return -ENODEV;
0430     }
0431 
0432     /* delegate signal strength measurement to tuner */
0433     adap->fe[0]->ops.read_signal_strength =
0434             adap->fe[0]->ops.tuner_ops.get_rf_strength;
0435 
0436     /* hook fe: need to resync the slave fifo when signal locks. */
0437     state->fe_read_status = adap->fe[0]->ops.read_status;
0438     adap->fe[0]->ops.read_status = dvbsky_usb_read_status;
0439 
0440     /* hook fe: LNB off/on is control by Cypress usb chip. */
0441     state->fe_set_voltage = adap->fe[0]->ops.set_voltage;
0442     adap->fe[0]->ops.set_voltage = dvbsky_usb_ci_set_voltage;
0443 
0444     return 0;
0445 }
0446 
0447 static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap)
0448 {
0449     struct dvbsky_state *state = adap_to_priv(adap);
0450     struct dvb_usb_device *d = adap_to_d(adap);
0451     struct i2c_adapter *i2c_adapter;
0452     struct si2168_config si2168_config = {};
0453     struct si2157_config si2157_config = {};
0454     struct sp2_config sp2_config = {};
0455 
0456     /* attach demod */
0457     si2168_config.i2c_adapter = &i2c_adapter;
0458     si2168_config.fe = &adap->fe[0];
0459     si2168_config.ts_mode = SI2168_TS_PARALLEL;
0460 
0461     state->i2c_client_demod = dvb_module_probe("si2168", NULL,
0462                            &d->i2c_adap,
0463                            0x64, &si2168_config);
0464     if (!state->i2c_client_demod)
0465         return -ENODEV;
0466 
0467     /* attach tuner */
0468     si2157_config.fe = adap->fe[0];
0469     si2157_config.if_port = 1;
0470 
0471     state->i2c_client_tuner = dvb_module_probe("si2157", NULL,
0472                            i2c_adapter,
0473                            0x60, &si2157_config);
0474     if (!state->i2c_client_tuner) {
0475         dvb_module_release(state->i2c_client_demod);
0476         return -ENODEV;
0477     }
0478 
0479     /* attach ci controller */
0480     sp2_config.dvb_adap = &adap->dvb_adap;
0481     sp2_config.priv = d;
0482     sp2_config.ci_control = dvbsky_ci_ctrl;
0483 
0484     state->i2c_client_ci = dvb_module_probe("sp2", NULL,
0485                         &d->i2c_adap,
0486                         0x40, &sp2_config);
0487 
0488     if (!state->i2c_client_ci) {
0489         dvb_module_release(state->i2c_client_tuner);
0490         dvb_module_release(state->i2c_client_demod);
0491         return -ENODEV;
0492     }
0493 
0494     return 0;
0495 }
0496 
0497 static int dvbsky_t330_attach(struct dvb_usb_adapter *adap)
0498 {
0499     struct dvbsky_state *state = adap_to_priv(adap);
0500     struct dvb_usb_device *d = adap_to_d(adap);
0501     struct i2c_adapter *i2c_adapter;
0502     struct si2168_config si2168_config = {};
0503     struct si2157_config si2157_config = {};
0504 
0505     /* attach demod */
0506     si2168_config.i2c_adapter = &i2c_adapter;
0507     si2168_config.fe = &adap->fe[0];
0508     si2168_config.ts_mode = SI2168_TS_PARALLEL;
0509     si2168_config.ts_clock_gapped = true;
0510 
0511     state->i2c_client_demod = dvb_module_probe("si2168", NULL,
0512                            &d->i2c_adap,
0513                            0x64, &si2168_config);
0514     if (!state->i2c_client_demod)
0515         return -ENODEV;
0516 
0517     /* attach tuner */
0518     si2157_config.fe = adap->fe[0];
0519     si2157_config.if_port = 1;
0520 
0521     state->i2c_client_tuner = dvb_module_probe("si2157", NULL,
0522                            i2c_adapter,
0523                            0x60, &si2157_config);
0524     if (!state->i2c_client_tuner) {
0525         dvb_module_release(state->i2c_client_demod);
0526         return -ENODEV;
0527     }
0528 
0529     return 0;
0530 }
0531 
0532 static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
0533 {
0534     struct dvbsky_state *state = adap_to_priv(adap);
0535     struct dvb_usb_device *d = adap_to_d(adap);
0536     struct i2c_adapter *i2c_adapter;
0537     struct si2168_config si2168_config = {};
0538     struct si2157_config si2157_config = {};
0539 
0540     /* attach demod */
0541     si2168_config.i2c_adapter = &i2c_adapter;
0542     si2168_config.fe = &adap->fe[0];
0543     si2168_config.ts_mode = SI2168_TS_PARALLEL;
0544     if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2 ||
0545         le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2_LITE ||
0546         le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230A)
0547         si2168_config.ts_mode |= SI2168_TS_CLK_MANUAL;
0548     si2168_config.ts_clock_inv = 1;
0549 
0550     state->i2c_client_demod = dvb_module_probe("si2168", NULL,
0551                            &d->i2c_adap,
0552                            0x64, &si2168_config);
0553     if (!state->i2c_client_demod)
0554         return -ENODEV;
0555 
0556     /* attach tuner */
0557     si2157_config.fe = adap->fe[0];
0558     if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230) {
0559         si2157_config.if_port = 1;
0560         state->i2c_client_tuner = dvb_module_probe("si2157", NULL,
0561                                i2c_adapter,
0562                                0x60,
0563                                &si2157_config);
0564     } else {
0565         si2157_config.if_port = 0;
0566         state->i2c_client_tuner = dvb_module_probe("si2157", "si2141",
0567                                i2c_adapter,
0568                                0x60,
0569                                &si2157_config);
0570     }
0571     if (!state->i2c_client_tuner) {
0572         dvb_module_release(state->i2c_client_demod);
0573         return -ENODEV;
0574     }
0575 
0576     return 0;
0577 }
0578 
0579 
0580 static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
0581 {
0582     if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230A) {
0583         dvbsky_gpio_ctrl(d, 0x87, 0);
0584         msleep(20);
0585         dvbsky_gpio_ctrl(d, 0x86, 1);
0586         dvbsky_gpio_ctrl(d, 0x80, 0);
0587         msleep(100);
0588         dvbsky_gpio_ctrl(d, 0x80, 1);
0589         msleep(50);
0590     } else {
0591         dvbsky_gpio_ctrl(d, 0x04, 1);
0592         msleep(20);
0593         dvbsky_gpio_ctrl(d, 0x83, 0);
0594         dvbsky_gpio_ctrl(d, 0xc0, 1);
0595         msleep(100);
0596         dvbsky_gpio_ctrl(d, 0x83, 1);
0597         dvbsky_gpio_ctrl(d, 0xc0, 0);
0598         msleep(50);
0599     }
0600     return WARM;
0601 }
0602 
0603 static int dvbsky_init(struct dvb_usb_device *d)
0604 {
0605     struct dvbsky_state *state = d_to_priv(d);
0606     state->last_lock = 0;
0607     return 0;
0608 }
0609 
0610 static int dvbsky_frontend_detach(struct dvb_usb_adapter *adap)
0611 {
0612     struct dvb_usb_device *d = adap_to_d(adap);
0613     struct dvbsky_state *state = d_to_priv(d);
0614 
0615     dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id);
0616 
0617     dvb_module_release(state->i2c_client_tuner);
0618     dvb_module_release(state->i2c_client_demod);
0619     dvb_module_release(state->i2c_client_ci);
0620 
0621     return 0;
0622 }
0623 
0624 /* DVB USB Driver stuff */
0625 static struct dvb_usb_device_properties dvbsky_s960_props = {
0626     .driver_name = KBUILD_MODNAME,
0627     .owner = THIS_MODULE,
0628     .adapter_nr = adapter_nr,
0629     .size_of_priv = sizeof(struct dvbsky_state),
0630 
0631     .generic_bulk_ctrl_endpoint = 0x01,
0632     .generic_bulk_ctrl_endpoint_response = 0x81,
0633     .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
0634 
0635     .i2c_algo         = &dvbsky_i2c_algo,
0636     .frontend_attach  = dvbsky_s960_attach,
0637     .frontend_detach  = dvbsky_frontend_detach,
0638     .init             = dvbsky_init,
0639     .get_rc_config    = dvbsky_get_rc_config,
0640     .streaming_ctrl   = dvbsky_streaming_ctrl,
0641     .identify_state   = dvbsky_identify_state,
0642     .read_mac_address = dvbsky_read_mac_addr,
0643 
0644     .num_adapters = 1,
0645     .adapter = {
0646         {
0647             .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
0648         }
0649     }
0650 };
0651 
0652 static struct dvb_usb_device_properties dvbsky_s960c_props = {
0653     .driver_name = KBUILD_MODNAME,
0654     .owner = THIS_MODULE,
0655     .adapter_nr = adapter_nr,
0656     .size_of_priv = sizeof(struct dvbsky_state),
0657 
0658     .generic_bulk_ctrl_endpoint = 0x01,
0659     .generic_bulk_ctrl_endpoint_response = 0x81,
0660     .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
0661 
0662     .i2c_algo         = &dvbsky_i2c_algo,
0663     .frontend_attach  = dvbsky_s960c_attach,
0664     .frontend_detach  = dvbsky_frontend_detach,
0665     .init             = dvbsky_init,
0666     .get_rc_config    = dvbsky_get_rc_config,
0667     .streaming_ctrl   = dvbsky_streaming_ctrl,
0668     .identify_state   = dvbsky_identify_state,
0669     .read_mac_address = dvbsky_read_mac_addr,
0670 
0671     .num_adapters = 1,
0672     .adapter = {
0673         {
0674             .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
0675         }
0676     }
0677 };
0678 
0679 static struct dvb_usb_device_properties dvbsky_t680c_props = {
0680     .driver_name = KBUILD_MODNAME,
0681     .owner = THIS_MODULE,
0682     .adapter_nr = adapter_nr,
0683     .size_of_priv = sizeof(struct dvbsky_state),
0684 
0685     .generic_bulk_ctrl_endpoint = 0x01,
0686     .generic_bulk_ctrl_endpoint_response = 0x81,
0687     .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
0688 
0689     .i2c_algo         = &dvbsky_i2c_algo,
0690     .frontend_attach  = dvbsky_t680c_attach,
0691     .frontend_detach  = dvbsky_frontend_detach,
0692     .init             = dvbsky_init,
0693     .get_rc_config    = dvbsky_get_rc_config,
0694     .streaming_ctrl   = dvbsky_streaming_ctrl,
0695     .identify_state   = dvbsky_identify_state,
0696     .read_mac_address = dvbsky_read_mac_addr,
0697 
0698     .num_adapters = 1,
0699     .adapter = {
0700         {
0701             .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
0702         }
0703     }
0704 };
0705 
0706 static struct dvb_usb_device_properties dvbsky_t330_props = {
0707     .driver_name = KBUILD_MODNAME,
0708     .owner = THIS_MODULE,
0709     .adapter_nr = adapter_nr,
0710     .size_of_priv = sizeof(struct dvbsky_state),
0711 
0712     .generic_bulk_ctrl_endpoint = 0x01,
0713     .generic_bulk_ctrl_endpoint_response = 0x81,
0714     .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
0715 
0716     .i2c_algo         = &dvbsky_i2c_algo,
0717     .frontend_attach  = dvbsky_t330_attach,
0718     .frontend_detach  = dvbsky_frontend_detach,
0719     .init             = dvbsky_init,
0720     .get_rc_config    = dvbsky_get_rc_config,
0721     .streaming_ctrl   = dvbsky_streaming_ctrl,
0722     .identify_state   = dvbsky_identify_state,
0723     .read_mac_address = dvbsky_read_mac_addr,
0724 
0725     .num_adapters = 1,
0726     .adapter = {
0727         {
0728             .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
0729         }
0730     }
0731 };
0732 
0733 static struct dvb_usb_device_properties mygica_t230c_props = {
0734     .driver_name = KBUILD_MODNAME,
0735     .owner = THIS_MODULE,
0736     .adapter_nr = adapter_nr,
0737     .size_of_priv = sizeof(struct dvbsky_state),
0738 
0739     .generic_bulk_ctrl_endpoint = 0x01,
0740     .generic_bulk_ctrl_endpoint_response = 0x81,
0741     .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
0742 
0743     .i2c_algo         = &dvbsky_i2c_algo,
0744     .frontend_attach  = dvbsky_mygica_t230c_attach,
0745     .frontend_detach  = dvbsky_frontend_detach,
0746     .init             = dvbsky_init,
0747     .get_rc_config    = dvbsky_get_rc_config,
0748     .streaming_ctrl   = dvbsky_streaming_ctrl,
0749     .identify_state   = dvbsky_identify_state,
0750 
0751     .num_adapters = 1,
0752     .adapter = {
0753         {
0754             .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
0755         }
0756     }
0757 };
0758 
0759 static const struct usb_device_id dvbsky_id_table[] = {
0760     { DVB_USB_DEVICE(0x0572, 0x6831,
0761         &dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) },
0762     { DVB_USB_DEVICE(0x0572, 0x960c,
0763         &dvbsky_s960c_props, "DVBSky S960CI", RC_MAP_DVBSKY) },
0764     { DVB_USB_DEVICE(0x0572, 0x680c,
0765         &dvbsky_t680c_props, "DVBSky T680CI", RC_MAP_DVBSKY) },
0766     { DVB_USB_DEVICE(0x0572, 0x0320,
0767         &dvbsky_t330_props, "DVBSky T330", RC_MAP_DVBSKY) },
0768     { DVB_USB_DEVICE(USB_VID_TECHNOTREND,
0769         USB_PID_TECHNOTREND_TVSTICK_CT2_4400,
0770         &dvbsky_t330_props, "TechnoTrend TVStick CT2-4400",
0771         RC_MAP_TT_1500) },
0772     { DVB_USB_DEVICE(USB_VID_TECHNOTREND,
0773         USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI,
0774         &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI",
0775         RC_MAP_TT_1500) },
0776     { DVB_USB_DEVICE(USB_VID_TECHNOTREND,
0777         USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2,
0778         &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI v1.1",
0779         RC_MAP_TT_1500) },
0780     { DVB_USB_DEVICE(USB_VID_TECHNOTREND,
0781         USB_PID_TECHNOTREND_CONNECT_S2_4650_CI,
0782         &dvbsky_s960c_props, "TechnoTrend TT-connect S2-4650 CI",
0783         RC_MAP_TT_1500) },
0784     { DVB_USB_DEVICE(USB_VID_TERRATEC,
0785         USB_PID_TERRATEC_H7_3,
0786         &dvbsky_t680c_props, "Terratec H7 Rev.4",
0787         RC_MAP_TT_1500) },
0788     { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4,
0789         &dvbsky_s960_props, "Terratec Cinergy S2 Rev.4",
0790         RC_MAP_DVBSKY) },
0791     { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230,
0792         &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230",
0793         RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
0794     { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C,
0795         &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C",
0796         RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
0797     { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C_LITE,
0798         &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C Lite",
0799         NULL) },
0800     { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2,
0801         &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C v2",
0802         RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
0803     { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2_LITE,
0804          &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C v2  Lite",
0805          NULL) },
0806     { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230A,
0807          &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230A",
0808          NULL) },
0809     { }
0810 };
0811 MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
0812 
0813 static struct usb_driver dvbsky_usb_driver = {
0814     .name = KBUILD_MODNAME,
0815     .id_table = dvbsky_id_table,
0816     .probe = dvb_usbv2_probe,
0817     .disconnect = dvb_usbv2_disconnect,
0818     .suspend = dvb_usbv2_suspend,
0819     .resume = dvb_usbv2_resume,
0820     .reset_resume = dvb_usbv2_reset_resume,
0821     .no_dynamic_id = 1,
0822     .soft_unbind = 1,
0823 };
0824 
0825 module_usb_driver(dvbsky_usb_driver);
0826 
0827 MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
0828 MODULE_DESCRIPTION("Driver for DVBSky USB");
0829 MODULE_LICENSE("GPL");