1*a10e763bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2786baecfSMauro Carvalho Chehab /* DVB USB framework compliant Linux driver for the 3786baecfSMauro Carvalho Chehab * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, 46ede20f9SOlli Salonen * TeVii S421, S480, S482, S600, S630, S632, S650, S660, S662, 5786baecfSMauro Carvalho Chehab * Prof 1100, 7500, 627254c36SOlli Salonen * Geniatech SU3000, T220, 76ede20f9SOlli Salonen * TechnoTrend S2-4600, 86ede20f9SOlli Salonen * Terratec Cinergy S2 cards 9955d00acSIgor M. Liplianin * Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by) 10786baecfSMauro Carvalho Chehab * 11670d7adbSMauro Carvalho Chehab * see Documentation/media/dvb-drivers/dvb-usb.rst for more information 12786baecfSMauro Carvalho Chehab */ 13fada1935SMauro Carvalho Chehab #include <media/dvb-usb-ids.h> 14786baecfSMauro Carvalho Chehab #include "dw2102.h" 15786baecfSMauro Carvalho Chehab #include "si21xx.h" 16786baecfSMauro Carvalho Chehab #include "stv0299.h" 17786baecfSMauro Carvalho Chehab #include "z0194a.h" 18786baecfSMauro Carvalho Chehab #include "stv0288.h" 19786baecfSMauro Carvalho Chehab #include "stb6000.h" 20786baecfSMauro Carvalho Chehab #include "eds1547.h" 21786baecfSMauro Carvalho Chehab #include "cx24116.h" 22786baecfSMauro Carvalho Chehab #include "tda1002x.h" 23786baecfSMauro Carvalho Chehab #include "mt312.h" 24786baecfSMauro Carvalho Chehab #include "zl10039.h" 2573f0af44SKonstantin Dimitrov #include "ts2020.h" 26786baecfSMauro Carvalho Chehab #include "ds3000.h" 27786baecfSMauro Carvalho Chehab #include "stv0900.h" 28786baecfSMauro Carvalho Chehab #include "stv6110.h" 29786baecfSMauro Carvalho Chehab #include "stb6100.h" 30786baecfSMauro Carvalho Chehab #include "stb6100_proc.h" 31955d00acSIgor M. Liplianin #include "m88rs2000.h" 3251d882edSEvgeny Plehov #include "tda18271.h" 3351d882edSEvgeny Plehov #include "cxd2820r.h" 3427254c36SOlli Salonen #include "m88ds3103.h" 35786baecfSMauro Carvalho Chehab 360065a79aSMauro Carvalho Chehab /* Max transfer size done by I2C transfer functions */ 370065a79aSMauro Carvalho Chehab #define MAX_XFER_SIZE 64 380065a79aSMauro Carvalho Chehab 39f08e9f0dSAndrey Pavlenko 40786baecfSMauro Carvalho Chehab #define DW210X_READ_MSG 0 41786baecfSMauro Carvalho Chehab #define DW210X_WRITE_MSG 1 42786baecfSMauro Carvalho Chehab 43786baecfSMauro Carvalho Chehab #define REG_1F_SYMBOLRATE_BYTE0 0x1f 44786baecfSMauro Carvalho Chehab #define REG_20_SYMBOLRATE_BYTE1 0x20 45786baecfSMauro Carvalho Chehab #define REG_21_SYMBOLRATE_BYTE2 0x21 46786baecfSMauro Carvalho Chehab /* on my own*/ 47786baecfSMauro Carvalho Chehab #define DW2102_VOLTAGE_CTRL (0x1800) 48786baecfSMauro Carvalho Chehab #define SU3000_STREAM_CTRL (0x1900) 49786baecfSMauro Carvalho Chehab #define DW2102_RC_QUERY (0x1a00) 50786baecfSMauro Carvalho Chehab #define DW2102_LED_CTRL (0x1b00) 51786baecfSMauro Carvalho Chehab 526823627bSRémi Cardona #define DW2101_FIRMWARE "dvb-usb-dw2101.fw" 536823627bSRémi Cardona #define DW2102_FIRMWARE "dvb-usb-dw2102.fw" 546823627bSRémi Cardona #define DW2104_FIRMWARE "dvb-usb-dw2104.fw" 556823627bSRémi Cardona #define DW3101_FIRMWARE "dvb-usb-dw3101.fw" 566823627bSRémi Cardona #define S630_FIRMWARE "dvb-usb-s630.fw" 576823627bSRémi Cardona #define S660_FIRMWARE "dvb-usb-s660.fw" 586823627bSRémi Cardona #define P1100_FIRMWARE "dvb-usb-p1100.fw" 596823627bSRémi Cardona #define P7500_FIRMWARE "dvb-usb-p7500.fw" 606823627bSRémi Cardona 61fe63a1a6SMauro Carvalho Chehab #define err_str "did not find the firmware file '%s'. You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware" 62786baecfSMauro Carvalho Chehab 632c4ffe27SOlli Salonen struct dw2102_state { 64786baecfSMauro Carvalho Chehab u8 initialized; 65356484caSOlli Salonen u8 last_lock; 66606142afSJonathan McDowell u8 data[MAX_XFER_SIZE + 4]; 67f3c6abcaSOlli Salonen struct i2c_client *i2c_client_demod; 6870769b24SOlli Salonen struct i2c_client *i2c_client_tuner; 69356484caSOlli Salonen 70356484caSOlli Salonen /* fe hook functions*/ 710df289a2SMauro Carvalho Chehab int (*old_set_voltage)(struct dvb_frontend *f, enum fe_sec_voltage v); 72356484caSOlli Salonen int (*fe_read_status)(struct dvb_frontend *fe, 730df289a2SMauro Carvalho Chehab enum fe_status *status); 74786baecfSMauro Carvalho Chehab }; 75786baecfSMauro Carvalho Chehab 76786baecfSMauro Carvalho Chehab /* debug */ 77786baecfSMauro Carvalho Chehab static int dvb_usb_dw2102_debug; 78786baecfSMauro Carvalho Chehab module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); 79786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))." 80786baecfSMauro Carvalho Chehab DVB_USB_DEBUG_STATUS); 81786baecfSMauro Carvalho Chehab 82786baecfSMauro Carvalho Chehab /* demod probe */ 83786baecfSMauro Carvalho Chehab static int demod_probe = 1; 84786baecfSMauro Carvalho Chehab module_param_named(demod, demod_probe, int, 0644); 85f319ed91SMauro Carvalho Chehab MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 4=stv0903+stb6100(or-able))."); 86786baecfSMauro Carvalho Chehab 87786baecfSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 88786baecfSMauro Carvalho Chehab 89786baecfSMauro Carvalho Chehab static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, 90786baecfSMauro Carvalho Chehab u16 index, u8 * data, u16 len, int flags) 91786baecfSMauro Carvalho Chehab { 92786baecfSMauro Carvalho Chehab int ret; 93786baecfSMauro Carvalho Chehab u8 *u8buf; 94786baecfSMauro Carvalho Chehab unsigned int pipe = (flags == DW210X_READ_MSG) ? 95786baecfSMauro Carvalho Chehab usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); 96786baecfSMauro Carvalho Chehab u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; 97786baecfSMauro Carvalho Chehab 98786baecfSMauro Carvalho Chehab u8buf = kmalloc(len, GFP_KERNEL); 99786baecfSMauro Carvalho Chehab if (!u8buf) 100786baecfSMauro Carvalho Chehab return -ENOMEM; 101786baecfSMauro Carvalho Chehab 102786baecfSMauro Carvalho Chehab 103786baecfSMauro Carvalho Chehab if (flags == DW210X_WRITE_MSG) 104786baecfSMauro Carvalho Chehab memcpy(u8buf, data, len); 105786baecfSMauro Carvalho Chehab ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, 106786baecfSMauro Carvalho Chehab value, index , u8buf, len, 2000); 107786baecfSMauro Carvalho Chehab 108786baecfSMauro Carvalho Chehab if (flags == DW210X_READ_MSG) 109786baecfSMauro Carvalho Chehab memcpy(data, u8buf, len); 110786baecfSMauro Carvalho Chehab 111786baecfSMauro Carvalho Chehab kfree(u8buf); 112786baecfSMauro Carvalho Chehab return ret; 113786baecfSMauro Carvalho Chehab } 114786baecfSMauro Carvalho Chehab 115786baecfSMauro Carvalho Chehab /* I2C */ 116786baecfSMauro Carvalho Chehab static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], 117786baecfSMauro Carvalho Chehab int num) 118786baecfSMauro Carvalho Chehab { 119786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 120786baecfSMauro Carvalho Chehab int i = 0; 121786baecfSMauro Carvalho Chehab u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; 122786baecfSMauro Carvalho Chehab u16 value; 123786baecfSMauro Carvalho Chehab 124786baecfSMauro Carvalho Chehab if (!d) 125786baecfSMauro Carvalho Chehab return -ENODEV; 126786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 127786baecfSMauro Carvalho Chehab return -EAGAIN; 128786baecfSMauro Carvalho Chehab 129786baecfSMauro Carvalho Chehab switch (num) { 130786baecfSMauro Carvalho Chehab case 2: 131786baecfSMauro Carvalho Chehab /* read stv0299 register */ 132786baecfSMauro Carvalho Chehab value = msg[0].buf[0];/* register */ 133786baecfSMauro Carvalho Chehab for (i = 0; i < msg[1].len; i++) { 134786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb5, value + i, 0, 135786baecfSMauro Carvalho Chehab buf6, 2, DW210X_READ_MSG); 136786baecfSMauro Carvalho Chehab msg[1].buf[i] = buf6[0]; 137786baecfSMauro Carvalho Chehab } 138786baecfSMauro Carvalho Chehab break; 139786baecfSMauro Carvalho Chehab case 1: 140786baecfSMauro Carvalho Chehab switch (msg[0].addr) { 141786baecfSMauro Carvalho Chehab case 0x68: 142786baecfSMauro Carvalho Chehab /* write to stv0299 register */ 143786baecfSMauro Carvalho Chehab buf6[0] = 0x2a; 144786baecfSMauro Carvalho Chehab buf6[1] = msg[0].buf[0]; 145786baecfSMauro Carvalho Chehab buf6[2] = msg[0].buf[1]; 146786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb2, 0, 0, 147786baecfSMauro Carvalho Chehab buf6, 3, DW210X_WRITE_MSG); 148786baecfSMauro Carvalho Chehab break; 149786baecfSMauro Carvalho Chehab case 0x60: 150786baecfSMauro Carvalho Chehab if (msg[0].flags == 0) { 151786baecfSMauro Carvalho Chehab /* write to tuner pll */ 152786baecfSMauro Carvalho Chehab buf6[0] = 0x2c; 153786baecfSMauro Carvalho Chehab buf6[1] = 5; 154786baecfSMauro Carvalho Chehab buf6[2] = 0xc0; 155786baecfSMauro Carvalho Chehab buf6[3] = msg[0].buf[0]; 156786baecfSMauro Carvalho Chehab buf6[4] = msg[0].buf[1]; 157786baecfSMauro Carvalho Chehab buf6[5] = msg[0].buf[2]; 158786baecfSMauro Carvalho Chehab buf6[6] = msg[0].buf[3]; 159786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb2, 0, 0, 160786baecfSMauro Carvalho Chehab buf6, 7, DW210X_WRITE_MSG); 161786baecfSMauro Carvalho Chehab } else { 162786baecfSMauro Carvalho Chehab /* read from tuner */ 163786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb5, 0, 0, 164786baecfSMauro Carvalho Chehab buf6, 1, DW210X_READ_MSG); 165786baecfSMauro Carvalho Chehab msg[0].buf[0] = buf6[0]; 166786baecfSMauro Carvalho Chehab } 167786baecfSMauro Carvalho Chehab break; 168786baecfSMauro Carvalho Chehab case (DW2102_RC_QUERY): 169786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb8, 0, 0, 170786baecfSMauro Carvalho Chehab buf6, 2, DW210X_READ_MSG); 171786baecfSMauro Carvalho Chehab msg[0].buf[0] = buf6[0]; 172786baecfSMauro Carvalho Chehab msg[0].buf[1] = buf6[1]; 173786baecfSMauro Carvalho Chehab break; 174786baecfSMauro Carvalho Chehab case (DW2102_VOLTAGE_CTRL): 175786baecfSMauro Carvalho Chehab buf6[0] = 0x30; 176786baecfSMauro Carvalho Chehab buf6[1] = msg[0].buf[0]; 177786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb2, 0, 0, 178786baecfSMauro Carvalho Chehab buf6, 2, DW210X_WRITE_MSG); 179786baecfSMauro Carvalho Chehab break; 180786baecfSMauro Carvalho Chehab } 181786baecfSMauro Carvalho Chehab 182786baecfSMauro Carvalho Chehab break; 183786baecfSMauro Carvalho Chehab } 184786baecfSMauro Carvalho Chehab 185786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 186786baecfSMauro Carvalho Chehab return num; 187786baecfSMauro Carvalho Chehab } 188786baecfSMauro Carvalho Chehab 189786baecfSMauro Carvalho Chehab static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, 190786baecfSMauro Carvalho Chehab struct i2c_msg msg[], int num) 191786baecfSMauro Carvalho Chehab { 192786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 193786baecfSMauro Carvalho Chehab u8 buf6[] = {0, 0, 0, 0, 0, 0, 0}; 194786baecfSMauro Carvalho Chehab 195786baecfSMauro Carvalho Chehab if (!d) 196786baecfSMauro Carvalho Chehab return -ENODEV; 197786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 198786baecfSMauro Carvalho Chehab return -EAGAIN; 199786baecfSMauro Carvalho Chehab 200786baecfSMauro Carvalho Chehab switch (num) { 201786baecfSMauro Carvalho Chehab case 2: 202950e252cSAlyssa Milburn if (msg[0].len != 1) { 203950e252cSAlyssa Milburn warn("i2c rd: len=%d is not 1!\n", 204950e252cSAlyssa Milburn msg[0].len); 205950e252cSAlyssa Milburn num = -EOPNOTSUPP; 206950e252cSAlyssa Milburn break; 207950e252cSAlyssa Milburn } 208950e252cSAlyssa Milburn 209950e252cSAlyssa Milburn if (2 + msg[1].len > sizeof(buf6)) { 210950e252cSAlyssa Milburn warn("i2c rd: len=%d is too big!\n", 211950e252cSAlyssa Milburn msg[1].len); 212950e252cSAlyssa Milburn num = -EOPNOTSUPP; 213950e252cSAlyssa Milburn break; 214950e252cSAlyssa Milburn } 215950e252cSAlyssa Milburn 216786baecfSMauro Carvalho Chehab /* read si2109 register by number */ 217786baecfSMauro Carvalho Chehab buf6[0] = msg[0].addr << 1; 218786baecfSMauro Carvalho Chehab buf6[1] = msg[0].len; 219786baecfSMauro Carvalho Chehab buf6[2] = msg[0].buf[0]; 220786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc2, 0, 0, 221786baecfSMauro Carvalho Chehab buf6, msg[0].len + 2, DW210X_WRITE_MSG); 222786baecfSMauro Carvalho Chehab /* read si2109 register */ 223786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc3, 0xd0, 0, 224786baecfSMauro Carvalho Chehab buf6, msg[1].len + 2, DW210X_READ_MSG); 225786baecfSMauro Carvalho Chehab memcpy(msg[1].buf, buf6 + 2, msg[1].len); 226786baecfSMauro Carvalho Chehab 227786baecfSMauro Carvalho Chehab break; 228786baecfSMauro Carvalho Chehab case 1: 229786baecfSMauro Carvalho Chehab switch (msg[0].addr) { 230786baecfSMauro Carvalho Chehab case 0x68: 231950e252cSAlyssa Milburn if (2 + msg[0].len > sizeof(buf6)) { 232950e252cSAlyssa Milburn warn("i2c wr: len=%d is too big!\n", 233950e252cSAlyssa Milburn msg[0].len); 234950e252cSAlyssa Milburn num = -EOPNOTSUPP; 235950e252cSAlyssa Milburn break; 236950e252cSAlyssa Milburn } 237950e252cSAlyssa Milburn 238786baecfSMauro Carvalho Chehab /* write to si2109 register */ 239786baecfSMauro Carvalho Chehab buf6[0] = msg[0].addr << 1; 240786baecfSMauro Carvalho Chehab buf6[1] = msg[0].len; 241786baecfSMauro Carvalho Chehab memcpy(buf6 + 2, msg[0].buf, msg[0].len); 242786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6, 243786baecfSMauro Carvalho Chehab msg[0].len + 2, DW210X_WRITE_MSG); 244786baecfSMauro Carvalho Chehab break; 245786baecfSMauro Carvalho Chehab case(DW2102_RC_QUERY): 246786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb8, 0, 0, 247786baecfSMauro Carvalho Chehab buf6, 2, DW210X_READ_MSG); 248786baecfSMauro Carvalho Chehab msg[0].buf[0] = buf6[0]; 249786baecfSMauro Carvalho Chehab msg[0].buf[1] = buf6[1]; 250786baecfSMauro Carvalho Chehab break; 251786baecfSMauro Carvalho Chehab case(DW2102_VOLTAGE_CTRL): 252786baecfSMauro Carvalho Chehab buf6[0] = 0x30; 253786baecfSMauro Carvalho Chehab buf6[1] = msg[0].buf[0]; 254786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb2, 0, 0, 255786baecfSMauro Carvalho Chehab buf6, 2, DW210X_WRITE_MSG); 256786baecfSMauro Carvalho Chehab break; 257786baecfSMauro Carvalho Chehab } 258786baecfSMauro Carvalho Chehab break; 259786baecfSMauro Carvalho Chehab } 260786baecfSMauro Carvalho Chehab 261786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 262786baecfSMauro Carvalho Chehab return num; 263786baecfSMauro Carvalho Chehab } 264786baecfSMauro Carvalho Chehab 265786baecfSMauro Carvalho Chehab static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) 266786baecfSMauro Carvalho Chehab { 267786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 268324ed533SDan Carpenter int ret; 269786baecfSMauro Carvalho Chehab 270786baecfSMauro Carvalho Chehab if (!d) 271786baecfSMauro Carvalho Chehab return -ENODEV; 272786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 273786baecfSMauro Carvalho Chehab return -EAGAIN; 274786baecfSMauro Carvalho Chehab 275786baecfSMauro Carvalho Chehab switch (num) { 276786baecfSMauro Carvalho Chehab case 2: { 277786baecfSMauro Carvalho Chehab /* read */ 278786baecfSMauro Carvalho Chehab /* first write first register number */ 2790065a79aSMauro Carvalho Chehab u8 ibuf[MAX_XFER_SIZE], obuf[3]; 2800065a79aSMauro Carvalho Chehab 281950e252cSAlyssa Milburn if (2 + msg[0].len != sizeof(obuf)) { 282950e252cSAlyssa Milburn warn("i2c rd: len=%d is not 1!\n", 283950e252cSAlyssa Milburn msg[0].len); 284950e252cSAlyssa Milburn ret = -EOPNOTSUPP; 285950e252cSAlyssa Milburn goto unlock; 286950e252cSAlyssa Milburn } 287950e252cSAlyssa Milburn 2880065a79aSMauro Carvalho Chehab if (2 + msg[1].len > sizeof(ibuf)) { 2890065a79aSMauro Carvalho Chehab warn("i2c rd: len=%d is too big!\n", 2900065a79aSMauro Carvalho Chehab msg[1].len); 291324ed533SDan Carpenter ret = -EOPNOTSUPP; 292324ed533SDan Carpenter goto unlock; 2930065a79aSMauro Carvalho Chehab } 2940065a79aSMauro Carvalho Chehab 295786baecfSMauro Carvalho Chehab obuf[0] = msg[0].addr << 1; 296786baecfSMauro Carvalho Chehab obuf[1] = msg[0].len; 297786baecfSMauro Carvalho Chehab obuf[2] = msg[0].buf[0]; 298786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc2, 0, 0, 299786baecfSMauro Carvalho Chehab obuf, msg[0].len + 2, DW210X_WRITE_MSG); 300786baecfSMauro Carvalho Chehab /* second read registers */ 301786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0, 302786baecfSMauro Carvalho Chehab ibuf, msg[1].len + 2, DW210X_READ_MSG); 303786baecfSMauro Carvalho Chehab memcpy(msg[1].buf, ibuf + 2, msg[1].len); 304786baecfSMauro Carvalho Chehab 305786baecfSMauro Carvalho Chehab break; 306786baecfSMauro Carvalho Chehab } 307786baecfSMauro Carvalho Chehab case 1: 308786baecfSMauro Carvalho Chehab switch (msg[0].addr) { 309786baecfSMauro Carvalho Chehab case 0x68: { 310786baecfSMauro Carvalho Chehab /* write to register */ 3110065a79aSMauro Carvalho Chehab u8 obuf[MAX_XFER_SIZE]; 3120065a79aSMauro Carvalho Chehab 3130065a79aSMauro Carvalho Chehab if (2 + msg[0].len > sizeof(obuf)) { 3140065a79aSMauro Carvalho Chehab warn("i2c wr: len=%d is too big!\n", 3150065a79aSMauro Carvalho Chehab msg[1].len); 316324ed533SDan Carpenter ret = -EOPNOTSUPP; 317324ed533SDan Carpenter goto unlock; 3180065a79aSMauro Carvalho Chehab } 3190065a79aSMauro Carvalho Chehab 320786baecfSMauro Carvalho Chehab obuf[0] = msg[0].addr << 1; 321786baecfSMauro Carvalho Chehab obuf[1] = msg[0].len; 322786baecfSMauro Carvalho Chehab memcpy(obuf + 2, msg[0].buf, msg[0].len); 323786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc2, 0, 0, 324786baecfSMauro Carvalho Chehab obuf, msg[0].len + 2, DW210X_WRITE_MSG); 325786baecfSMauro Carvalho Chehab break; 326786baecfSMauro Carvalho Chehab } 327786baecfSMauro Carvalho Chehab case 0x61: { 328786baecfSMauro Carvalho Chehab /* write to tuner */ 3290065a79aSMauro Carvalho Chehab u8 obuf[MAX_XFER_SIZE]; 3300065a79aSMauro Carvalho Chehab 3310065a79aSMauro Carvalho Chehab if (2 + msg[0].len > sizeof(obuf)) { 3320065a79aSMauro Carvalho Chehab warn("i2c wr: len=%d is too big!\n", 3330065a79aSMauro Carvalho Chehab msg[1].len); 334324ed533SDan Carpenter ret = -EOPNOTSUPP; 335324ed533SDan Carpenter goto unlock; 3360065a79aSMauro Carvalho Chehab } 3370065a79aSMauro Carvalho Chehab 338786baecfSMauro Carvalho Chehab obuf[0] = msg[0].addr << 1; 339786baecfSMauro Carvalho Chehab obuf[1] = msg[0].len; 340786baecfSMauro Carvalho Chehab memcpy(obuf + 2, msg[0].buf, msg[0].len); 341786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc2, 0, 0, 342786baecfSMauro Carvalho Chehab obuf, msg[0].len + 2, DW210X_WRITE_MSG); 343786baecfSMauro Carvalho Chehab break; 344786baecfSMauro Carvalho Chehab } 345786baecfSMauro Carvalho Chehab case(DW2102_RC_QUERY): { 346786baecfSMauro Carvalho Chehab u8 ibuf[2]; 347786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb8, 0, 0, 348786baecfSMauro Carvalho Chehab ibuf, 2, DW210X_READ_MSG); 349786baecfSMauro Carvalho Chehab memcpy(msg[0].buf, ibuf , 2); 350786baecfSMauro Carvalho Chehab break; 351786baecfSMauro Carvalho Chehab } 352786baecfSMauro Carvalho Chehab case(DW2102_VOLTAGE_CTRL): { 353786baecfSMauro Carvalho Chehab u8 obuf[2]; 354786baecfSMauro Carvalho Chehab obuf[0] = 0x30; 355786baecfSMauro Carvalho Chehab obuf[1] = msg[0].buf[0]; 356786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb2, 0, 0, 357786baecfSMauro Carvalho Chehab obuf, 2, DW210X_WRITE_MSG); 358786baecfSMauro Carvalho Chehab break; 359786baecfSMauro Carvalho Chehab } 360786baecfSMauro Carvalho Chehab } 361786baecfSMauro Carvalho Chehab 362786baecfSMauro Carvalho Chehab break; 363786baecfSMauro Carvalho Chehab } 364324ed533SDan Carpenter ret = num; 365786baecfSMauro Carvalho Chehab 366324ed533SDan Carpenter unlock: 367786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 368324ed533SDan Carpenter return ret; 369786baecfSMauro Carvalho Chehab } 370786baecfSMauro Carvalho Chehab 371786baecfSMauro Carvalho Chehab static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) 372786baecfSMauro Carvalho Chehab { 373786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 374324ed533SDan Carpenter int len, i, j, ret; 375786baecfSMauro Carvalho Chehab 376786baecfSMauro Carvalho Chehab if (!d) 377786baecfSMauro Carvalho Chehab return -ENODEV; 378786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 379786baecfSMauro Carvalho Chehab return -EAGAIN; 380786baecfSMauro Carvalho Chehab 381786baecfSMauro Carvalho Chehab for (j = 0; j < num; j++) { 382786baecfSMauro Carvalho Chehab switch (msg[j].addr) { 383786baecfSMauro Carvalho Chehab case(DW2102_RC_QUERY): { 384786baecfSMauro Carvalho Chehab u8 ibuf[2]; 385786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb8, 0, 0, 386786baecfSMauro Carvalho Chehab ibuf, 2, DW210X_READ_MSG); 387786baecfSMauro Carvalho Chehab memcpy(msg[j].buf, ibuf , 2); 388786baecfSMauro Carvalho Chehab break; 389786baecfSMauro Carvalho Chehab } 390786baecfSMauro Carvalho Chehab case(DW2102_VOLTAGE_CTRL): { 391786baecfSMauro Carvalho Chehab u8 obuf[2]; 392786baecfSMauro Carvalho Chehab obuf[0] = 0x30; 393786baecfSMauro Carvalho Chehab obuf[1] = msg[j].buf[0]; 394786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb2, 0, 0, 395786baecfSMauro Carvalho Chehab obuf, 2, DW210X_WRITE_MSG); 396786baecfSMauro Carvalho Chehab break; 397786baecfSMauro Carvalho Chehab } 398786baecfSMauro Carvalho Chehab /*case 0x55: cx24116 399786baecfSMauro Carvalho Chehab case 0x6a: stv0903 400786baecfSMauro Carvalho Chehab case 0x68: ds3000, stv0903 401786baecfSMauro Carvalho Chehab case 0x60: ts2020, stv6110, stb6100 */ 402786baecfSMauro Carvalho Chehab default: { 403786baecfSMauro Carvalho Chehab if (msg[j].flags == I2C_M_RD) { 404786baecfSMauro Carvalho Chehab /* read registers */ 4050065a79aSMauro Carvalho Chehab u8 ibuf[MAX_XFER_SIZE]; 4060065a79aSMauro Carvalho Chehab 4070065a79aSMauro Carvalho Chehab if (2 + msg[j].len > sizeof(ibuf)) { 4080065a79aSMauro Carvalho Chehab warn("i2c rd: len=%d is too big!\n", 4090065a79aSMauro Carvalho Chehab msg[j].len); 410324ed533SDan Carpenter ret = -EOPNOTSUPP; 411324ed533SDan Carpenter goto unlock; 4120065a79aSMauro Carvalho Chehab } 4130065a79aSMauro Carvalho Chehab 414786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc3, 415786baecfSMauro Carvalho Chehab (msg[j].addr << 1) + 1, 0, 416786baecfSMauro Carvalho Chehab ibuf, msg[j].len + 2, 417786baecfSMauro Carvalho Chehab DW210X_READ_MSG); 418786baecfSMauro Carvalho Chehab memcpy(msg[j].buf, ibuf + 2, msg[j].len); 419786baecfSMauro Carvalho Chehab mdelay(10); 420786baecfSMauro Carvalho Chehab } else if (((msg[j].buf[0] == 0xb0) && 421786baecfSMauro Carvalho Chehab (msg[j].addr == 0x68)) || 422786baecfSMauro Carvalho Chehab ((msg[j].buf[0] == 0xf7) && 423786baecfSMauro Carvalho Chehab (msg[j].addr == 0x55))) { 424786baecfSMauro Carvalho Chehab /* write firmware */ 425786baecfSMauro Carvalho Chehab u8 obuf[19]; 426786baecfSMauro Carvalho Chehab obuf[0] = msg[j].addr << 1; 427786baecfSMauro Carvalho Chehab obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len); 428786baecfSMauro Carvalho Chehab obuf[2] = msg[j].buf[0]; 429786baecfSMauro Carvalho Chehab len = msg[j].len - 1; 430786baecfSMauro Carvalho Chehab i = 1; 431786baecfSMauro Carvalho Chehab do { 432786baecfSMauro Carvalho Chehab memcpy(obuf + 3, msg[j].buf + i, 433786baecfSMauro Carvalho Chehab (len > 16 ? 16 : len)); 434786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc2, 0, 0, 435786baecfSMauro Carvalho Chehab obuf, (len > 16 ? 16 : len) + 3, 436786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG); 437786baecfSMauro Carvalho Chehab i += 16; 438786baecfSMauro Carvalho Chehab len -= 16; 439786baecfSMauro Carvalho Chehab } while (len > 0); 440786baecfSMauro Carvalho Chehab } else { 441786baecfSMauro Carvalho Chehab /* write registers */ 4420065a79aSMauro Carvalho Chehab u8 obuf[MAX_XFER_SIZE]; 4430065a79aSMauro Carvalho Chehab 4440065a79aSMauro Carvalho Chehab if (2 + msg[j].len > sizeof(obuf)) { 4450065a79aSMauro Carvalho Chehab warn("i2c wr: len=%d is too big!\n", 4460065a79aSMauro Carvalho Chehab msg[j].len); 447324ed533SDan Carpenter ret = -EOPNOTSUPP; 448324ed533SDan Carpenter goto unlock; 4490065a79aSMauro Carvalho Chehab } 4500065a79aSMauro Carvalho Chehab 451786baecfSMauro Carvalho Chehab obuf[0] = msg[j].addr << 1; 452786baecfSMauro Carvalho Chehab obuf[1] = msg[j].len; 453786baecfSMauro Carvalho Chehab memcpy(obuf + 2, msg[j].buf, msg[j].len); 454786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc2, 0, 0, 455786baecfSMauro Carvalho Chehab obuf, msg[j].len + 2, 456786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG); 457786baecfSMauro Carvalho Chehab } 458786baecfSMauro Carvalho Chehab break; 459786baecfSMauro Carvalho Chehab } 460786baecfSMauro Carvalho Chehab } 461786baecfSMauro Carvalho Chehab 462786baecfSMauro Carvalho Chehab } 463324ed533SDan Carpenter ret = num; 464786baecfSMauro Carvalho Chehab 465324ed533SDan Carpenter unlock: 466786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 467324ed533SDan Carpenter return ret; 468786baecfSMauro Carvalho Chehab } 469786baecfSMauro Carvalho Chehab 470786baecfSMauro Carvalho Chehab static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], 471786baecfSMauro Carvalho Chehab int num) 472786baecfSMauro Carvalho Chehab { 473786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 474324ed533SDan Carpenter int ret; 475786baecfSMauro Carvalho Chehab int i; 476786baecfSMauro Carvalho Chehab 477786baecfSMauro Carvalho Chehab if (!d) 478786baecfSMauro Carvalho Chehab return -ENODEV; 479786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 480786baecfSMauro Carvalho Chehab return -EAGAIN; 481786baecfSMauro Carvalho Chehab 482786baecfSMauro Carvalho Chehab switch (num) { 483786baecfSMauro Carvalho Chehab case 2: { 484786baecfSMauro Carvalho Chehab /* read */ 485786baecfSMauro Carvalho Chehab /* first write first register number */ 4860065a79aSMauro Carvalho Chehab u8 ibuf[MAX_XFER_SIZE], obuf[3]; 4870065a79aSMauro Carvalho Chehab 488950e252cSAlyssa Milburn if (2 + msg[0].len != sizeof(obuf)) { 489950e252cSAlyssa Milburn warn("i2c rd: len=%d is not 1!\n", 490950e252cSAlyssa Milburn msg[0].len); 491950e252cSAlyssa Milburn ret = -EOPNOTSUPP; 492950e252cSAlyssa Milburn goto unlock; 493950e252cSAlyssa Milburn } 4940065a79aSMauro Carvalho Chehab if (2 + msg[1].len > sizeof(ibuf)) { 4950065a79aSMauro Carvalho Chehab warn("i2c rd: len=%d is too big!\n", 4960065a79aSMauro Carvalho Chehab msg[1].len); 497324ed533SDan Carpenter ret = -EOPNOTSUPP; 498324ed533SDan Carpenter goto unlock; 4990065a79aSMauro Carvalho Chehab } 500786baecfSMauro Carvalho Chehab obuf[0] = msg[0].addr << 1; 501786baecfSMauro Carvalho Chehab obuf[1] = msg[0].len; 502786baecfSMauro Carvalho Chehab obuf[2] = msg[0].buf[0]; 503786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc2, 0, 0, 504786baecfSMauro Carvalho Chehab obuf, msg[0].len + 2, DW210X_WRITE_MSG); 505786baecfSMauro Carvalho Chehab /* second read registers */ 506786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc3, 0x19 , 0, 507786baecfSMauro Carvalho Chehab ibuf, msg[1].len + 2, DW210X_READ_MSG); 508786baecfSMauro Carvalho Chehab memcpy(msg[1].buf, ibuf + 2, msg[1].len); 509786baecfSMauro Carvalho Chehab 510786baecfSMauro Carvalho Chehab break; 511786baecfSMauro Carvalho Chehab } 512786baecfSMauro Carvalho Chehab case 1: 513786baecfSMauro Carvalho Chehab switch (msg[0].addr) { 514786baecfSMauro Carvalho Chehab case 0x60: 515786baecfSMauro Carvalho Chehab case 0x0c: { 516786baecfSMauro Carvalho Chehab /* write to register */ 5170065a79aSMauro Carvalho Chehab u8 obuf[MAX_XFER_SIZE]; 5180065a79aSMauro Carvalho Chehab 5190065a79aSMauro Carvalho Chehab if (2 + msg[0].len > sizeof(obuf)) { 5200065a79aSMauro Carvalho Chehab warn("i2c wr: len=%d is too big!\n", 5210065a79aSMauro Carvalho Chehab msg[0].len); 522324ed533SDan Carpenter ret = -EOPNOTSUPP; 523324ed533SDan Carpenter goto unlock; 5240065a79aSMauro Carvalho Chehab } 525786baecfSMauro Carvalho Chehab obuf[0] = msg[0].addr << 1; 526786baecfSMauro Carvalho Chehab obuf[1] = msg[0].len; 527786baecfSMauro Carvalho Chehab memcpy(obuf + 2, msg[0].buf, msg[0].len); 528786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xc2, 0, 0, 529786baecfSMauro Carvalho Chehab obuf, msg[0].len + 2, DW210X_WRITE_MSG); 530786baecfSMauro Carvalho Chehab break; 531786baecfSMauro Carvalho Chehab } 532786baecfSMauro Carvalho Chehab case(DW2102_RC_QUERY): { 533786baecfSMauro Carvalho Chehab u8 ibuf[2]; 534786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb8, 0, 0, 535786baecfSMauro Carvalho Chehab ibuf, 2, DW210X_READ_MSG); 536786baecfSMauro Carvalho Chehab memcpy(msg[0].buf, ibuf , 2); 537786baecfSMauro Carvalho Chehab break; 538786baecfSMauro Carvalho Chehab } 539786baecfSMauro Carvalho Chehab } 540786baecfSMauro Carvalho Chehab 541786baecfSMauro Carvalho Chehab break; 542786baecfSMauro Carvalho Chehab } 543786baecfSMauro Carvalho Chehab 544786baecfSMauro Carvalho Chehab for (i = 0; i < num; i++) { 545786baecfSMauro Carvalho Chehab deb_xfer("%02x:%02x: %s ", i, msg[i].addr, 546786baecfSMauro Carvalho Chehab msg[i].flags == 0 ? ">>>" : "<<<"); 547786baecfSMauro Carvalho Chehab debug_dump(msg[i].buf, msg[i].len, deb_xfer); 548786baecfSMauro Carvalho Chehab } 549324ed533SDan Carpenter ret = num; 550786baecfSMauro Carvalho Chehab 551324ed533SDan Carpenter unlock: 552786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 553324ed533SDan Carpenter return ret; 554786baecfSMauro Carvalho Chehab } 555786baecfSMauro Carvalho Chehab 556786baecfSMauro Carvalho Chehab static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], 557786baecfSMauro Carvalho Chehab int num) 558786baecfSMauro Carvalho Chehab { 559786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 560786baecfSMauro Carvalho Chehab struct usb_device *udev; 561324ed533SDan Carpenter int len, i, j, ret; 562786baecfSMauro Carvalho Chehab 563786baecfSMauro Carvalho Chehab if (!d) 564786baecfSMauro Carvalho Chehab return -ENODEV; 565786baecfSMauro Carvalho Chehab udev = d->udev; 566786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 567786baecfSMauro Carvalho Chehab return -EAGAIN; 568786baecfSMauro Carvalho Chehab 569786baecfSMauro Carvalho Chehab for (j = 0; j < num; j++) { 570786baecfSMauro Carvalho Chehab switch (msg[j].addr) { 571786baecfSMauro Carvalho Chehab case (DW2102_RC_QUERY): { 572786baecfSMauro Carvalho Chehab u8 ibuf[5]; 573786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0xb8, 0, 0, 574786baecfSMauro Carvalho Chehab ibuf, 5, DW210X_READ_MSG); 575786baecfSMauro Carvalho Chehab memcpy(msg[j].buf, ibuf + 3, 2); 576786baecfSMauro Carvalho Chehab break; 577786baecfSMauro Carvalho Chehab } 578786baecfSMauro Carvalho Chehab case (DW2102_VOLTAGE_CTRL): { 579786baecfSMauro Carvalho Chehab u8 obuf[2]; 580786baecfSMauro Carvalho Chehab 581786baecfSMauro Carvalho Chehab obuf[0] = 1; 582786baecfSMauro Carvalho Chehab obuf[1] = msg[j].buf[1];/* off-on */ 583786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0x8a, 0, 0, 584786baecfSMauro Carvalho Chehab obuf, 2, DW210X_WRITE_MSG); 585786baecfSMauro Carvalho Chehab obuf[0] = 3; 586786baecfSMauro Carvalho Chehab obuf[1] = msg[j].buf[0];/* 13v-18v */ 587786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0x8a, 0, 0, 588786baecfSMauro Carvalho Chehab obuf, 2, DW210X_WRITE_MSG); 589786baecfSMauro Carvalho Chehab break; 590786baecfSMauro Carvalho Chehab } 591786baecfSMauro Carvalho Chehab case (DW2102_LED_CTRL): { 592786baecfSMauro Carvalho Chehab u8 obuf[2]; 593786baecfSMauro Carvalho Chehab 594786baecfSMauro Carvalho Chehab obuf[0] = 5; 595786baecfSMauro Carvalho Chehab obuf[1] = msg[j].buf[0]; 596786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0x8a, 0, 0, 597786baecfSMauro Carvalho Chehab obuf, 2, DW210X_WRITE_MSG); 598786baecfSMauro Carvalho Chehab break; 599786baecfSMauro Carvalho Chehab } 600786baecfSMauro Carvalho Chehab /*case 0x55: cx24116 601786baecfSMauro Carvalho Chehab case 0x6a: stv0903 602955d00acSIgor M. Liplianin case 0x68: ds3000, stv0903, rs2000 603786baecfSMauro Carvalho Chehab case 0x60: ts2020, stv6110, stb6100 604786baecfSMauro Carvalho Chehab case 0xa0: eeprom */ 605786baecfSMauro Carvalho Chehab default: { 606786baecfSMauro Carvalho Chehab if (msg[j].flags == I2C_M_RD) { 607786baecfSMauro Carvalho Chehab /* read registers */ 6080065a79aSMauro Carvalho Chehab u8 ibuf[MAX_XFER_SIZE]; 6090065a79aSMauro Carvalho Chehab 6100065a79aSMauro Carvalho Chehab if (msg[j].len > sizeof(ibuf)) { 6110065a79aSMauro Carvalho Chehab warn("i2c rd: len=%d is too big!\n", 6120065a79aSMauro Carvalho Chehab msg[j].len); 613324ed533SDan Carpenter ret = -EOPNOTSUPP; 614324ed533SDan Carpenter goto unlock; 6150065a79aSMauro Carvalho Chehab } 6160065a79aSMauro Carvalho Chehab 617786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0x91, 0, 0, 618786baecfSMauro Carvalho Chehab ibuf, msg[j].len, 619786baecfSMauro Carvalho Chehab DW210X_READ_MSG); 620786baecfSMauro Carvalho Chehab memcpy(msg[j].buf, ibuf, msg[j].len); 621786baecfSMauro Carvalho Chehab break; 622786baecfSMauro Carvalho Chehab } else if ((msg[j].buf[0] == 0xb0) && 623786baecfSMauro Carvalho Chehab (msg[j].addr == 0x68)) { 624786baecfSMauro Carvalho Chehab /* write firmware */ 625786baecfSMauro Carvalho Chehab u8 obuf[19]; 626786baecfSMauro Carvalho Chehab obuf[0] = (msg[j].len > 16 ? 627786baecfSMauro Carvalho Chehab 18 : msg[j].len + 1); 628786baecfSMauro Carvalho Chehab obuf[1] = msg[j].addr << 1; 629786baecfSMauro Carvalho Chehab obuf[2] = msg[j].buf[0]; 630786baecfSMauro Carvalho Chehab len = msg[j].len - 1; 631786baecfSMauro Carvalho Chehab i = 1; 632786baecfSMauro Carvalho Chehab do { 633786baecfSMauro Carvalho Chehab memcpy(obuf + 3, msg[j].buf + i, 634786baecfSMauro Carvalho Chehab (len > 16 ? 16 : len)); 635786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0x80, 0, 0, 636786baecfSMauro Carvalho Chehab obuf, (len > 16 ? 16 : len) + 3, 637786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG); 638786baecfSMauro Carvalho Chehab i += 16; 639786baecfSMauro Carvalho Chehab len -= 16; 640786baecfSMauro Carvalho Chehab } while (len > 0); 641786baecfSMauro Carvalho Chehab } else if (j < (num - 1)) { 642786baecfSMauro Carvalho Chehab /* write register addr before read */ 6430065a79aSMauro Carvalho Chehab u8 obuf[MAX_XFER_SIZE]; 6440065a79aSMauro Carvalho Chehab 6450065a79aSMauro Carvalho Chehab if (2 + msg[j].len > sizeof(obuf)) { 6460065a79aSMauro Carvalho Chehab warn("i2c wr: len=%d is too big!\n", 6470065a79aSMauro Carvalho Chehab msg[j].len); 648324ed533SDan Carpenter ret = -EOPNOTSUPP; 649324ed533SDan Carpenter goto unlock; 6500065a79aSMauro Carvalho Chehab } 6510065a79aSMauro Carvalho Chehab 652786baecfSMauro Carvalho Chehab obuf[0] = msg[j + 1].len; 653786baecfSMauro Carvalho Chehab obuf[1] = (msg[j].addr << 1); 654786baecfSMauro Carvalho Chehab memcpy(obuf + 2, msg[j].buf, msg[j].len); 655786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 6561ad5d064SHans Verkuil le16_to_cpu(udev->descriptor.idProduct) == 657786baecfSMauro Carvalho Chehab 0x7500 ? 0x92 : 0x90, 0, 0, 658786baecfSMauro Carvalho Chehab obuf, msg[j].len + 2, 659786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG); 660786baecfSMauro Carvalho Chehab break; 661786baecfSMauro Carvalho Chehab } else { 662786baecfSMauro Carvalho Chehab /* write registers */ 6630065a79aSMauro Carvalho Chehab u8 obuf[MAX_XFER_SIZE]; 6640065a79aSMauro Carvalho Chehab 6650065a79aSMauro Carvalho Chehab if (2 + msg[j].len > sizeof(obuf)) { 6660065a79aSMauro Carvalho Chehab warn("i2c wr: len=%d is too big!\n", 6670065a79aSMauro Carvalho Chehab msg[j].len); 668324ed533SDan Carpenter ret = -EOPNOTSUPP; 669324ed533SDan Carpenter goto unlock; 6700065a79aSMauro Carvalho Chehab } 671786baecfSMauro Carvalho Chehab obuf[0] = msg[j].len + 1; 672786baecfSMauro Carvalho Chehab obuf[1] = (msg[j].addr << 1); 673786baecfSMauro Carvalho Chehab memcpy(obuf + 2, msg[j].buf, msg[j].len); 674786baecfSMauro Carvalho Chehab dw210x_op_rw(d->udev, 0x80, 0, 0, 675786baecfSMauro Carvalho Chehab obuf, msg[j].len + 2, 676786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG); 677786baecfSMauro Carvalho Chehab break; 678786baecfSMauro Carvalho Chehab } 679786baecfSMauro Carvalho Chehab break; 680786baecfSMauro Carvalho Chehab } 681786baecfSMauro Carvalho Chehab } 682786baecfSMauro Carvalho Chehab } 683324ed533SDan Carpenter ret = num; 684786baecfSMauro Carvalho Chehab 685324ed533SDan Carpenter unlock: 686786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 687324ed533SDan Carpenter return ret; 688786baecfSMauro Carvalho Chehab } 689786baecfSMauro Carvalho Chehab 690786baecfSMauro Carvalho Chehab static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], 691786baecfSMauro Carvalho Chehab int num) 692786baecfSMauro Carvalho Chehab { 693786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 694606142afSJonathan McDowell struct dw2102_state *state; 695786baecfSMauro Carvalho Chehab 696786baecfSMauro Carvalho Chehab if (!d) 697786baecfSMauro Carvalho Chehab return -ENODEV; 698606142afSJonathan McDowell 699606142afSJonathan McDowell state = d->priv; 700606142afSJonathan McDowell 701786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 702786baecfSMauro Carvalho Chehab return -EAGAIN; 703606142afSJonathan McDowell if (mutex_lock_interruptible(&d->data_mutex) < 0) { 704606142afSJonathan McDowell mutex_unlock(&d->i2c_mutex); 705606142afSJonathan McDowell return -EAGAIN; 706606142afSJonathan McDowell } 707786baecfSMauro Carvalho Chehab 708786baecfSMauro Carvalho Chehab switch (num) { 709786baecfSMauro Carvalho Chehab case 1: 710786baecfSMauro Carvalho Chehab switch (msg[0].addr) { 711786baecfSMauro Carvalho Chehab case SU3000_STREAM_CTRL: 712606142afSJonathan McDowell state->data[0] = msg[0].buf[0] + 0x36; 713606142afSJonathan McDowell state->data[1] = 3; 714606142afSJonathan McDowell state->data[2] = 0; 715606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, 716606142afSJonathan McDowell state->data, 0, 0) < 0) 717786baecfSMauro Carvalho Chehab err("i2c transfer failed."); 718786baecfSMauro Carvalho Chehab break; 719786baecfSMauro Carvalho Chehab case DW2102_RC_QUERY: 720606142afSJonathan McDowell state->data[0] = 0x10; 721606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 1, 722606142afSJonathan McDowell state->data, 2, 0) < 0) 723786baecfSMauro Carvalho Chehab err("i2c transfer failed."); 724606142afSJonathan McDowell msg[0].buf[1] = state->data[0]; 725606142afSJonathan McDowell msg[0].buf[0] = state->data[1]; 726786baecfSMauro Carvalho Chehab break; 727786baecfSMauro Carvalho Chehab default: 728950e252cSAlyssa Milburn if (3 + msg[0].len > sizeof(state->data)) { 729950e252cSAlyssa Milburn warn("i2c wr: len=%d is too big!\n", 730950e252cSAlyssa Milburn msg[0].len); 731950e252cSAlyssa Milburn num = -EOPNOTSUPP; 732950e252cSAlyssa Milburn break; 733950e252cSAlyssa Milburn } 734950e252cSAlyssa Milburn 735786baecfSMauro Carvalho Chehab /* always i2c write*/ 736606142afSJonathan McDowell state->data[0] = 0x08; 737606142afSJonathan McDowell state->data[1] = msg[0].addr; 738606142afSJonathan McDowell state->data[2] = msg[0].len; 739786baecfSMauro Carvalho Chehab 740606142afSJonathan McDowell memcpy(&state->data[3], msg[0].buf, msg[0].len); 741786baecfSMauro Carvalho Chehab 742606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, msg[0].len + 3, 743606142afSJonathan McDowell state->data, 1, 0) < 0) 744786baecfSMauro Carvalho Chehab err("i2c transfer failed."); 745786baecfSMauro Carvalho Chehab 746786baecfSMauro Carvalho Chehab } 747786baecfSMauro Carvalho Chehab break; 748786baecfSMauro Carvalho Chehab case 2: 749786baecfSMauro Carvalho Chehab /* always i2c read */ 750950e252cSAlyssa Milburn if (4 + msg[0].len > sizeof(state->data)) { 751950e252cSAlyssa Milburn warn("i2c rd: len=%d is too big!\n", 752950e252cSAlyssa Milburn msg[0].len); 753950e252cSAlyssa Milburn num = -EOPNOTSUPP; 754950e252cSAlyssa Milburn break; 755950e252cSAlyssa Milburn } 756950e252cSAlyssa Milburn if (1 + msg[1].len > sizeof(state->data)) { 757950e252cSAlyssa Milburn warn("i2c rd: len=%d is too big!\n", 758950e252cSAlyssa Milburn msg[1].len); 759950e252cSAlyssa Milburn num = -EOPNOTSUPP; 760950e252cSAlyssa Milburn break; 761950e252cSAlyssa Milburn } 762950e252cSAlyssa Milburn 763606142afSJonathan McDowell state->data[0] = 0x09; 764606142afSJonathan McDowell state->data[1] = msg[0].len; 765606142afSJonathan McDowell state->data[2] = msg[1].len; 766606142afSJonathan McDowell state->data[3] = msg[0].addr; 767606142afSJonathan McDowell memcpy(&state->data[4], msg[0].buf, msg[0].len); 768786baecfSMauro Carvalho Chehab 769606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, msg[0].len + 4, 770606142afSJonathan McDowell state->data, msg[1].len + 1, 0) < 0) 771786baecfSMauro Carvalho Chehab err("i2c transfer failed."); 772786baecfSMauro Carvalho Chehab 773606142afSJonathan McDowell memcpy(msg[1].buf, &state->data[1], msg[1].len); 774786baecfSMauro Carvalho Chehab break; 775786baecfSMauro Carvalho Chehab default: 776786baecfSMauro Carvalho Chehab warn("more than 2 i2c messages at a time is not handled yet."); 777786baecfSMauro Carvalho Chehab break; 778786baecfSMauro Carvalho Chehab } 779606142afSJonathan McDowell mutex_unlock(&d->data_mutex); 780786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 781786baecfSMauro Carvalho Chehab return num; 782786baecfSMauro Carvalho Chehab } 783786baecfSMauro Carvalho Chehab 784786baecfSMauro Carvalho Chehab static u32 dw210x_i2c_func(struct i2c_adapter *adapter) 785786baecfSMauro Carvalho Chehab { 786786baecfSMauro Carvalho Chehab return I2C_FUNC_I2C; 787786baecfSMauro Carvalho Chehab } 788786baecfSMauro Carvalho Chehab 789786baecfSMauro Carvalho Chehab static struct i2c_algorithm dw2102_i2c_algo = { 790786baecfSMauro Carvalho Chehab .master_xfer = dw2102_i2c_transfer, 791786baecfSMauro Carvalho Chehab .functionality = dw210x_i2c_func, 792786baecfSMauro Carvalho Chehab }; 793786baecfSMauro Carvalho Chehab 794786baecfSMauro Carvalho Chehab static struct i2c_algorithm dw2102_serit_i2c_algo = { 795786baecfSMauro Carvalho Chehab .master_xfer = dw2102_serit_i2c_transfer, 796786baecfSMauro Carvalho Chehab .functionality = dw210x_i2c_func, 797786baecfSMauro Carvalho Chehab }; 798786baecfSMauro Carvalho Chehab 799786baecfSMauro Carvalho Chehab static struct i2c_algorithm dw2102_earda_i2c_algo = { 800786baecfSMauro Carvalho Chehab .master_xfer = dw2102_earda_i2c_transfer, 801786baecfSMauro Carvalho Chehab .functionality = dw210x_i2c_func, 802786baecfSMauro Carvalho Chehab }; 803786baecfSMauro Carvalho Chehab 804786baecfSMauro Carvalho Chehab static struct i2c_algorithm dw2104_i2c_algo = { 805786baecfSMauro Carvalho Chehab .master_xfer = dw2104_i2c_transfer, 806786baecfSMauro Carvalho Chehab .functionality = dw210x_i2c_func, 807786baecfSMauro Carvalho Chehab }; 808786baecfSMauro Carvalho Chehab 809786baecfSMauro Carvalho Chehab static struct i2c_algorithm dw3101_i2c_algo = { 810786baecfSMauro Carvalho Chehab .master_xfer = dw3101_i2c_transfer, 811786baecfSMauro Carvalho Chehab .functionality = dw210x_i2c_func, 812786baecfSMauro Carvalho Chehab }; 813786baecfSMauro Carvalho Chehab 814786baecfSMauro Carvalho Chehab static struct i2c_algorithm s6x0_i2c_algo = { 815786baecfSMauro Carvalho Chehab .master_xfer = s6x0_i2c_transfer, 816786baecfSMauro Carvalho Chehab .functionality = dw210x_i2c_func, 817786baecfSMauro Carvalho Chehab }; 818786baecfSMauro Carvalho Chehab 819786baecfSMauro Carvalho Chehab static struct i2c_algorithm su3000_i2c_algo = { 820786baecfSMauro Carvalho Chehab .master_xfer = su3000_i2c_transfer, 821786baecfSMauro Carvalho Chehab .functionality = dw210x_i2c_func, 822786baecfSMauro Carvalho Chehab }; 823786baecfSMauro Carvalho Chehab 824786baecfSMauro Carvalho Chehab static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) 825786baecfSMauro Carvalho Chehab { 826786baecfSMauro Carvalho Chehab int i; 827786baecfSMauro Carvalho Chehab u8 ibuf[] = {0, 0}; 828786baecfSMauro Carvalho Chehab u8 eeprom[256], eepromline[16]; 829786baecfSMauro Carvalho Chehab 830786baecfSMauro Carvalho Chehab for (i = 0; i < 256; i++) { 831786baecfSMauro Carvalho Chehab if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) { 832786baecfSMauro Carvalho Chehab err("read eeprom failed."); 833786baecfSMauro Carvalho Chehab return -1; 834786baecfSMauro Carvalho Chehab } else { 835786baecfSMauro Carvalho Chehab eepromline[i%16] = ibuf[0]; 836786baecfSMauro Carvalho Chehab eeprom[i] = ibuf[0]; 837786baecfSMauro Carvalho Chehab } 838786baecfSMauro Carvalho Chehab if ((i % 16) == 15) { 839786baecfSMauro Carvalho Chehab deb_xfer("%02x: ", i - 15); 840786baecfSMauro Carvalho Chehab debug_dump(eepromline, 16, deb_xfer); 841786baecfSMauro Carvalho Chehab } 842786baecfSMauro Carvalho Chehab } 843786baecfSMauro Carvalho Chehab 844786baecfSMauro Carvalho Chehab memcpy(mac, eeprom + 8, 6); 845786baecfSMauro Carvalho Chehab return 0; 846786baecfSMauro Carvalho Chehab }; 847786baecfSMauro Carvalho Chehab 848786baecfSMauro Carvalho Chehab static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) 849786baecfSMauro Carvalho Chehab { 850786baecfSMauro Carvalho Chehab int i, ret; 851786baecfSMauro Carvalho Chehab u8 ibuf[] = { 0 }, obuf[] = { 0 }; 852786baecfSMauro Carvalho Chehab u8 eeprom[256], eepromline[16]; 853786baecfSMauro Carvalho Chehab struct i2c_msg msg[] = { 854786baecfSMauro Carvalho Chehab { 855786baecfSMauro Carvalho Chehab .addr = 0xa0 >> 1, 856786baecfSMauro Carvalho Chehab .flags = 0, 857786baecfSMauro Carvalho Chehab .buf = obuf, 858786baecfSMauro Carvalho Chehab .len = 1, 859786baecfSMauro Carvalho Chehab }, { 860786baecfSMauro Carvalho Chehab .addr = 0xa0 >> 1, 861786baecfSMauro Carvalho Chehab .flags = I2C_M_RD, 862786baecfSMauro Carvalho Chehab .buf = ibuf, 863786baecfSMauro Carvalho Chehab .len = 1, 864786baecfSMauro Carvalho Chehab } 865786baecfSMauro Carvalho Chehab }; 866786baecfSMauro Carvalho Chehab 867786baecfSMauro Carvalho Chehab for (i = 0; i < 256; i++) { 868786baecfSMauro Carvalho Chehab obuf[0] = i; 869786baecfSMauro Carvalho Chehab ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2); 870786baecfSMauro Carvalho Chehab if (ret != 2) { 871786baecfSMauro Carvalho Chehab err("read eeprom failed."); 872786baecfSMauro Carvalho Chehab return -1; 873786baecfSMauro Carvalho Chehab } else { 874786baecfSMauro Carvalho Chehab eepromline[i % 16] = ibuf[0]; 875786baecfSMauro Carvalho Chehab eeprom[i] = ibuf[0]; 876786baecfSMauro Carvalho Chehab } 877786baecfSMauro Carvalho Chehab 878786baecfSMauro Carvalho Chehab if ((i % 16) == 15) { 879786baecfSMauro Carvalho Chehab deb_xfer("%02x: ", i - 15); 880786baecfSMauro Carvalho Chehab debug_dump(eepromline, 16, deb_xfer); 881786baecfSMauro Carvalho Chehab } 882786baecfSMauro Carvalho Chehab } 883786baecfSMauro Carvalho Chehab 884786baecfSMauro Carvalho Chehab memcpy(mac, eeprom + 16, 6); 885786baecfSMauro Carvalho Chehab return 0; 886786baecfSMauro Carvalho Chehab }; 887786baecfSMauro Carvalho Chehab 888786baecfSMauro Carvalho Chehab static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) 889786baecfSMauro Carvalho Chehab { 890786baecfSMauro Carvalho Chehab static u8 command_start[] = {0x00}; 891786baecfSMauro Carvalho Chehab static u8 command_stop[] = {0x01}; 892786baecfSMauro Carvalho Chehab struct i2c_msg msg = { 893786baecfSMauro Carvalho Chehab .addr = SU3000_STREAM_CTRL, 894786baecfSMauro Carvalho Chehab .flags = 0, 895786baecfSMauro Carvalho Chehab .buf = onoff ? command_start : command_stop, 896786baecfSMauro Carvalho Chehab .len = 1 897786baecfSMauro Carvalho Chehab }; 898786baecfSMauro Carvalho Chehab 899786baecfSMauro Carvalho Chehab i2c_transfer(&adap->dev->i2c_adap, &msg, 1); 900786baecfSMauro Carvalho Chehab 901786baecfSMauro Carvalho Chehab return 0; 902786baecfSMauro Carvalho Chehab } 903786baecfSMauro Carvalho Chehab 904786baecfSMauro Carvalho Chehab static int su3000_power_ctrl(struct dvb_usb_device *d, int i) 905786baecfSMauro Carvalho Chehab { 9062c4ffe27SOlli Salonen struct dw2102_state *state = (struct dw2102_state *)d->priv; 907606142afSJonathan McDowell int ret = 0; 908786baecfSMauro Carvalho Chehab 9090385443fSJonathan McDowell info("%s: %d, initialized %d", __func__, i, state->initialized); 910786baecfSMauro Carvalho Chehab 911786baecfSMauro Carvalho Chehab if (i && !state->initialized) { 912606142afSJonathan McDowell mutex_lock(&d->data_mutex); 913606142afSJonathan McDowell 914606142afSJonathan McDowell state->data[0] = 0xde; 915606142afSJonathan McDowell state->data[1] = 0; 916606142afSJonathan McDowell 917786baecfSMauro Carvalho Chehab state->initialized = 1; 918786baecfSMauro Carvalho Chehab /* reset board */ 919606142afSJonathan McDowell ret = dvb_usb_generic_rw(d, state->data, 2, NULL, 0, 0); 920606142afSJonathan McDowell mutex_unlock(&d->data_mutex); 921786baecfSMauro Carvalho Chehab } 922786baecfSMauro Carvalho Chehab 923606142afSJonathan McDowell return ret; 924786baecfSMauro Carvalho Chehab } 925786baecfSMauro Carvalho Chehab 926786baecfSMauro Carvalho Chehab static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) 927786baecfSMauro Carvalho Chehab { 928786baecfSMauro Carvalho Chehab int i; 929786baecfSMauro Carvalho Chehab u8 obuf[] = { 0x1f, 0xf0 }; 930786baecfSMauro Carvalho Chehab u8 ibuf[] = { 0 }; 931786baecfSMauro Carvalho Chehab struct i2c_msg msg[] = { 932786baecfSMauro Carvalho Chehab { 933786baecfSMauro Carvalho Chehab .addr = 0x51, 934786baecfSMauro Carvalho Chehab .flags = 0, 935786baecfSMauro Carvalho Chehab .buf = obuf, 936786baecfSMauro Carvalho Chehab .len = 2, 937786baecfSMauro Carvalho Chehab }, { 938786baecfSMauro Carvalho Chehab .addr = 0x51, 939786baecfSMauro Carvalho Chehab .flags = I2C_M_RD, 940786baecfSMauro Carvalho Chehab .buf = ibuf, 941786baecfSMauro Carvalho Chehab .len = 1, 942786baecfSMauro Carvalho Chehab 943786baecfSMauro Carvalho Chehab } 944786baecfSMauro Carvalho Chehab }; 945786baecfSMauro Carvalho Chehab 946786baecfSMauro Carvalho Chehab for (i = 0; i < 6; i++) { 947786baecfSMauro Carvalho Chehab obuf[1] = 0xf0 + i; 948786baecfSMauro Carvalho Chehab if (i2c_transfer(&d->i2c_adap, msg, 2) != 2) 949786baecfSMauro Carvalho Chehab break; 950786baecfSMauro Carvalho Chehab else 951786baecfSMauro Carvalho Chehab mac[i] = ibuf[0]; 952786baecfSMauro Carvalho Chehab } 953786baecfSMauro Carvalho Chehab 954786baecfSMauro Carvalho Chehab return 0; 955786baecfSMauro Carvalho Chehab } 956786baecfSMauro Carvalho Chehab 957786baecfSMauro Carvalho Chehab static int su3000_identify_state(struct usb_device *udev, 958786baecfSMauro Carvalho Chehab struct dvb_usb_device_properties *props, 959786baecfSMauro Carvalho Chehab struct dvb_usb_device_description **desc, 960786baecfSMauro Carvalho Chehab int *cold) 961786baecfSMauro Carvalho Chehab { 9620385443fSJonathan McDowell info("%s", __func__); 963786baecfSMauro Carvalho Chehab 964786baecfSMauro Carvalho Chehab *cold = 0; 965786baecfSMauro Carvalho Chehab return 0; 966786baecfSMauro Carvalho Chehab } 967786baecfSMauro Carvalho Chehab 9680df289a2SMauro Carvalho Chehab static int dw210x_set_voltage(struct dvb_frontend *fe, 9690df289a2SMauro Carvalho Chehab enum fe_sec_voltage voltage) 970786baecfSMauro Carvalho Chehab { 971786baecfSMauro Carvalho Chehab static u8 command_13v[] = {0x00, 0x01}; 972786baecfSMauro Carvalho Chehab static u8 command_18v[] = {0x01, 0x01}; 973786baecfSMauro Carvalho Chehab static u8 command_off[] = {0x00, 0x00}; 974786baecfSMauro Carvalho Chehab struct i2c_msg msg = { 975786baecfSMauro Carvalho Chehab .addr = DW2102_VOLTAGE_CTRL, 976786baecfSMauro Carvalho Chehab .flags = 0, 977786baecfSMauro Carvalho Chehab .buf = command_off, 978786baecfSMauro Carvalho Chehab .len = 2, 979786baecfSMauro Carvalho Chehab }; 980786baecfSMauro Carvalho Chehab 981786baecfSMauro Carvalho Chehab struct dvb_usb_adapter *udev_adap = 982786baecfSMauro Carvalho Chehab (struct dvb_usb_adapter *)(fe->dvb->priv); 983786baecfSMauro Carvalho Chehab if (voltage == SEC_VOLTAGE_18) 984786baecfSMauro Carvalho Chehab msg.buf = command_18v; 985786baecfSMauro Carvalho Chehab else if (voltage == SEC_VOLTAGE_13) 986786baecfSMauro Carvalho Chehab msg.buf = command_13v; 987786baecfSMauro Carvalho Chehab 988786baecfSMauro Carvalho Chehab i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); 989786baecfSMauro Carvalho Chehab 990786baecfSMauro Carvalho Chehab return 0; 991786baecfSMauro Carvalho Chehab } 992786baecfSMauro Carvalho Chehab 9930df289a2SMauro Carvalho Chehab static int s660_set_voltage(struct dvb_frontend *fe, 9940df289a2SMauro Carvalho Chehab enum fe_sec_voltage voltage) 995786baecfSMauro Carvalho Chehab { 996786baecfSMauro Carvalho Chehab struct dvb_usb_adapter *d = 997786baecfSMauro Carvalho Chehab (struct dvb_usb_adapter *)(fe->dvb->priv); 9982c4ffe27SOlli Salonen struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; 999786baecfSMauro Carvalho Chehab 1000786baecfSMauro Carvalho Chehab dw210x_set_voltage(fe, voltage); 1001786baecfSMauro Carvalho Chehab if (st->old_set_voltage) 1002786baecfSMauro Carvalho Chehab st->old_set_voltage(fe, voltage); 1003786baecfSMauro Carvalho Chehab 1004786baecfSMauro Carvalho Chehab return 0; 1005786baecfSMauro Carvalho Chehab } 1006786baecfSMauro Carvalho Chehab 1007786baecfSMauro Carvalho Chehab static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon) 1008786baecfSMauro Carvalho Chehab { 1009786baecfSMauro Carvalho Chehab static u8 led_off[] = { 0 }; 1010786baecfSMauro Carvalho Chehab static u8 led_on[] = { 1 }; 1011786baecfSMauro Carvalho Chehab struct i2c_msg msg = { 1012786baecfSMauro Carvalho Chehab .addr = DW2102_LED_CTRL, 1013786baecfSMauro Carvalho Chehab .flags = 0, 1014786baecfSMauro Carvalho Chehab .buf = led_off, 1015786baecfSMauro Carvalho Chehab .len = 1 1016786baecfSMauro Carvalho Chehab }; 1017786baecfSMauro Carvalho Chehab struct dvb_usb_adapter *udev_adap = 1018786baecfSMauro Carvalho Chehab (struct dvb_usb_adapter *)(fe->dvb->priv); 1019786baecfSMauro Carvalho Chehab 1020786baecfSMauro Carvalho Chehab if (offon) 1021786baecfSMauro Carvalho Chehab msg.buf = led_on; 1022786baecfSMauro Carvalho Chehab i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); 1023786baecfSMauro Carvalho Chehab } 1024786baecfSMauro Carvalho Chehab 10250df289a2SMauro Carvalho Chehab static int tt_s2_4600_read_status(struct dvb_frontend *fe, 10260df289a2SMauro Carvalho Chehab enum fe_status *status) 1027356484caSOlli Salonen { 1028356484caSOlli Salonen struct dvb_usb_adapter *d = 1029356484caSOlli Salonen (struct dvb_usb_adapter *)(fe->dvb->priv); 1030356484caSOlli Salonen struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; 1031356484caSOlli Salonen int ret; 1032356484caSOlli Salonen 1033356484caSOlli Salonen ret = st->fe_read_status(fe, status); 1034356484caSOlli Salonen 1035356484caSOlli Salonen /* resync slave fifo when signal change from unlock to lock */ 1036356484caSOlli Salonen if ((*status & FE_HAS_LOCK) && (!st->last_lock)) 1037356484caSOlli Salonen su3000_streaming_ctrl(d, 1); 1038356484caSOlli Salonen 1039356484caSOlli Salonen st->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0; 1040356484caSOlli Salonen return ret; 1041356484caSOlli Salonen } 1042356484caSOlli Salonen 1043786baecfSMauro Carvalho Chehab static struct stv0299_config sharp_z0194a_config = { 1044786baecfSMauro Carvalho Chehab .demod_address = 0x68, 1045786baecfSMauro Carvalho Chehab .inittab = sharp_z0194a_inittab, 1046786baecfSMauro Carvalho Chehab .mclk = 88000000UL, 1047786baecfSMauro Carvalho Chehab .invert = 1, 1048786baecfSMauro Carvalho Chehab .skip_reinit = 0, 1049786baecfSMauro Carvalho Chehab .lock_output = STV0299_LOCKOUTPUT_1, 1050786baecfSMauro Carvalho Chehab .volt13_op0_op1 = STV0299_VOLT13_OP1, 1051786baecfSMauro Carvalho Chehab .min_delay_ms = 100, 1052786baecfSMauro Carvalho Chehab .set_symbol_rate = sharp_z0194a_set_symbol_rate, 1053786baecfSMauro Carvalho Chehab }; 1054786baecfSMauro Carvalho Chehab 1055786baecfSMauro Carvalho Chehab static struct cx24116_config dw2104_config = { 1056786baecfSMauro Carvalho Chehab .demod_address = 0x55, 1057786baecfSMauro Carvalho Chehab .mpg_clk_pos_pol = 0x01, 1058786baecfSMauro Carvalho Chehab }; 1059786baecfSMauro Carvalho Chehab 1060786baecfSMauro Carvalho Chehab static struct si21xx_config serit_sp1511lhb_config = { 1061786baecfSMauro Carvalho Chehab .demod_address = 0x68, 1062786baecfSMauro Carvalho Chehab .min_delay_ms = 100, 1063786baecfSMauro Carvalho Chehab 1064786baecfSMauro Carvalho Chehab }; 1065786baecfSMauro Carvalho Chehab 1066786baecfSMauro Carvalho Chehab static struct tda10023_config dw3101_tda10023_config = { 1067786baecfSMauro Carvalho Chehab .demod_address = 0x0c, 1068786baecfSMauro Carvalho Chehab .invert = 1, 1069786baecfSMauro Carvalho Chehab }; 1070786baecfSMauro Carvalho Chehab 1071786baecfSMauro Carvalho Chehab static struct mt312_config zl313_config = { 1072786baecfSMauro Carvalho Chehab .demod_address = 0x0e, 1073786baecfSMauro Carvalho Chehab }; 1074786baecfSMauro Carvalho Chehab 1075786baecfSMauro Carvalho Chehab static struct ds3000_config dw2104_ds3000_config = { 1076786baecfSMauro Carvalho Chehab .demod_address = 0x68, 1077786baecfSMauro Carvalho Chehab }; 1078786baecfSMauro Carvalho Chehab 107973f0af44SKonstantin Dimitrov static struct ts2020_config dw2104_ts2020_config = { 108073f0af44SKonstantin Dimitrov .tuner_address = 0x60, 1081b858c331SIgor M. Liplianin .clk_out_div = 1, 108203a67279SJohn Horan .frequency_div = 1060000, 108373f0af44SKonstantin Dimitrov }; 108473f0af44SKonstantin Dimitrov 108543385c8aSIgor M. Liplianin static struct ds3000_config s660_ds3000_config = { 108643385c8aSIgor M. Liplianin .demod_address = 0x68, 1087b858c331SIgor M. Liplianin .ci_mode = 1, 108843385c8aSIgor M. Liplianin .set_lock_led = dw210x_led_ctrl, 108943385c8aSIgor M. Liplianin }; 109043385c8aSIgor M. Liplianin 109103a67279SJohn Horan static struct ts2020_config s660_ts2020_config = { 109203a67279SJohn Horan .tuner_address = 0x60, 109303a67279SJohn Horan .clk_out_div = 1, 109403a67279SJohn Horan .frequency_div = 1146000, 109503a67279SJohn Horan }; 109603a67279SJohn Horan 1097786baecfSMauro Carvalho Chehab static struct stv0900_config dw2104a_stv0900_config = { 1098786baecfSMauro Carvalho Chehab .demod_address = 0x6a, 1099786baecfSMauro Carvalho Chehab .demod_mode = 0, 1100786baecfSMauro Carvalho Chehab .xtal = 27000000, 1101786baecfSMauro Carvalho Chehab .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ 1102786baecfSMauro Carvalho Chehab .diseqc_mode = 2,/* 2/3 PWM */ 1103786baecfSMauro Carvalho Chehab .tun1_maddress = 0,/* 0x60 */ 1104786baecfSMauro Carvalho Chehab .tun1_adc = 0,/* 2 Vpp */ 1105786baecfSMauro Carvalho Chehab .path1_mode = 3, 1106786baecfSMauro Carvalho Chehab }; 1107786baecfSMauro Carvalho Chehab 1108786baecfSMauro Carvalho Chehab static struct stb6100_config dw2104a_stb6100_config = { 1109786baecfSMauro Carvalho Chehab .tuner_address = 0x60, 1110786baecfSMauro Carvalho Chehab .refclock = 27000000, 1111786baecfSMauro Carvalho Chehab }; 1112786baecfSMauro Carvalho Chehab 1113786baecfSMauro Carvalho Chehab static struct stv0900_config dw2104_stv0900_config = { 1114786baecfSMauro Carvalho Chehab .demod_address = 0x68, 1115786baecfSMauro Carvalho Chehab .demod_mode = 0, 1116786baecfSMauro Carvalho Chehab .xtal = 8000000, 1117786baecfSMauro Carvalho Chehab .clkmode = 3, 1118786baecfSMauro Carvalho Chehab .diseqc_mode = 2, 1119786baecfSMauro Carvalho Chehab .tun1_maddress = 0, 1120786baecfSMauro Carvalho Chehab .tun1_adc = 1,/* 1 Vpp */ 1121786baecfSMauro Carvalho Chehab .path1_mode = 3, 1122786baecfSMauro Carvalho Chehab }; 1123786baecfSMauro Carvalho Chehab 1124786baecfSMauro Carvalho Chehab static struct stv6110_config dw2104_stv6110_config = { 1125786baecfSMauro Carvalho Chehab .i2c_address = 0x60, 1126786baecfSMauro Carvalho Chehab .mclk = 16000000, 1127786baecfSMauro Carvalho Chehab .clk_div = 1, 1128786baecfSMauro Carvalho Chehab }; 1129786baecfSMauro Carvalho Chehab 1130786baecfSMauro Carvalho Chehab static struct stv0900_config prof_7500_stv0900_config = { 1131786baecfSMauro Carvalho Chehab .demod_address = 0x6a, 1132786baecfSMauro Carvalho Chehab .demod_mode = 0, 1133786baecfSMauro Carvalho Chehab .xtal = 27000000, 1134786baecfSMauro Carvalho Chehab .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ 1135786baecfSMauro Carvalho Chehab .diseqc_mode = 2,/* 2/3 PWM */ 1136786baecfSMauro Carvalho Chehab .tun1_maddress = 0,/* 0x60 */ 1137786baecfSMauro Carvalho Chehab .tun1_adc = 0,/* 2 Vpp */ 1138786baecfSMauro Carvalho Chehab .path1_mode = 3, 1139786baecfSMauro Carvalho Chehab .tun1_type = 3, 1140786baecfSMauro Carvalho Chehab .set_lock_led = dw210x_led_ctrl, 1141786baecfSMauro Carvalho Chehab }; 1142786baecfSMauro Carvalho Chehab 1143786baecfSMauro Carvalho Chehab static struct ds3000_config su3000_ds3000_config = { 1144786baecfSMauro Carvalho Chehab .demod_address = 0x68, 1145786baecfSMauro Carvalho Chehab .ci_mode = 1, 1146b858c331SIgor M. Liplianin .set_lock_led = dw210x_led_ctrl, 114773f0af44SKonstantin Dimitrov }; 114873f0af44SKonstantin Dimitrov 114951d882edSEvgeny Plehov static struct cxd2820r_config cxd2820r_config = { 115051d882edSEvgeny Plehov .i2c_address = 0x6c, /* (0xd8 >> 1) */ 115151d882edSEvgeny Plehov .ts_mode = 0x38, 11527b71ef7eSCrazyCat .ts_clock_inv = 1, 115351d882edSEvgeny Plehov }; 115451d882edSEvgeny Plehov 115551d882edSEvgeny Plehov static struct tda18271_config tda18271_config = { 115651d882edSEvgeny Plehov .output_opt = TDA18271_OUTPUT_LT_OFF, 115751d882edSEvgeny Plehov .gate = TDA18271_GATE_DIGITAL, 115851d882edSEvgeny Plehov }; 115951d882edSEvgeny Plehov 1160955d00acSIgor M. Liplianin static u8 m88rs2000_inittab[] = { 1161955d00acSIgor M. Liplianin DEMOD_WRITE, 0x9a, 0x30, 1162955d00acSIgor M. Liplianin DEMOD_WRITE, 0x00, 0x01, 1163955d00acSIgor M. Liplianin WRITE_DELAY, 0x19, 0x00, 1164955d00acSIgor M. Liplianin DEMOD_WRITE, 0x00, 0x00, 1165955d00acSIgor M. Liplianin DEMOD_WRITE, 0x9a, 0xb0, 1166955d00acSIgor M. Liplianin DEMOD_WRITE, 0x81, 0xc1, 1167955d00acSIgor M. Liplianin DEMOD_WRITE, 0x81, 0x81, 1168955d00acSIgor M. Liplianin DEMOD_WRITE, 0x86, 0xc6, 1169955d00acSIgor M. Liplianin DEMOD_WRITE, 0x9a, 0x30, 1170955d00acSIgor M. Liplianin DEMOD_WRITE, 0xf0, 0x80, 1171955d00acSIgor M. Liplianin DEMOD_WRITE, 0xf1, 0xbf, 1172955d00acSIgor M. Liplianin DEMOD_WRITE, 0xb0, 0x45, 1173955d00acSIgor M. Liplianin DEMOD_WRITE, 0xb2, 0x01, 1174955d00acSIgor M. Liplianin DEMOD_WRITE, 0x9a, 0xb0, 1175955d00acSIgor M. Liplianin 0xff, 0xaa, 0xff 1176955d00acSIgor M. Liplianin }; 1177955d00acSIgor M. Liplianin 1178955d00acSIgor M. Liplianin static struct m88rs2000_config s421_m88rs2000_config = { 1179955d00acSIgor M. Liplianin .demod_addr = 0x68, 1180955d00acSIgor M. Liplianin .inittab = m88rs2000_inittab, 1181955d00acSIgor M. Liplianin }; 1182955d00acSIgor M. Liplianin 1183786baecfSMauro Carvalho Chehab static int dw2104_frontend_attach(struct dvb_usb_adapter *d) 1184786baecfSMauro Carvalho Chehab { 1185786baecfSMauro Carvalho Chehab struct dvb_tuner_ops *tuner_ops = NULL; 1186786baecfSMauro Carvalho Chehab 1187786baecfSMauro Carvalho Chehab if (demod_probe & 4) { 1188786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config, 1189786baecfSMauro Carvalho Chehab &d->dev->i2c_adap, 0); 1190786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe != NULL) { 1191786baecfSMauro Carvalho Chehab if (dvb_attach(stb6100_attach, d->fe_adap[0].fe, 1192786baecfSMauro Carvalho Chehab &dw2104a_stb6100_config, 1193786baecfSMauro Carvalho Chehab &d->dev->i2c_adap)) { 1194786baecfSMauro Carvalho Chehab tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops; 1195786baecfSMauro Carvalho Chehab tuner_ops->set_frequency = stb6100_set_freq; 1196786baecfSMauro Carvalho Chehab tuner_ops->get_frequency = stb6100_get_freq; 1197786baecfSMauro Carvalho Chehab tuner_ops->set_bandwidth = stb6100_set_bandw; 1198786baecfSMauro Carvalho Chehab tuner_ops->get_bandwidth = stb6100_get_bandw; 1199786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 12000385443fSJonathan McDowell info("Attached STV0900+STB6100!"); 1201786baecfSMauro Carvalho Chehab return 0; 1202786baecfSMauro Carvalho Chehab } 1203786baecfSMauro Carvalho Chehab } 1204786baecfSMauro Carvalho Chehab } 1205786baecfSMauro Carvalho Chehab 1206786baecfSMauro Carvalho Chehab if (demod_probe & 2) { 1207786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config, 1208786baecfSMauro Carvalho Chehab &d->dev->i2c_adap, 0); 1209786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe != NULL) { 1210786baecfSMauro Carvalho Chehab if (dvb_attach(stv6110_attach, d->fe_adap[0].fe, 1211786baecfSMauro Carvalho Chehab &dw2104_stv6110_config, 1212786baecfSMauro Carvalho Chehab &d->dev->i2c_adap)) { 1213786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 12140385443fSJonathan McDowell info("Attached STV0900+STV6110A!"); 1215786baecfSMauro Carvalho Chehab return 0; 1216786baecfSMauro Carvalho Chehab } 1217786baecfSMauro Carvalho Chehab } 1218786baecfSMauro Carvalho Chehab } 1219786baecfSMauro Carvalho Chehab 1220786baecfSMauro Carvalho Chehab if (demod_probe & 1) { 1221786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config, 1222786baecfSMauro Carvalho Chehab &d->dev->i2c_adap); 1223786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe != NULL) { 1224786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 12250385443fSJonathan McDowell info("Attached cx24116!"); 1226786baecfSMauro Carvalho Chehab return 0; 1227786baecfSMauro Carvalho Chehab } 1228786baecfSMauro Carvalho Chehab } 1229786baecfSMauro Carvalho Chehab 1230786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config, 1231786baecfSMauro Carvalho Chehab &d->dev->i2c_adap); 1232786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe != NULL) { 123373f0af44SKonstantin Dimitrov dvb_attach(ts2020_attach, d->fe_adap[0].fe, 123473f0af44SKonstantin Dimitrov &dw2104_ts2020_config, &d->dev->i2c_adap); 1235786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 12360385443fSJonathan McDowell info("Attached DS3000!"); 1237786baecfSMauro Carvalho Chehab return 0; 1238786baecfSMauro Carvalho Chehab } 1239786baecfSMauro Carvalho Chehab 1240786baecfSMauro Carvalho Chehab return -EIO; 1241786baecfSMauro Carvalho Chehab } 1242786baecfSMauro Carvalho Chehab 1243786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties dw2102_properties; 1244786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties dw2104_properties; 1245786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties s6x0_properties; 1246786baecfSMauro Carvalho Chehab 1247786baecfSMauro Carvalho Chehab static int dw2102_frontend_attach(struct dvb_usb_adapter *d) 1248786baecfSMauro Carvalho Chehab { 1249786baecfSMauro Carvalho Chehab if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) { 1250786baecfSMauro Carvalho Chehab /*dw2102_properties.adapter->tuner_attach = NULL;*/ 1251786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config, 1252786baecfSMauro Carvalho Chehab &d->dev->i2c_adap); 1253786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe != NULL) { 1254786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 12550385443fSJonathan McDowell info("Attached si21xx!"); 1256786baecfSMauro Carvalho Chehab return 0; 1257786baecfSMauro Carvalho Chehab } 1258786baecfSMauro Carvalho Chehab } 1259786baecfSMauro Carvalho Chehab 1260786baecfSMauro Carvalho Chehab if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) { 1261786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config, 1262786baecfSMauro Carvalho Chehab &d->dev->i2c_adap); 1263786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe != NULL) { 1264786baecfSMauro Carvalho Chehab if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, 1265786baecfSMauro Carvalho Chehab &d->dev->i2c_adap)) { 1266786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 12670385443fSJonathan McDowell info("Attached stv0288!"); 1268786baecfSMauro Carvalho Chehab return 0; 1269786baecfSMauro Carvalho Chehab } 1270786baecfSMauro Carvalho Chehab } 1271786baecfSMauro Carvalho Chehab } 1272786baecfSMauro Carvalho Chehab 1273786baecfSMauro Carvalho Chehab if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) { 1274786baecfSMauro Carvalho Chehab /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ 1275786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, 1276786baecfSMauro Carvalho Chehab &d->dev->i2c_adap); 1277786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe != NULL) { 1278786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 12790385443fSJonathan McDowell info("Attached stv0299!"); 1280786baecfSMauro Carvalho Chehab return 0; 1281786baecfSMauro Carvalho Chehab } 1282786baecfSMauro Carvalho Chehab } 1283786baecfSMauro Carvalho Chehab return -EIO; 1284786baecfSMauro Carvalho Chehab } 1285786baecfSMauro Carvalho Chehab 1286786baecfSMauro Carvalho Chehab static int dw3101_frontend_attach(struct dvb_usb_adapter *d) 1287786baecfSMauro Carvalho Chehab { 1288786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config, 1289786baecfSMauro Carvalho Chehab &d->dev->i2c_adap, 0x48); 1290786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe != NULL) { 12910385443fSJonathan McDowell info("Attached tda10023!"); 1292786baecfSMauro Carvalho Chehab return 0; 1293786baecfSMauro Carvalho Chehab } 1294786baecfSMauro Carvalho Chehab return -EIO; 1295786baecfSMauro Carvalho Chehab } 1296786baecfSMauro Carvalho Chehab 1297786baecfSMauro Carvalho Chehab static int zl100313_frontend_attach(struct dvb_usb_adapter *d) 1298786baecfSMauro Carvalho Chehab { 1299786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config, 1300786baecfSMauro Carvalho Chehab &d->dev->i2c_adap); 1301786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe != NULL) { 1302786baecfSMauro Carvalho Chehab if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60, 1303786baecfSMauro Carvalho Chehab &d->dev->i2c_adap)) { 1304786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 13050385443fSJonathan McDowell info("Attached zl100313+zl10039!"); 1306786baecfSMauro Carvalho Chehab return 0; 1307786baecfSMauro Carvalho Chehab } 1308786baecfSMauro Carvalho Chehab } 1309786baecfSMauro Carvalho Chehab 1310786baecfSMauro Carvalho Chehab return -EIO; 1311786baecfSMauro Carvalho Chehab } 1312786baecfSMauro Carvalho Chehab 1313786baecfSMauro Carvalho Chehab static int stv0288_frontend_attach(struct dvb_usb_adapter *d) 1314786baecfSMauro Carvalho Chehab { 1315786baecfSMauro Carvalho Chehab u8 obuf[] = {7, 1}; 1316786baecfSMauro Carvalho Chehab 1317786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config, 1318786baecfSMauro Carvalho Chehab &d->dev->i2c_adap); 1319786baecfSMauro Carvalho Chehab 1320786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe == NULL) 1321786baecfSMauro Carvalho Chehab return -EIO; 1322786baecfSMauro Carvalho Chehab 1323786baecfSMauro Carvalho Chehab if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap)) 1324786baecfSMauro Carvalho Chehab return -EIO; 1325786baecfSMauro Carvalho Chehab 1326786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 1327786baecfSMauro Carvalho Chehab 1328786baecfSMauro Carvalho Chehab dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); 1329786baecfSMauro Carvalho Chehab 13300385443fSJonathan McDowell info("Attached stv0288+stb6000!"); 1331786baecfSMauro Carvalho Chehab 1332786baecfSMauro Carvalho Chehab return 0; 1333786baecfSMauro Carvalho Chehab 1334786baecfSMauro Carvalho Chehab } 1335786baecfSMauro Carvalho Chehab 1336786baecfSMauro Carvalho Chehab static int ds3000_frontend_attach(struct dvb_usb_adapter *d) 1337786baecfSMauro Carvalho Chehab { 13382c4ffe27SOlli Salonen struct dw2102_state *st = d->dev->priv; 1339786baecfSMauro Carvalho Chehab u8 obuf[] = {7, 1}; 1340786baecfSMauro Carvalho Chehab 134143385c8aSIgor M. Liplianin d->fe_adap[0].fe = dvb_attach(ds3000_attach, &s660_ds3000_config, 1342786baecfSMauro Carvalho Chehab &d->dev->i2c_adap); 1343786baecfSMauro Carvalho Chehab 1344786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe == NULL) 1345786baecfSMauro Carvalho Chehab return -EIO; 1346786baecfSMauro Carvalho Chehab 134703a67279SJohn Horan dvb_attach(ts2020_attach, d->fe_adap[0].fe, &s660_ts2020_config, 134873f0af44SKonstantin Dimitrov &d->dev->i2c_adap); 134973f0af44SKonstantin Dimitrov 1350786baecfSMauro Carvalho Chehab st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage; 1351786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage; 1352786baecfSMauro Carvalho Chehab 1353786baecfSMauro Carvalho Chehab dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); 1354786baecfSMauro Carvalho Chehab 13550385443fSJonathan McDowell info("Attached ds3000+ts2020!"); 1356786baecfSMauro Carvalho Chehab 1357786baecfSMauro Carvalho Chehab return 0; 1358786baecfSMauro Carvalho Chehab } 1359786baecfSMauro Carvalho Chehab 1360786baecfSMauro Carvalho Chehab static int prof_7500_frontend_attach(struct dvb_usb_adapter *d) 1361786baecfSMauro Carvalho Chehab { 1362786baecfSMauro Carvalho Chehab u8 obuf[] = {7, 1}; 1363786baecfSMauro Carvalho Chehab 1364786baecfSMauro Carvalho Chehab d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config, 1365786baecfSMauro Carvalho Chehab &d->dev->i2c_adap, 0); 1366786baecfSMauro Carvalho Chehab if (d->fe_adap[0].fe == NULL) 1367786baecfSMauro Carvalho Chehab return -EIO; 1368786baecfSMauro Carvalho Chehab 1369786baecfSMauro Carvalho Chehab d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; 1370786baecfSMauro Carvalho Chehab 1371786baecfSMauro Carvalho Chehab dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); 1372786baecfSMauro Carvalho Chehab 13730385443fSJonathan McDowell info("Attached STV0900+STB6100A!"); 1374786baecfSMauro Carvalho Chehab 1375786baecfSMauro Carvalho Chehab return 0; 1376786baecfSMauro Carvalho Chehab } 1377786baecfSMauro Carvalho Chehab 1378606142afSJonathan McDowell static int su3000_frontend_attach(struct dvb_usb_adapter *adap) 1379786baecfSMauro Carvalho Chehab { 1380606142afSJonathan McDowell struct dvb_usb_device *d = adap->dev; 1381606142afSJonathan McDowell struct dw2102_state *state = d->priv; 1382786baecfSMauro Carvalho Chehab 1383606142afSJonathan McDowell mutex_lock(&d->data_mutex); 1384606142afSJonathan McDowell 1385606142afSJonathan McDowell state->data[0] = 0xe; 1386606142afSJonathan McDowell state->data[1] = 0x80; 1387606142afSJonathan McDowell state->data[2] = 0; 1388606142afSJonathan McDowell 1389606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 1390786baecfSMauro Carvalho Chehab err("command 0x0e transfer failed."); 1391786baecfSMauro Carvalho Chehab 1392606142afSJonathan McDowell state->data[0] = 0xe; 1393606142afSJonathan McDowell state->data[1] = 0x02; 1394606142afSJonathan McDowell state->data[2] = 1; 1395b858c331SIgor M. Liplianin 1396606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 1397b858c331SIgor M. Liplianin err("command 0x0e transfer failed."); 1398b858c331SIgor M. Liplianin msleep(300); 1399b858c331SIgor M. Liplianin 1400606142afSJonathan McDowell state->data[0] = 0xe; 1401606142afSJonathan McDowell state->data[1] = 0x83; 1402606142afSJonathan McDowell state->data[2] = 0; 1403786baecfSMauro Carvalho Chehab 1404606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 1405786baecfSMauro Carvalho Chehab err("command 0x0e transfer failed."); 1406786baecfSMauro Carvalho Chehab 1407606142afSJonathan McDowell state->data[0] = 0xe; 1408606142afSJonathan McDowell state->data[1] = 0x83; 1409606142afSJonathan McDowell state->data[2] = 1; 1410786baecfSMauro Carvalho Chehab 1411606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 1412786baecfSMauro Carvalho Chehab err("command 0x0e transfer failed."); 1413786baecfSMauro Carvalho Chehab 1414606142afSJonathan McDowell state->data[0] = 0x51; 1415786baecfSMauro Carvalho Chehab 1416606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0) 1417786baecfSMauro Carvalho Chehab err("command 0x51 transfer failed."); 1418786baecfSMauro Carvalho Chehab 1419606142afSJonathan McDowell mutex_unlock(&d->data_mutex); 1420606142afSJonathan McDowell 1421606142afSJonathan McDowell adap->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config, 1422606142afSJonathan McDowell &d->i2c_adap); 1423606142afSJonathan McDowell if (adap->fe_adap[0].fe == NULL) 1424786baecfSMauro Carvalho Chehab return -EIO; 1425786baecfSMauro Carvalho Chehab 1426606142afSJonathan McDowell if (dvb_attach(ts2020_attach, adap->fe_adap[0].fe, 1427b858c331SIgor M. Liplianin &dw2104_ts2020_config, 1428606142afSJonathan McDowell &d->i2c_adap)) { 14290385443fSJonathan McDowell info("Attached DS3000/TS2020!"); 1430786baecfSMauro Carvalho Chehab return 0; 1431786baecfSMauro Carvalho Chehab } 1432786baecfSMauro Carvalho Chehab 14330385443fSJonathan McDowell info("Failed to attach DS3000/TS2020!"); 1434b858c331SIgor M. Liplianin return -EIO; 1435b858c331SIgor M. Liplianin } 1436b858c331SIgor M. Liplianin 1437606142afSJonathan McDowell static int t220_frontend_attach(struct dvb_usb_adapter *adap) 143851d882edSEvgeny Plehov { 1439606142afSJonathan McDowell struct dvb_usb_device *d = adap->dev; 1440606142afSJonathan McDowell struct dw2102_state *state = d->priv; 144151d882edSEvgeny Plehov 1442606142afSJonathan McDowell mutex_lock(&d->data_mutex); 1443606142afSJonathan McDowell 1444606142afSJonathan McDowell state->data[0] = 0xe; 1445606142afSJonathan McDowell state->data[1] = 0x87; 1446606142afSJonathan McDowell state->data[2] = 0x0; 1447606142afSJonathan McDowell 1448606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 144951d882edSEvgeny Plehov err("command 0x0e transfer failed."); 145051d882edSEvgeny Plehov 1451606142afSJonathan McDowell state->data[0] = 0xe; 1452606142afSJonathan McDowell state->data[1] = 0x86; 1453606142afSJonathan McDowell state->data[2] = 1; 14547b71ef7eSCrazyCat 1455606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 14567b71ef7eSCrazyCat err("command 0x0e transfer failed."); 14577b71ef7eSCrazyCat 1458606142afSJonathan McDowell state->data[0] = 0xe; 1459606142afSJonathan McDowell state->data[1] = 0x80; 1460606142afSJonathan McDowell state->data[2] = 0; 146151d882edSEvgeny Plehov 1462606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 146351d882edSEvgeny Plehov err("command 0x0e transfer failed."); 146451d882edSEvgeny Plehov 14657b71ef7eSCrazyCat msleep(50); 146651d882edSEvgeny Plehov 1467606142afSJonathan McDowell state->data[0] = 0xe; 1468606142afSJonathan McDowell state->data[1] = 0x80; 1469606142afSJonathan McDowell state->data[2] = 1; 147051d882edSEvgeny Plehov 1471606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 147251d882edSEvgeny Plehov err("command 0x0e transfer failed."); 147351d882edSEvgeny Plehov 1474606142afSJonathan McDowell state->data[0] = 0x51; 147551d882edSEvgeny Plehov 1476606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0) 147751d882edSEvgeny Plehov err("command 0x51 transfer failed."); 147851d882edSEvgeny Plehov 1479606142afSJonathan McDowell mutex_unlock(&d->data_mutex); 1480606142afSJonathan McDowell 1481606142afSJonathan McDowell adap->fe_adap[0].fe = dvb_attach(cxd2820r_attach, &cxd2820r_config, 1482606142afSJonathan McDowell &d->i2c_adap, NULL); 1483606142afSJonathan McDowell if (adap->fe_adap[0].fe != NULL) { 1484606142afSJonathan McDowell if (dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0x60, 1485606142afSJonathan McDowell &d->i2c_adap, &tda18271_config)) { 14860385443fSJonathan McDowell info("Attached TDA18271HD/CXD2820R!"); 148751d882edSEvgeny Plehov return 0; 148851d882edSEvgeny Plehov } 148951d882edSEvgeny Plehov } 149051d882edSEvgeny Plehov 14910385443fSJonathan McDowell info("Failed to attach TDA18271HD/CXD2820R!"); 149251d882edSEvgeny Plehov return -EIO; 149351d882edSEvgeny Plehov } 149451d882edSEvgeny Plehov 1495606142afSJonathan McDowell static int m88rs2000_frontend_attach(struct dvb_usb_adapter *adap) 1496955d00acSIgor M. Liplianin { 1497606142afSJonathan McDowell struct dvb_usb_device *d = adap->dev; 1498606142afSJonathan McDowell struct dw2102_state *state = d->priv; 1499955d00acSIgor M. Liplianin 1500606142afSJonathan McDowell mutex_lock(&d->data_mutex); 1501606142afSJonathan McDowell 1502606142afSJonathan McDowell state->data[0] = 0x51; 1503606142afSJonathan McDowell 1504606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0) 1505955d00acSIgor M. Liplianin err("command 0x51 transfer failed."); 1506955d00acSIgor M. Liplianin 1507606142afSJonathan McDowell mutex_unlock(&d->data_mutex); 1508b858c331SIgor M. Liplianin 1509606142afSJonathan McDowell adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach, 1510606142afSJonathan McDowell &s421_m88rs2000_config, 1511606142afSJonathan McDowell &d->i2c_adap); 1512606142afSJonathan McDowell 1513606142afSJonathan McDowell if (adap->fe_adap[0].fe == NULL) 1514955d00acSIgor M. Liplianin return -EIO; 1515955d00acSIgor M. Liplianin 1516606142afSJonathan McDowell if (dvb_attach(ts2020_attach, adap->fe_adap[0].fe, 1517b858c331SIgor M. Liplianin &dw2104_ts2020_config, 1518606142afSJonathan McDowell &d->i2c_adap)) { 15190385443fSJonathan McDowell info("Attached RS2000/TS2020!"); 1520955d00acSIgor M. Liplianin return 0; 1521955d00acSIgor M. Liplianin } 1522955d00acSIgor M. Liplianin 15230385443fSJonathan McDowell info("Failed to attach RS2000/TS2020!"); 1524b858c331SIgor M. Liplianin return -EIO; 1525b858c331SIgor M. Liplianin } 1526b858c331SIgor M. Liplianin 152727254c36SOlli Salonen static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap) 152827254c36SOlli Salonen { 152927254c36SOlli Salonen struct dvb_usb_device *d = adap->dev; 153027254c36SOlli Salonen struct dw2102_state *state = d->priv; 153127254c36SOlli Salonen struct i2c_adapter *i2c_adapter; 153227254c36SOlli Salonen struct i2c_client *client; 1533f3c6abcaSOlli Salonen struct i2c_board_info board_info; 1534f3c6abcaSOlli Salonen struct m88ds3103_platform_data m88ds3103_pdata = {}; 15350fecb6c0SAntti Palosaari struct ts2020_config ts2020_config = {}; 153627254c36SOlli Salonen 1537606142afSJonathan McDowell mutex_lock(&d->data_mutex); 1538606142afSJonathan McDowell 1539606142afSJonathan McDowell state->data[0] = 0xe; 1540606142afSJonathan McDowell state->data[1] = 0x80; 1541606142afSJonathan McDowell state->data[2] = 0x0; 1542606142afSJonathan McDowell 1543606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 154427254c36SOlli Salonen err("command 0x0e transfer failed."); 154527254c36SOlli Salonen 1546606142afSJonathan McDowell state->data[0] = 0xe; 1547606142afSJonathan McDowell state->data[1] = 0x02; 1548606142afSJonathan McDowell state->data[2] = 1; 154927254c36SOlli Salonen 1550606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 155127254c36SOlli Salonen err("command 0x0e transfer failed."); 155227254c36SOlli Salonen msleep(300); 155327254c36SOlli Salonen 1554606142afSJonathan McDowell state->data[0] = 0xe; 1555606142afSJonathan McDowell state->data[1] = 0x83; 1556606142afSJonathan McDowell state->data[2] = 0; 155727254c36SOlli Salonen 1558606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 155927254c36SOlli Salonen err("command 0x0e transfer failed."); 156027254c36SOlli Salonen 1561606142afSJonathan McDowell state->data[0] = 0xe; 1562606142afSJonathan McDowell state->data[1] = 0x83; 1563606142afSJonathan McDowell state->data[2] = 1; 156427254c36SOlli Salonen 1565606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) 156627254c36SOlli Salonen err("command 0x0e transfer failed."); 156727254c36SOlli Salonen 1568606142afSJonathan McDowell state->data[0] = 0x51; 156927254c36SOlli Salonen 1570606142afSJonathan McDowell if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0) 157127254c36SOlli Salonen err("command 0x51 transfer failed."); 157227254c36SOlli Salonen 1573606142afSJonathan McDowell mutex_unlock(&d->data_mutex); 1574606142afSJonathan McDowell 1575f3c6abcaSOlli Salonen /* attach demod */ 1576f3c6abcaSOlli Salonen m88ds3103_pdata.clk = 27000000; 1577f3c6abcaSOlli Salonen m88ds3103_pdata.i2c_wr_max = 33; 1578f3c6abcaSOlli Salonen m88ds3103_pdata.ts_mode = M88DS3103_TS_CI; 1579f3c6abcaSOlli Salonen m88ds3103_pdata.ts_clk = 16000; 1580f3c6abcaSOlli Salonen m88ds3103_pdata.ts_clk_pol = 0; 1581f3c6abcaSOlli Salonen m88ds3103_pdata.spec_inv = 0; 1582f3c6abcaSOlli Salonen m88ds3103_pdata.agc = 0x99; 1583f3c6abcaSOlli Salonen m88ds3103_pdata.agc_inv = 0; 1584f3c6abcaSOlli Salonen m88ds3103_pdata.clk_out = M88DS3103_CLOCK_OUT_ENABLED; 1585f3c6abcaSOlli Salonen m88ds3103_pdata.envelope_mode = 0; 1586f3c6abcaSOlli Salonen m88ds3103_pdata.lnb_hv_pol = 1; 1587f3c6abcaSOlli Salonen m88ds3103_pdata.lnb_en_pol = 0; 1588f3c6abcaSOlli Salonen memset(&board_info, 0, sizeof(board_info)); 1589c0decac1SMauro Carvalho Chehab strscpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); 1590f3c6abcaSOlli Salonen board_info.addr = 0x68; 1591f3c6abcaSOlli Salonen board_info.platform_data = &m88ds3103_pdata; 1592f3c6abcaSOlli Salonen request_module("m88ds3103"); 1593f3c6abcaSOlli Salonen client = i2c_new_device(&d->i2c_adap, &board_info); 1594f3c6abcaSOlli Salonen if (client == NULL || client->dev.driver == NULL) 159527254c36SOlli Salonen return -ENODEV; 1596f3c6abcaSOlli Salonen if (!try_module_get(client->dev.driver->owner)) { 1597f3c6abcaSOlli Salonen i2c_unregister_device(client); 1598f3c6abcaSOlli Salonen return -ENODEV; 1599f3c6abcaSOlli Salonen } 1600f3c6abcaSOlli Salonen adap->fe_adap[0].fe = m88ds3103_pdata.get_dvb_frontend(client); 1601f3c6abcaSOlli Salonen i2c_adapter = m88ds3103_pdata.get_i2c_adapter(client); 1602f3c6abcaSOlli Salonen 1603f3c6abcaSOlli Salonen state->i2c_client_demod = client; 160427254c36SOlli Salonen 160527254c36SOlli Salonen /* attach tuner */ 16060fecb6c0SAntti Palosaari ts2020_config.fe = adap->fe_adap[0].fe; 1607f3c6abcaSOlli Salonen memset(&board_info, 0, sizeof(board_info)); 1608c0decac1SMauro Carvalho Chehab strscpy(board_info.type, "ts2022", I2C_NAME_SIZE); 1609f3c6abcaSOlli Salonen board_info.addr = 0x60; 1610f3c6abcaSOlli Salonen board_info.platform_data = &ts2020_config; 16110fecb6c0SAntti Palosaari request_module("ts2020"); 1612f3c6abcaSOlli Salonen client = i2c_new_device(i2c_adapter, &board_info); 161327254c36SOlli Salonen 161427254c36SOlli Salonen if (client == NULL || client->dev.driver == NULL) { 161527254c36SOlli Salonen dvb_frontend_detach(adap->fe_adap[0].fe); 161627254c36SOlli Salonen return -ENODEV; 161727254c36SOlli Salonen } 161827254c36SOlli Salonen 161927254c36SOlli Salonen if (!try_module_get(client->dev.driver->owner)) { 162027254c36SOlli Salonen i2c_unregister_device(client); 162127254c36SOlli Salonen dvb_frontend_detach(adap->fe_adap[0].fe); 162227254c36SOlli Salonen return -ENODEV; 162327254c36SOlli Salonen } 162427254c36SOlli Salonen 162527254c36SOlli Salonen /* delegate signal strength measurement to tuner */ 162627254c36SOlli Salonen adap->fe_adap[0].fe->ops.read_signal_strength = 162727254c36SOlli Salonen adap->fe_adap[0].fe->ops.tuner_ops.get_rf_strength; 162827254c36SOlli Salonen 162927254c36SOlli Salonen state->i2c_client_tuner = client; 163027254c36SOlli Salonen 1631356484caSOlli Salonen /* hook fe: need to resync the slave fifo when signal locks */ 1632356484caSOlli Salonen state->fe_read_status = adap->fe_adap[0].fe->ops.read_status; 1633356484caSOlli Salonen adap->fe_adap[0].fe->ops.read_status = tt_s2_4600_read_status; 1634356484caSOlli Salonen 1635356484caSOlli Salonen state->last_lock = 0; 1636356484caSOlli Salonen 163727254c36SOlli Salonen return 0; 163827254c36SOlli Salonen } 163927254c36SOlli Salonen 1640786baecfSMauro Carvalho Chehab static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) 1641786baecfSMauro Carvalho Chehab { 1642786baecfSMauro Carvalho Chehab dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, 1643786baecfSMauro Carvalho Chehab &adap->dev->i2c_adap, DVB_PLL_OPERA1); 1644786baecfSMauro Carvalho Chehab return 0; 1645786baecfSMauro Carvalho Chehab } 1646786baecfSMauro Carvalho Chehab 1647786baecfSMauro Carvalho Chehab static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) 1648786baecfSMauro Carvalho Chehab { 1649786baecfSMauro Carvalho Chehab dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, 1650786baecfSMauro Carvalho Chehab &adap->dev->i2c_adap, DVB_PLL_TUA6034); 1651786baecfSMauro Carvalho Chehab 1652786baecfSMauro Carvalho Chehab return 0; 1653786baecfSMauro Carvalho Chehab } 1654786baecfSMauro Carvalho Chehab 1655a49de26aSEvgeny Plehov static int dw2102_rc_query(struct dvb_usb_device *d) 1656786baecfSMauro Carvalho Chehab { 1657786baecfSMauro Carvalho Chehab u8 key[2]; 1658786baecfSMauro Carvalho Chehab struct i2c_msg msg = { 1659786baecfSMauro Carvalho Chehab .addr = DW2102_RC_QUERY, 1660786baecfSMauro Carvalho Chehab .flags = I2C_M_RD, 1661786baecfSMauro Carvalho Chehab .buf = key, 1662786baecfSMauro Carvalho Chehab .len = 2 1663786baecfSMauro Carvalho Chehab }; 1664786baecfSMauro Carvalho Chehab 1665786baecfSMauro Carvalho Chehab if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { 1666a49de26aSEvgeny Plehov if (msg.buf[0] != 0xff) { 1667a49de26aSEvgeny Plehov deb_rc("%s: rc code: %x, %x\n", 1668786baecfSMauro Carvalho Chehab __func__, key[0], key[1]); 16696d741bfeSSean Young rc_keydown(d->rc_dev, RC_PROTO_UNKNOWN, key[0], 0); 1670a49de26aSEvgeny Plehov } 1671a49de26aSEvgeny Plehov } 1672786baecfSMauro Carvalho Chehab 1673a49de26aSEvgeny Plehov return 0; 1674a49de26aSEvgeny Plehov } 1675a49de26aSEvgeny Plehov 1676a49de26aSEvgeny Plehov static int prof_rc_query(struct dvb_usb_device *d) 1677a49de26aSEvgeny Plehov { 1678a49de26aSEvgeny Plehov u8 key[2]; 1679a49de26aSEvgeny Plehov struct i2c_msg msg = { 1680a49de26aSEvgeny Plehov .addr = DW2102_RC_QUERY, 1681a49de26aSEvgeny Plehov .flags = I2C_M_RD, 1682a49de26aSEvgeny Plehov .buf = key, 1683a49de26aSEvgeny Plehov .len = 2 1684a49de26aSEvgeny Plehov }; 1685a49de26aSEvgeny Plehov 1686a49de26aSEvgeny Plehov if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { 1687a49de26aSEvgeny Plehov if (msg.buf[0] != 0xff) { 1688a49de26aSEvgeny Plehov deb_rc("%s: rc code: %x, %x\n", 1689a49de26aSEvgeny Plehov __func__, key[0], key[1]); 16906d741bfeSSean Young rc_keydown(d->rc_dev, RC_PROTO_UNKNOWN, key[0] ^ 0xff, 16916d741bfeSSean Young 0); 1692a49de26aSEvgeny Plehov } 1693a49de26aSEvgeny Plehov } 1694a49de26aSEvgeny Plehov 1695a49de26aSEvgeny Plehov return 0; 1696a49de26aSEvgeny Plehov } 1697a49de26aSEvgeny Plehov 1698a49de26aSEvgeny Plehov static int su3000_rc_query(struct dvb_usb_device *d) 1699a49de26aSEvgeny Plehov { 1700a49de26aSEvgeny Plehov u8 key[2]; 1701a49de26aSEvgeny Plehov struct i2c_msg msg = { 1702a49de26aSEvgeny Plehov .addr = DW2102_RC_QUERY, 1703a49de26aSEvgeny Plehov .flags = I2C_M_RD, 1704a49de26aSEvgeny Plehov .buf = key, 1705a49de26aSEvgeny Plehov .len = 2 1706a49de26aSEvgeny Plehov }; 1707a49de26aSEvgeny Plehov 1708a49de26aSEvgeny Plehov if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { 1709a49de26aSEvgeny Plehov if (msg.buf[0] != 0xff) { 1710a49de26aSEvgeny Plehov deb_rc("%s: rc code: %x, %x\n", 1711a49de26aSEvgeny Plehov __func__, key[0], key[1]); 17126d741bfeSSean Young rc_keydown(d->rc_dev, RC_PROTO_RC5, 1713120703f9SDavid Härdeman RC_SCANCODE_RC5(key[1], key[0]), 0); 1714a49de26aSEvgeny Plehov } 1715786baecfSMauro Carvalho Chehab } 1716786baecfSMauro Carvalho Chehab 1717786baecfSMauro Carvalho Chehab return 0; 1718786baecfSMauro Carvalho Chehab } 1719786baecfSMauro Carvalho Chehab 1720786baecfSMauro Carvalho Chehab enum dw2102_table_entry { 1721786baecfSMauro Carvalho Chehab CYPRESS_DW2102, 1722786baecfSMauro Carvalho Chehab CYPRESS_DW2101, 1723786baecfSMauro Carvalho Chehab CYPRESS_DW2104, 1724786baecfSMauro Carvalho Chehab TEVII_S650, 1725786baecfSMauro Carvalho Chehab TERRATEC_CINERGY_S, 1726786baecfSMauro Carvalho Chehab CYPRESS_DW3101, 1727786baecfSMauro Carvalho Chehab TEVII_S630, 1728786baecfSMauro Carvalho Chehab PROF_1100, 1729786baecfSMauro Carvalho Chehab TEVII_S660, 1730786baecfSMauro Carvalho Chehab PROF_7500, 1731786baecfSMauro Carvalho Chehab GENIATECH_SU3000, 1732786baecfSMauro Carvalho Chehab TERRATEC_CINERGY_S2, 1733786baecfSMauro Carvalho Chehab TEVII_S480_1, 1734786baecfSMauro Carvalho Chehab TEVII_S480_2, 1735786baecfSMauro Carvalho Chehab X3M_SPC1400HD, 1736955d00acSIgor M. Liplianin TEVII_S421, 1737955d00acSIgor M. Liplianin TEVII_S632, 173844122dd6SIgor M. Liplianin TERRATEC_CINERGY_S2_R2, 173949438d97SOlli Salonen TERRATEC_CINERGY_S2_R3, 174069fd825cSEnrico Mioso TERRATEC_CINERGY_S2_R4, 1741f08e9f0dSAndrey Pavlenko GOTVIEW_SAT_HD, 174251d882edSEvgeny Plehov GENIATECH_T220, 174327254c36SOlli Salonen TECHNOTREND_S2_4600, 174444767fc4SOlli Salonen TEVII_S482_1, 174544767fc4SOlli Salonen TEVII_S482_2, 174693b66420SPhilipp Zabel TERRATEC_CINERGY_S2_BOX, 17476ede20f9SOlli Salonen TEVII_S662 1748786baecfSMauro Carvalho Chehab }; 1749786baecfSMauro Carvalho Chehab 1750786baecfSMauro Carvalho Chehab static struct usb_device_id dw2102_table[] = { 1751786baecfSMauro Carvalho Chehab [CYPRESS_DW2102] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, 1752786baecfSMauro Carvalho Chehab [CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, 1753786baecfSMauro Carvalho Chehab [CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)}, 1754786baecfSMauro Carvalho Chehab [TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)}, 1755e8364275SMauro Carvalho Chehab [TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S)}, 1756786baecfSMauro Carvalho Chehab [CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, 1757786baecfSMauro Carvalho Chehab [TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, 1758786baecfSMauro Carvalho Chehab [PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, 1759786baecfSMauro Carvalho Chehab [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, 1760786baecfSMauro Carvalho Chehab [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)}, 1761786baecfSMauro Carvalho Chehab [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)}, 1762a561d768SMauro Carvalho Chehab [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R1)}, 1763786baecfSMauro Carvalho Chehab [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)}, 1764786baecfSMauro Carvalho Chehab [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)}, 1765786baecfSMauro Carvalho Chehab [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)}, 1766955d00acSIgor M. Liplianin [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)}, 1767955d00acSIgor M. Liplianin [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, 1768a561d768SMauro Carvalho Chehab [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R2)}, 176949438d97SOlli Salonen [TERRATEC_CINERGY_S2_R3] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R3)}, 177069fd825cSEnrico Mioso [TERRATEC_CINERGY_S2_R4] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4)}, 1771f08e9f0dSAndrey Pavlenko [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, 177251d882edSEvgeny Plehov [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, 177327254c36SOlli Salonen [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND, 177427254c36SOlli Salonen USB_PID_TECHNOTREND_CONNECT_S2_4600)}, 177544767fc4SOlli Salonen [TEVII_S482_1] = {USB_DEVICE(0x9022, 0xd483)}, 177644767fc4SOlli Salonen [TEVII_S482_2] = {USB_DEVICE(0x9022, 0xd484)}, 177793b66420SPhilipp Zabel [TERRATEC_CINERGY_S2_BOX] = {USB_DEVICE(USB_VID_TERRATEC, 0x0105)}, 17786ede20f9SOlli Salonen [TEVII_S662] = {USB_DEVICE(0x9022, USB_PID_TEVII_S662)}, 1779786baecfSMauro Carvalho Chehab { } 1780786baecfSMauro Carvalho Chehab }; 1781786baecfSMauro Carvalho Chehab 1782786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, dw2102_table); 1783786baecfSMauro Carvalho Chehab 1784786baecfSMauro Carvalho Chehab static int dw2102_load_firmware(struct usb_device *dev, 1785786baecfSMauro Carvalho Chehab const struct firmware *frmwr) 1786786baecfSMauro Carvalho Chehab { 1787786baecfSMauro Carvalho Chehab u8 *b, *p; 1788786baecfSMauro Carvalho Chehab int ret = 0, i; 1789786baecfSMauro Carvalho Chehab u8 reset; 1790786baecfSMauro Carvalho Chehab u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; 1791786baecfSMauro Carvalho Chehab const struct firmware *fw; 1792786baecfSMauro Carvalho Chehab 17931ad5d064SHans Verkuil switch (le16_to_cpu(dev->descriptor.idProduct)) { 1794786baecfSMauro Carvalho Chehab case 0x2101: 17956823627bSRémi Cardona ret = request_firmware(&fw, DW2101_FIRMWARE, &dev->dev); 1796786baecfSMauro Carvalho Chehab if (ret != 0) { 17976823627bSRémi Cardona err(err_str, DW2101_FIRMWARE); 1798786baecfSMauro Carvalho Chehab return ret; 1799786baecfSMauro Carvalho Chehab } 1800786baecfSMauro Carvalho Chehab break; 1801786baecfSMauro Carvalho Chehab default: 1802786baecfSMauro Carvalho Chehab fw = frmwr; 1803786baecfSMauro Carvalho Chehab break; 1804786baecfSMauro Carvalho Chehab } 1805786baecfSMauro Carvalho Chehab info("start downloading DW210X firmware"); 1806786baecfSMauro Carvalho Chehab p = kmalloc(fw->size, GFP_KERNEL); 1807786baecfSMauro Carvalho Chehab reset = 1; 1808786baecfSMauro Carvalho Chehab /*stop the CPU*/ 1809786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG); 1810786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG); 1811786baecfSMauro Carvalho Chehab 1812786baecfSMauro Carvalho Chehab if (p != NULL) { 1813786baecfSMauro Carvalho Chehab memcpy(p, fw->data, fw->size); 1814786baecfSMauro Carvalho Chehab for (i = 0; i < fw->size; i += 0x40) { 1815786baecfSMauro Carvalho Chehab b = (u8 *) p + i; 1816786baecfSMauro Carvalho Chehab if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40, 1817786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG) != 0x40) { 1818786baecfSMauro Carvalho Chehab err("error while transferring firmware"); 1819786baecfSMauro Carvalho Chehab ret = -EINVAL; 1820786baecfSMauro Carvalho Chehab break; 1821786baecfSMauro Carvalho Chehab } 1822786baecfSMauro Carvalho Chehab } 1823786baecfSMauro Carvalho Chehab /* restart the CPU */ 1824786baecfSMauro Carvalho Chehab reset = 0; 1825786baecfSMauro Carvalho Chehab if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, 1826786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG) != 1) { 1827786baecfSMauro Carvalho Chehab err("could not restart the USB controller CPU."); 1828786baecfSMauro Carvalho Chehab ret = -EINVAL; 1829786baecfSMauro Carvalho Chehab } 1830786baecfSMauro Carvalho Chehab if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, 1831786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG) != 1) { 1832786baecfSMauro Carvalho Chehab err("could not restart the USB controller CPU."); 1833786baecfSMauro Carvalho Chehab ret = -EINVAL; 1834786baecfSMauro Carvalho Chehab } 1835786baecfSMauro Carvalho Chehab /* init registers */ 18361ad5d064SHans Verkuil switch (le16_to_cpu(dev->descriptor.idProduct)) { 1837786baecfSMauro Carvalho Chehab case USB_PID_TEVII_S650: 1838a49de26aSEvgeny Plehov dw2104_properties.rc.core.rc_codes = RC_MAP_TEVII_NEC; 183906eeefe8SMauro Carvalho Chehab /* fall through */ 1840786baecfSMauro Carvalho Chehab case USB_PID_DW2104: 1841786baecfSMauro Carvalho Chehab reset = 1; 1842786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, 1843786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG); 184406eeefe8SMauro Carvalho Chehab /* fall through */ 1845786baecfSMauro Carvalho Chehab case USB_PID_DW3101: 1846786baecfSMauro Carvalho Chehab reset = 0; 1847786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, 1848786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG); 1849786baecfSMauro Carvalho Chehab break; 1850e8364275SMauro Carvalho Chehab case USB_PID_TERRATEC_CINERGY_S: 1851786baecfSMauro Carvalho Chehab case USB_PID_DW2102: 1852786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, 1853786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG); 1854786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, 1855786baecfSMauro Carvalho Chehab DW210X_READ_MSG); 1856786baecfSMauro Carvalho Chehab /* check STV0299 frontend */ 1857786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2, 1858786baecfSMauro Carvalho Chehab DW210X_READ_MSG); 1859786baecfSMauro Carvalho Chehab if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) { 1860786baecfSMauro Carvalho Chehab dw2102_properties.i2c_algo = &dw2102_i2c_algo; 1861786baecfSMauro Carvalho Chehab dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach; 1862786baecfSMauro Carvalho Chehab break; 1863786baecfSMauro Carvalho Chehab } else { 1864786baecfSMauro Carvalho Chehab /* check STV0288 frontend */ 1865786baecfSMauro Carvalho Chehab reset16[0] = 0xd0; 1866786baecfSMauro Carvalho Chehab reset16[1] = 1; 1867786baecfSMauro Carvalho Chehab reset16[2] = 0; 1868786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3, 1869786baecfSMauro Carvalho Chehab DW210X_WRITE_MSG); 1870786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3, 1871786baecfSMauro Carvalho Chehab DW210X_READ_MSG); 1872786baecfSMauro Carvalho Chehab if (reset16[2] == 0x11) { 1873786baecfSMauro Carvalho Chehab dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo; 1874786baecfSMauro Carvalho Chehab break; 1875786baecfSMauro Carvalho Chehab } 1876786baecfSMauro Carvalho Chehab } 187706eeefe8SMauro Carvalho Chehab /* fall through */ 1878786baecfSMauro Carvalho Chehab case 0x2101: 1879786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, 1880786baecfSMauro Carvalho Chehab DW210X_READ_MSG); 1881786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, 1882786baecfSMauro Carvalho Chehab DW210X_READ_MSG); 1883786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, 1884786baecfSMauro Carvalho Chehab DW210X_READ_MSG); 1885786baecfSMauro Carvalho Chehab dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, 1886786baecfSMauro Carvalho Chehab DW210X_READ_MSG); 1887786baecfSMauro Carvalho Chehab break; 1888786baecfSMauro Carvalho Chehab } 1889786baecfSMauro Carvalho Chehab 1890786baecfSMauro Carvalho Chehab msleep(100); 1891786baecfSMauro Carvalho Chehab kfree(p); 1892786baecfSMauro Carvalho Chehab } 18932a518f8eSSudip Mukherjee 18942a518f8eSSudip Mukherjee if (le16_to_cpu(dev->descriptor.idProduct) == 0x2101) 18952a518f8eSSudip Mukherjee release_firmware(fw); 1896786baecfSMauro Carvalho Chehab return ret; 1897786baecfSMauro Carvalho Chehab } 1898786baecfSMauro Carvalho Chehab 1899786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties dw2102_properties = { 1900786baecfSMauro Carvalho Chehab .caps = DVB_USB_IS_AN_I2C_ADAPTER, 1901786baecfSMauro Carvalho Chehab .usb_ctrl = DEVICE_SPECIFIC, 19026823627bSRémi Cardona .firmware = DW2102_FIRMWARE, 1903786baecfSMauro Carvalho Chehab .no_reconnect = 1, 1904786baecfSMauro Carvalho Chehab 1905786baecfSMauro Carvalho Chehab .i2c_algo = &dw2102_serit_i2c_algo, 1906786baecfSMauro Carvalho Chehab 1907a49de26aSEvgeny Plehov .rc.core = { 1908786baecfSMauro Carvalho Chehab .rc_interval = 150, 1909a49de26aSEvgeny Plehov .rc_codes = RC_MAP_DM1105_NEC, 1910a49de26aSEvgeny Plehov .module_name = "dw2102", 19116d741bfeSSean Young .allowed_protos = RC_PROTO_BIT_NEC, 1912786baecfSMauro Carvalho Chehab .rc_query = dw2102_rc_query, 1913786baecfSMauro Carvalho Chehab }, 1914786baecfSMauro Carvalho Chehab 1915786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x81, 1916786baecfSMauro Carvalho Chehab /* parameter for the MPEG2-data transfer */ 1917786baecfSMauro Carvalho Chehab .num_adapters = 1, 1918786baecfSMauro Carvalho Chehab .download_firmware = dw2102_load_firmware, 1919786baecfSMauro Carvalho Chehab .read_mac_address = dw210x_read_mac_address, 1920786baecfSMauro Carvalho Chehab .adapter = { 1921786baecfSMauro Carvalho Chehab { 1922786baecfSMauro Carvalho Chehab .num_frontends = 1, 1923786baecfSMauro Carvalho Chehab .fe = {{ 1924786baecfSMauro Carvalho Chehab .frontend_attach = dw2102_frontend_attach, 1925786baecfSMauro Carvalho Chehab .stream = { 1926786baecfSMauro Carvalho Chehab .type = USB_BULK, 1927786baecfSMauro Carvalho Chehab .count = 8, 1928786baecfSMauro Carvalho Chehab .endpoint = 0x82, 1929786baecfSMauro Carvalho Chehab .u = { 1930786baecfSMauro Carvalho Chehab .bulk = { 1931786baecfSMauro Carvalho Chehab .buffersize = 4096, 1932786baecfSMauro Carvalho Chehab } 1933786baecfSMauro Carvalho Chehab } 1934786baecfSMauro Carvalho Chehab }, 1935786baecfSMauro Carvalho Chehab }}, 1936786baecfSMauro Carvalho Chehab } 1937786baecfSMauro Carvalho Chehab }, 1938786baecfSMauro Carvalho Chehab .num_device_descs = 3, 1939786baecfSMauro Carvalho Chehab .devices = { 1940786baecfSMauro Carvalho Chehab {"DVBWorld DVB-S 2102 USB2.0", 1941786baecfSMauro Carvalho Chehab {&dw2102_table[CYPRESS_DW2102], NULL}, 1942786baecfSMauro Carvalho Chehab {NULL}, 1943786baecfSMauro Carvalho Chehab }, 1944786baecfSMauro Carvalho Chehab {"DVBWorld DVB-S 2101 USB2.0", 1945786baecfSMauro Carvalho Chehab {&dw2102_table[CYPRESS_DW2101], NULL}, 1946786baecfSMauro Carvalho Chehab {NULL}, 1947786baecfSMauro Carvalho Chehab }, 1948786baecfSMauro Carvalho Chehab {"TerraTec Cinergy S USB", 1949786baecfSMauro Carvalho Chehab {&dw2102_table[TERRATEC_CINERGY_S], NULL}, 1950786baecfSMauro Carvalho Chehab {NULL}, 1951786baecfSMauro Carvalho Chehab }, 1952786baecfSMauro Carvalho Chehab } 1953786baecfSMauro Carvalho Chehab }; 1954786baecfSMauro Carvalho Chehab 1955786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties dw2104_properties = { 1956786baecfSMauro Carvalho Chehab .caps = DVB_USB_IS_AN_I2C_ADAPTER, 1957786baecfSMauro Carvalho Chehab .usb_ctrl = DEVICE_SPECIFIC, 19586823627bSRémi Cardona .firmware = DW2104_FIRMWARE, 1959786baecfSMauro Carvalho Chehab .no_reconnect = 1, 1960786baecfSMauro Carvalho Chehab 1961786baecfSMauro Carvalho Chehab .i2c_algo = &dw2104_i2c_algo, 1962a49de26aSEvgeny Plehov .rc.core = { 1963786baecfSMauro Carvalho Chehab .rc_interval = 150, 1964a49de26aSEvgeny Plehov .rc_codes = RC_MAP_DM1105_NEC, 1965a49de26aSEvgeny Plehov .module_name = "dw2102", 19666d741bfeSSean Young .allowed_protos = RC_PROTO_BIT_NEC, 1967786baecfSMauro Carvalho Chehab .rc_query = dw2102_rc_query, 1968786baecfSMauro Carvalho Chehab }, 1969786baecfSMauro Carvalho Chehab 1970786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x81, 1971786baecfSMauro Carvalho Chehab /* parameter for the MPEG2-data transfer */ 1972786baecfSMauro Carvalho Chehab .num_adapters = 1, 1973786baecfSMauro Carvalho Chehab .download_firmware = dw2102_load_firmware, 1974786baecfSMauro Carvalho Chehab .read_mac_address = dw210x_read_mac_address, 1975786baecfSMauro Carvalho Chehab .adapter = { 1976786baecfSMauro Carvalho Chehab { 1977786baecfSMauro Carvalho Chehab .num_frontends = 1, 1978786baecfSMauro Carvalho Chehab .fe = {{ 1979786baecfSMauro Carvalho Chehab .frontend_attach = dw2104_frontend_attach, 1980786baecfSMauro Carvalho Chehab .stream = { 1981786baecfSMauro Carvalho Chehab .type = USB_BULK, 1982786baecfSMauro Carvalho Chehab .count = 8, 1983786baecfSMauro Carvalho Chehab .endpoint = 0x82, 1984786baecfSMauro Carvalho Chehab .u = { 1985786baecfSMauro Carvalho Chehab .bulk = { 1986786baecfSMauro Carvalho Chehab .buffersize = 4096, 1987786baecfSMauro Carvalho Chehab } 1988786baecfSMauro Carvalho Chehab } 1989786baecfSMauro Carvalho Chehab }, 1990786baecfSMauro Carvalho Chehab }}, 1991786baecfSMauro Carvalho Chehab } 1992786baecfSMauro Carvalho Chehab }, 1993786baecfSMauro Carvalho Chehab .num_device_descs = 2, 1994786baecfSMauro Carvalho Chehab .devices = { 1995786baecfSMauro Carvalho Chehab { "DVBWorld DW2104 USB2.0", 1996786baecfSMauro Carvalho Chehab {&dw2102_table[CYPRESS_DW2104], NULL}, 1997786baecfSMauro Carvalho Chehab {NULL}, 1998786baecfSMauro Carvalho Chehab }, 1999786baecfSMauro Carvalho Chehab { "TeVii S650 USB2.0", 2000786baecfSMauro Carvalho Chehab {&dw2102_table[TEVII_S650], NULL}, 2001786baecfSMauro Carvalho Chehab {NULL}, 2002786baecfSMauro Carvalho Chehab }, 2003786baecfSMauro Carvalho Chehab } 2004786baecfSMauro Carvalho Chehab }; 2005786baecfSMauro Carvalho Chehab 2006786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties dw3101_properties = { 2007786baecfSMauro Carvalho Chehab .caps = DVB_USB_IS_AN_I2C_ADAPTER, 2008786baecfSMauro Carvalho Chehab .usb_ctrl = DEVICE_SPECIFIC, 20096823627bSRémi Cardona .firmware = DW3101_FIRMWARE, 2010786baecfSMauro Carvalho Chehab .no_reconnect = 1, 2011786baecfSMauro Carvalho Chehab 2012786baecfSMauro Carvalho Chehab .i2c_algo = &dw3101_i2c_algo, 2013a49de26aSEvgeny Plehov .rc.core = { 2014786baecfSMauro Carvalho Chehab .rc_interval = 150, 2015a49de26aSEvgeny Plehov .rc_codes = RC_MAP_DM1105_NEC, 2016a49de26aSEvgeny Plehov .module_name = "dw2102", 20176d741bfeSSean Young .allowed_protos = RC_PROTO_BIT_NEC, 2018786baecfSMauro Carvalho Chehab .rc_query = dw2102_rc_query, 2019786baecfSMauro Carvalho Chehab }, 2020786baecfSMauro Carvalho Chehab 2021786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x81, 2022786baecfSMauro Carvalho Chehab /* parameter for the MPEG2-data transfer */ 2023786baecfSMauro Carvalho Chehab .num_adapters = 1, 2024786baecfSMauro Carvalho Chehab .download_firmware = dw2102_load_firmware, 2025786baecfSMauro Carvalho Chehab .read_mac_address = dw210x_read_mac_address, 2026786baecfSMauro Carvalho Chehab .adapter = { 2027786baecfSMauro Carvalho Chehab { 2028786baecfSMauro Carvalho Chehab .num_frontends = 1, 2029786baecfSMauro Carvalho Chehab .fe = {{ 2030786baecfSMauro Carvalho Chehab .frontend_attach = dw3101_frontend_attach, 2031786baecfSMauro Carvalho Chehab .tuner_attach = dw3101_tuner_attach, 2032786baecfSMauro Carvalho Chehab .stream = { 2033786baecfSMauro Carvalho Chehab .type = USB_BULK, 2034786baecfSMauro Carvalho Chehab .count = 8, 2035786baecfSMauro Carvalho Chehab .endpoint = 0x82, 2036786baecfSMauro Carvalho Chehab .u = { 2037786baecfSMauro Carvalho Chehab .bulk = { 2038786baecfSMauro Carvalho Chehab .buffersize = 4096, 2039786baecfSMauro Carvalho Chehab } 2040786baecfSMauro Carvalho Chehab } 2041786baecfSMauro Carvalho Chehab }, 2042786baecfSMauro Carvalho Chehab }}, 2043786baecfSMauro Carvalho Chehab } 2044786baecfSMauro Carvalho Chehab }, 2045786baecfSMauro Carvalho Chehab .num_device_descs = 1, 2046786baecfSMauro Carvalho Chehab .devices = { 2047786baecfSMauro Carvalho Chehab { "DVBWorld DVB-C 3101 USB2.0", 2048786baecfSMauro Carvalho Chehab {&dw2102_table[CYPRESS_DW3101], NULL}, 2049786baecfSMauro Carvalho Chehab {NULL}, 2050786baecfSMauro Carvalho Chehab }, 2051786baecfSMauro Carvalho Chehab } 2052786baecfSMauro Carvalho Chehab }; 2053786baecfSMauro Carvalho Chehab 2054786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties s6x0_properties = { 2055786baecfSMauro Carvalho Chehab .caps = DVB_USB_IS_AN_I2C_ADAPTER, 2056786baecfSMauro Carvalho Chehab .usb_ctrl = DEVICE_SPECIFIC, 20572c4ffe27SOlli Salonen .size_of_priv = sizeof(struct dw2102_state), 20586823627bSRémi Cardona .firmware = S630_FIRMWARE, 2059786baecfSMauro Carvalho Chehab .no_reconnect = 1, 2060786baecfSMauro Carvalho Chehab 2061786baecfSMauro Carvalho Chehab .i2c_algo = &s6x0_i2c_algo, 2062a49de26aSEvgeny Plehov .rc.core = { 2063786baecfSMauro Carvalho Chehab .rc_interval = 150, 2064a49de26aSEvgeny Plehov .rc_codes = RC_MAP_TEVII_NEC, 2065a49de26aSEvgeny Plehov .module_name = "dw2102", 20666d741bfeSSean Young .allowed_protos = RC_PROTO_BIT_NEC, 2067786baecfSMauro Carvalho Chehab .rc_query = dw2102_rc_query, 2068786baecfSMauro Carvalho Chehab }, 2069786baecfSMauro Carvalho Chehab 2070786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x81, 2071786baecfSMauro Carvalho Chehab .num_adapters = 1, 2072786baecfSMauro Carvalho Chehab .download_firmware = dw2102_load_firmware, 2073786baecfSMauro Carvalho Chehab .read_mac_address = s6x0_read_mac_address, 2074786baecfSMauro Carvalho Chehab .adapter = { 2075786baecfSMauro Carvalho Chehab { 2076786baecfSMauro Carvalho Chehab .num_frontends = 1, 2077786baecfSMauro Carvalho Chehab .fe = {{ 2078786baecfSMauro Carvalho Chehab .frontend_attach = zl100313_frontend_attach, 2079786baecfSMauro Carvalho Chehab .stream = { 2080786baecfSMauro Carvalho Chehab .type = USB_BULK, 2081786baecfSMauro Carvalho Chehab .count = 8, 2082786baecfSMauro Carvalho Chehab .endpoint = 0x82, 2083786baecfSMauro Carvalho Chehab .u = { 2084786baecfSMauro Carvalho Chehab .bulk = { 2085786baecfSMauro Carvalho Chehab .buffersize = 4096, 2086786baecfSMauro Carvalho Chehab } 2087786baecfSMauro Carvalho Chehab } 2088786baecfSMauro Carvalho Chehab }, 2089786baecfSMauro Carvalho Chehab }}, 2090786baecfSMauro Carvalho Chehab } 2091786baecfSMauro Carvalho Chehab }, 2092786baecfSMauro Carvalho Chehab .num_device_descs = 1, 2093786baecfSMauro Carvalho Chehab .devices = { 2094786baecfSMauro Carvalho Chehab {"TeVii S630 USB", 2095786baecfSMauro Carvalho Chehab {&dw2102_table[TEVII_S630], NULL}, 2096786baecfSMauro Carvalho Chehab {NULL}, 2097786baecfSMauro Carvalho Chehab }, 2098786baecfSMauro Carvalho Chehab } 2099786baecfSMauro Carvalho Chehab }; 2100786baecfSMauro Carvalho Chehab 2101651ac129SBhumika Goyal static const struct dvb_usb_device_description d1100 = { 2102786baecfSMauro Carvalho Chehab "Prof 1100 USB ", 2103786baecfSMauro Carvalho Chehab {&dw2102_table[PROF_1100], NULL}, 2104786baecfSMauro Carvalho Chehab {NULL}, 2105786baecfSMauro Carvalho Chehab }; 2106786baecfSMauro Carvalho Chehab 2107651ac129SBhumika Goyal static const struct dvb_usb_device_description d660 = { 2108786baecfSMauro Carvalho Chehab "TeVii S660 USB", 2109786baecfSMauro Carvalho Chehab {&dw2102_table[TEVII_S660], NULL}, 2110786baecfSMauro Carvalho Chehab {NULL}, 2111786baecfSMauro Carvalho Chehab }; 2112786baecfSMauro Carvalho Chehab 2113651ac129SBhumika Goyal static const struct dvb_usb_device_description d480_1 = { 2114786baecfSMauro Carvalho Chehab "TeVii S480.1 USB", 2115786baecfSMauro Carvalho Chehab {&dw2102_table[TEVII_S480_1], NULL}, 2116786baecfSMauro Carvalho Chehab {NULL}, 2117786baecfSMauro Carvalho Chehab }; 2118786baecfSMauro Carvalho Chehab 2119651ac129SBhumika Goyal static const struct dvb_usb_device_description d480_2 = { 2120786baecfSMauro Carvalho Chehab "TeVii S480.2 USB", 2121786baecfSMauro Carvalho Chehab {&dw2102_table[TEVII_S480_2], NULL}, 2122786baecfSMauro Carvalho Chehab {NULL}, 2123786baecfSMauro Carvalho Chehab }; 2124786baecfSMauro Carvalho Chehab 2125651ac129SBhumika Goyal static const struct dvb_usb_device_description d7500 = { 2126786baecfSMauro Carvalho Chehab "Prof 7500 USB DVB-S2", 2127786baecfSMauro Carvalho Chehab {&dw2102_table[PROF_7500], NULL}, 2128786baecfSMauro Carvalho Chehab {NULL}, 2129786baecfSMauro Carvalho Chehab }; 2130786baecfSMauro Carvalho Chehab 2131651ac129SBhumika Goyal static const struct dvb_usb_device_description d421 = { 2132955d00acSIgor M. Liplianin "TeVii S421 PCI", 2133955d00acSIgor M. Liplianin {&dw2102_table[TEVII_S421], NULL}, 2134955d00acSIgor M. Liplianin {NULL}, 2135955d00acSIgor M. Liplianin }; 2136955d00acSIgor M. Liplianin 2137651ac129SBhumika Goyal static const struct dvb_usb_device_description d632 = { 2138955d00acSIgor M. Liplianin "TeVii S632 USB", 2139955d00acSIgor M. Liplianin {&dw2102_table[TEVII_S632], NULL}, 2140955d00acSIgor M. Liplianin {NULL}, 2141955d00acSIgor M. Liplianin }; 2142955d00acSIgor M. Liplianin 2143786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties su3000_properties = { 2144786baecfSMauro Carvalho Chehab .caps = DVB_USB_IS_AN_I2C_ADAPTER, 2145786baecfSMauro Carvalho Chehab .usb_ctrl = DEVICE_SPECIFIC, 21462c4ffe27SOlli Salonen .size_of_priv = sizeof(struct dw2102_state), 2147786baecfSMauro Carvalho Chehab .power_ctrl = su3000_power_ctrl, 2148786baecfSMauro Carvalho Chehab .num_adapters = 1, 2149786baecfSMauro Carvalho Chehab .identify_state = su3000_identify_state, 2150786baecfSMauro Carvalho Chehab .i2c_algo = &su3000_i2c_algo, 2151786baecfSMauro Carvalho Chehab 2152a49de26aSEvgeny Plehov .rc.core = { 2153786baecfSMauro Carvalho Chehab .rc_interval = 150, 2154a49de26aSEvgeny Plehov .rc_codes = RC_MAP_SU3000, 2155a49de26aSEvgeny Plehov .module_name = "dw2102", 21566d741bfeSSean Young .allowed_protos = RC_PROTO_BIT_RC5, 2157a49de26aSEvgeny Plehov .rc_query = su3000_rc_query, 2158786baecfSMauro Carvalho Chehab }, 2159786baecfSMauro Carvalho Chehab 2160786baecfSMauro Carvalho Chehab .read_mac_address = su3000_read_mac_address, 2161786baecfSMauro Carvalho Chehab 2162786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x01, 2163786baecfSMauro Carvalho Chehab 2164786baecfSMauro Carvalho Chehab .adapter = { 2165786baecfSMauro Carvalho Chehab { 2166786baecfSMauro Carvalho Chehab .num_frontends = 1, 2167786baecfSMauro Carvalho Chehab .fe = {{ 2168786baecfSMauro Carvalho Chehab .streaming_ctrl = su3000_streaming_ctrl, 2169786baecfSMauro Carvalho Chehab .frontend_attach = su3000_frontend_attach, 2170786baecfSMauro Carvalho Chehab .stream = { 2171786baecfSMauro Carvalho Chehab .type = USB_BULK, 2172786baecfSMauro Carvalho Chehab .count = 8, 2173786baecfSMauro Carvalho Chehab .endpoint = 0x82, 2174786baecfSMauro Carvalho Chehab .u = { 2175786baecfSMauro Carvalho Chehab .bulk = { 2176786baecfSMauro Carvalho Chehab .buffersize = 4096, 2177786baecfSMauro Carvalho Chehab } 2178786baecfSMauro Carvalho Chehab } 2179786baecfSMauro Carvalho Chehab } 2180786baecfSMauro Carvalho Chehab }}, 2181786baecfSMauro Carvalho Chehab } 2182786baecfSMauro Carvalho Chehab }, 218349438d97SOlli Salonen .num_device_descs = 6, 2184786baecfSMauro Carvalho Chehab .devices = { 2185786baecfSMauro Carvalho Chehab { "SU3000HD DVB-S USB2.0", 2186786baecfSMauro Carvalho Chehab { &dw2102_table[GENIATECH_SU3000], NULL }, 2187786baecfSMauro Carvalho Chehab { NULL }, 2188786baecfSMauro Carvalho Chehab }, 2189786baecfSMauro Carvalho Chehab { "Terratec Cinergy S2 USB HD", 2190786baecfSMauro Carvalho Chehab { &dw2102_table[TERRATEC_CINERGY_S2], NULL }, 2191786baecfSMauro Carvalho Chehab { NULL }, 2192786baecfSMauro Carvalho Chehab }, 2193786baecfSMauro Carvalho Chehab { "X3M TV SPC1400HD PCI", 2194786baecfSMauro Carvalho Chehab { &dw2102_table[X3M_SPC1400HD], NULL }, 2195786baecfSMauro Carvalho Chehab { NULL }, 2196786baecfSMauro Carvalho Chehab }, 219744122dd6SIgor M. Liplianin { "Terratec Cinergy S2 USB HD Rev.2", 219844122dd6SIgor M. Liplianin { &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL }, 219944122dd6SIgor M. Liplianin { NULL }, 220044122dd6SIgor M. Liplianin }, 220149438d97SOlli Salonen { "Terratec Cinergy S2 USB HD Rev.3", 220249438d97SOlli Salonen { &dw2102_table[TERRATEC_CINERGY_S2_R3], NULL }, 220349438d97SOlli Salonen { NULL }, 220449438d97SOlli Salonen }, 2205f08e9f0dSAndrey Pavlenko { "GOTVIEW Satellite HD", 2206f08e9f0dSAndrey Pavlenko { &dw2102_table[GOTVIEW_SAT_HD], NULL }, 2207f08e9f0dSAndrey Pavlenko { NULL }, 2208f08e9f0dSAndrey Pavlenko }, 2209786baecfSMauro Carvalho Chehab } 2210786baecfSMauro Carvalho Chehab }; 2211786baecfSMauro Carvalho Chehab 221251d882edSEvgeny Plehov static struct dvb_usb_device_properties t220_properties = { 221351d882edSEvgeny Plehov .caps = DVB_USB_IS_AN_I2C_ADAPTER, 221451d882edSEvgeny Plehov .usb_ctrl = DEVICE_SPECIFIC, 22152c4ffe27SOlli Salonen .size_of_priv = sizeof(struct dw2102_state), 221651d882edSEvgeny Plehov .power_ctrl = su3000_power_ctrl, 221751d882edSEvgeny Plehov .num_adapters = 1, 221851d882edSEvgeny Plehov .identify_state = su3000_identify_state, 221951d882edSEvgeny Plehov .i2c_algo = &su3000_i2c_algo, 222051d882edSEvgeny Plehov 2221a49de26aSEvgeny Plehov .rc.core = { 222251d882edSEvgeny Plehov .rc_interval = 150, 2223a49de26aSEvgeny Plehov .rc_codes = RC_MAP_SU3000, 2224a49de26aSEvgeny Plehov .module_name = "dw2102", 22256d741bfeSSean Young .allowed_protos = RC_PROTO_BIT_RC5, 2226a49de26aSEvgeny Plehov .rc_query = su3000_rc_query, 222751d882edSEvgeny Plehov }, 222851d882edSEvgeny Plehov 222951d882edSEvgeny Plehov .read_mac_address = su3000_read_mac_address, 223051d882edSEvgeny Plehov 223151d882edSEvgeny Plehov .generic_bulk_ctrl_endpoint = 0x01, 223251d882edSEvgeny Plehov 223351d882edSEvgeny Plehov .adapter = { 223451d882edSEvgeny Plehov { 223551d882edSEvgeny Plehov .num_frontends = 1, 223651d882edSEvgeny Plehov .fe = { { 223751d882edSEvgeny Plehov .streaming_ctrl = su3000_streaming_ctrl, 223851d882edSEvgeny Plehov .frontend_attach = t220_frontend_attach, 223951d882edSEvgeny Plehov .stream = { 224051d882edSEvgeny Plehov .type = USB_BULK, 224151d882edSEvgeny Plehov .count = 8, 224251d882edSEvgeny Plehov .endpoint = 0x82, 224351d882edSEvgeny Plehov .u = { 224451d882edSEvgeny Plehov .bulk = { 224551d882edSEvgeny Plehov .buffersize = 4096, 224651d882edSEvgeny Plehov } 224751d882edSEvgeny Plehov } 224851d882edSEvgeny Plehov } 224951d882edSEvgeny Plehov } }, 225051d882edSEvgeny Plehov } 225151d882edSEvgeny Plehov }, 225251d882edSEvgeny Plehov .num_device_descs = 1, 225351d882edSEvgeny Plehov .devices = { 225451d882edSEvgeny Plehov { "Geniatech T220 DVB-T/T2 USB2.0", 225551d882edSEvgeny Plehov { &dw2102_table[GENIATECH_T220], NULL }, 225651d882edSEvgeny Plehov { NULL }, 225751d882edSEvgeny Plehov }, 225851d882edSEvgeny Plehov } 225951d882edSEvgeny Plehov }; 226051d882edSEvgeny Plehov 226127254c36SOlli Salonen static struct dvb_usb_device_properties tt_s2_4600_properties = { 226227254c36SOlli Salonen .caps = DVB_USB_IS_AN_I2C_ADAPTER, 226327254c36SOlli Salonen .usb_ctrl = DEVICE_SPECIFIC, 226427254c36SOlli Salonen .size_of_priv = sizeof(struct dw2102_state), 226527254c36SOlli Salonen .power_ctrl = su3000_power_ctrl, 226627254c36SOlli Salonen .num_adapters = 1, 226727254c36SOlli Salonen .identify_state = su3000_identify_state, 226827254c36SOlli Salonen .i2c_algo = &su3000_i2c_algo, 226927254c36SOlli Salonen 227027254c36SOlli Salonen .rc.core = { 227127254c36SOlli Salonen .rc_interval = 250, 227227254c36SOlli Salonen .rc_codes = RC_MAP_TT_1500, 227327254c36SOlli Salonen .module_name = "dw2102", 22746d741bfeSSean Young .allowed_protos = RC_PROTO_BIT_RC5, 227527254c36SOlli Salonen .rc_query = su3000_rc_query, 227627254c36SOlli Salonen }, 227727254c36SOlli Salonen 227827254c36SOlli Salonen .read_mac_address = su3000_read_mac_address, 227927254c36SOlli Salonen 228027254c36SOlli Salonen .generic_bulk_ctrl_endpoint = 0x01, 228127254c36SOlli Salonen 228227254c36SOlli Salonen .adapter = { 228327254c36SOlli Salonen { 228427254c36SOlli Salonen .num_frontends = 1, 228527254c36SOlli Salonen .fe = {{ 228627254c36SOlli Salonen .streaming_ctrl = su3000_streaming_ctrl, 228727254c36SOlli Salonen .frontend_attach = tt_s2_4600_frontend_attach, 228827254c36SOlli Salonen .stream = { 228927254c36SOlli Salonen .type = USB_BULK, 229027254c36SOlli Salonen .count = 8, 229127254c36SOlli Salonen .endpoint = 0x82, 229227254c36SOlli Salonen .u = { 229327254c36SOlli Salonen .bulk = { 229427254c36SOlli Salonen .buffersize = 4096, 229527254c36SOlli Salonen } 229627254c36SOlli Salonen } 229727254c36SOlli Salonen } 229827254c36SOlli Salonen } }, 229927254c36SOlli Salonen } 230027254c36SOlli Salonen }, 23016ede20f9SOlli Salonen .num_device_descs = 5, 230227254c36SOlli Salonen .devices = { 230327254c36SOlli Salonen { "TechnoTrend TT-connect S2-4600", 230427254c36SOlli Salonen { &dw2102_table[TECHNOTREND_S2_4600], NULL }, 230527254c36SOlli Salonen { NULL }, 230627254c36SOlli Salonen }, 230744767fc4SOlli Salonen { "TeVii S482 (tuner 1)", 230844767fc4SOlli Salonen { &dw2102_table[TEVII_S482_1], NULL }, 230944767fc4SOlli Salonen { NULL }, 231044767fc4SOlli Salonen }, 231144767fc4SOlli Salonen { "TeVii S482 (tuner 2)", 231244767fc4SOlli Salonen { &dw2102_table[TEVII_S482_2], NULL }, 231344767fc4SOlli Salonen { NULL }, 231444767fc4SOlli Salonen }, 231593b66420SPhilipp Zabel { "Terratec Cinergy S2 USB BOX", 231693b66420SPhilipp Zabel { &dw2102_table[TERRATEC_CINERGY_S2_BOX], NULL }, 231793b66420SPhilipp Zabel { NULL }, 231893b66420SPhilipp Zabel }, 23196ede20f9SOlli Salonen { "TeVii S662", 23206ede20f9SOlli Salonen { &dw2102_table[TEVII_S662], NULL }, 23216ede20f9SOlli Salonen { NULL }, 23226ede20f9SOlli Salonen }, 232327254c36SOlli Salonen } 232427254c36SOlli Salonen }; 232527254c36SOlli Salonen 2326786baecfSMauro Carvalho Chehab static int dw2102_probe(struct usb_interface *intf, 2327786baecfSMauro Carvalho Chehab const struct usb_device_id *id) 2328786baecfSMauro Carvalho Chehab { 2329be90cc8eSAnton Vasilyev int retval = -ENOMEM; 2330299c7007SAnton Vasilyev struct dvb_usb_device_properties *p1100; 2331299c7007SAnton Vasilyev struct dvb_usb_device_properties *s660; 2332299c7007SAnton Vasilyev struct dvb_usb_device_properties *p7500; 2333299c7007SAnton Vasilyev struct dvb_usb_device_properties *s421; 2334299c7007SAnton Vasilyev 2335786baecfSMauro Carvalho Chehab p1100 = kmemdup(&s6x0_properties, 2336786baecfSMauro Carvalho Chehab sizeof(struct dvb_usb_device_properties), GFP_KERNEL); 2337786baecfSMauro Carvalho Chehab if (!p1100) 2338be90cc8eSAnton Vasilyev goto err0; 2339be90cc8eSAnton Vasilyev 2340786baecfSMauro Carvalho Chehab /* copy default structure */ 2341786baecfSMauro Carvalho Chehab /* fill only different fields */ 23426823627bSRémi Cardona p1100->firmware = P1100_FIRMWARE; 2343786baecfSMauro Carvalho Chehab p1100->devices[0] = d1100; 2344a49de26aSEvgeny Plehov p1100->rc.core.rc_query = prof_rc_query; 2345a49de26aSEvgeny Plehov p1100->rc.core.rc_codes = RC_MAP_TBS_NEC; 2346786baecfSMauro Carvalho Chehab p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach; 2347786baecfSMauro Carvalho Chehab 2348786baecfSMauro Carvalho Chehab s660 = kmemdup(&s6x0_properties, 2349786baecfSMauro Carvalho Chehab sizeof(struct dvb_usb_device_properties), GFP_KERNEL); 2350be90cc8eSAnton Vasilyev if (!s660) 2351be90cc8eSAnton Vasilyev goto err1; 2352be90cc8eSAnton Vasilyev 23536823627bSRémi Cardona s660->firmware = S660_FIRMWARE; 2354786baecfSMauro Carvalho Chehab s660->num_device_descs = 3; 2355786baecfSMauro Carvalho Chehab s660->devices[0] = d660; 2356786baecfSMauro Carvalho Chehab s660->devices[1] = d480_1; 2357786baecfSMauro Carvalho Chehab s660->devices[2] = d480_2; 2358786baecfSMauro Carvalho Chehab s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach; 2359786baecfSMauro Carvalho Chehab 2360786baecfSMauro Carvalho Chehab p7500 = kmemdup(&s6x0_properties, 2361786baecfSMauro Carvalho Chehab sizeof(struct dvb_usb_device_properties), GFP_KERNEL); 2362be90cc8eSAnton Vasilyev if (!p7500) 2363be90cc8eSAnton Vasilyev goto err2; 2364be90cc8eSAnton Vasilyev 23656823627bSRémi Cardona p7500->firmware = P7500_FIRMWARE; 2366786baecfSMauro Carvalho Chehab p7500->devices[0] = d7500; 2367a49de26aSEvgeny Plehov p7500->rc.core.rc_query = prof_rc_query; 2368a49de26aSEvgeny Plehov p7500->rc.core.rc_codes = RC_MAP_TBS_NEC; 2369786baecfSMauro Carvalho Chehab p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach; 2370786baecfSMauro Carvalho Chehab 2371955d00acSIgor M. Liplianin 2372955d00acSIgor M. Liplianin s421 = kmemdup(&su3000_properties, 2373955d00acSIgor M. Liplianin sizeof(struct dvb_usb_device_properties), GFP_KERNEL); 2374be90cc8eSAnton Vasilyev if (!s421) 2375be90cc8eSAnton Vasilyev goto err3; 2376be90cc8eSAnton Vasilyev 2377955d00acSIgor M. Liplianin s421->num_device_descs = 2; 2378955d00acSIgor M. Liplianin s421->devices[0] = d421; 2379955d00acSIgor M. Liplianin s421->devices[1] = d632; 2380955d00acSIgor M. Liplianin s421->adapter->fe[0].frontend_attach = m88rs2000_frontend_attach; 2381955d00acSIgor M. Liplianin 2382786baecfSMauro Carvalho Chehab if (0 == dvb_usb_device_init(intf, &dw2102_properties, 2383786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr) || 2384786baecfSMauro Carvalho Chehab 0 == dvb_usb_device_init(intf, &dw2104_properties, 2385786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr) || 2386786baecfSMauro Carvalho Chehab 0 == dvb_usb_device_init(intf, &dw3101_properties, 2387786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr) || 2388786baecfSMauro Carvalho Chehab 0 == dvb_usb_device_init(intf, &s6x0_properties, 2389786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr) || 2390786baecfSMauro Carvalho Chehab 0 == dvb_usb_device_init(intf, p1100, 2391786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr) || 2392786baecfSMauro Carvalho Chehab 0 == dvb_usb_device_init(intf, s660, 2393786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr) || 2394786baecfSMauro Carvalho Chehab 0 == dvb_usb_device_init(intf, p7500, 2395786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr) || 2396955d00acSIgor M. Liplianin 0 == dvb_usb_device_init(intf, s421, 2397955d00acSIgor M. Liplianin THIS_MODULE, NULL, adapter_nr) || 2398786baecfSMauro Carvalho Chehab 0 == dvb_usb_device_init(intf, &su3000_properties, 239951d882edSEvgeny Plehov THIS_MODULE, NULL, adapter_nr) || 240051d882edSEvgeny Plehov 0 == dvb_usb_device_init(intf, &t220_properties, 240127254c36SOlli Salonen THIS_MODULE, NULL, adapter_nr) || 240227254c36SOlli Salonen 0 == dvb_usb_device_init(intf, &tt_s2_4600_properties, 2403299c7007SAnton Vasilyev THIS_MODULE, NULL, adapter_nr)) { 2404299c7007SAnton Vasilyev 2405299c7007SAnton Vasilyev /* clean up copied properties */ 2406299c7007SAnton Vasilyev kfree(s421); 2407299c7007SAnton Vasilyev kfree(p7500); 2408299c7007SAnton Vasilyev kfree(s660); 2409299c7007SAnton Vasilyev kfree(p1100); 2410299c7007SAnton Vasilyev 2411786baecfSMauro Carvalho Chehab return 0; 2412299c7007SAnton Vasilyev } 2413786baecfSMauro Carvalho Chehab 2414be90cc8eSAnton Vasilyev retval = -ENODEV; 2415be90cc8eSAnton Vasilyev kfree(s421); 2416be90cc8eSAnton Vasilyev err3: 2417be90cc8eSAnton Vasilyev kfree(p7500); 2418be90cc8eSAnton Vasilyev err2: 2419be90cc8eSAnton Vasilyev kfree(s660); 2420be90cc8eSAnton Vasilyev err1: 2421be90cc8eSAnton Vasilyev kfree(p1100); 2422be90cc8eSAnton Vasilyev err0: 2423be90cc8eSAnton Vasilyev return retval; 2424786baecfSMauro Carvalho Chehab } 2425786baecfSMauro Carvalho Chehab 242670769b24SOlli Salonen static void dw2102_disconnect(struct usb_interface *intf) 242770769b24SOlli Salonen { 242870769b24SOlli Salonen struct dvb_usb_device *d = usb_get_intfdata(intf); 242970769b24SOlli Salonen struct dw2102_state *st = (struct dw2102_state *)d->priv; 243070769b24SOlli Salonen struct i2c_client *client; 243170769b24SOlli Salonen 243270769b24SOlli Salonen /* remove I2C client for tuner */ 243370769b24SOlli Salonen client = st->i2c_client_tuner; 243470769b24SOlli Salonen if (client) { 243570769b24SOlli Salonen module_put(client->dev.driver->owner); 243670769b24SOlli Salonen i2c_unregister_device(client); 243770769b24SOlli Salonen } 243870769b24SOlli Salonen 2439f3c6abcaSOlli Salonen /* remove I2C client for demodulator */ 2440f3c6abcaSOlli Salonen client = st->i2c_client_demod; 2441f3c6abcaSOlli Salonen if (client) { 2442f3c6abcaSOlli Salonen module_put(client->dev.driver->owner); 2443f3c6abcaSOlli Salonen i2c_unregister_device(client); 2444f3c6abcaSOlli Salonen } 2445f3c6abcaSOlli Salonen 244670769b24SOlli Salonen dvb_usb_device_exit(intf); 244770769b24SOlli Salonen } 244870769b24SOlli Salonen 2449786baecfSMauro Carvalho Chehab static struct usb_driver dw2102_driver = { 2450786baecfSMauro Carvalho Chehab .name = "dw2102", 2451786baecfSMauro Carvalho Chehab .probe = dw2102_probe, 245270769b24SOlli Salonen .disconnect = dw2102_disconnect, 2453786baecfSMauro Carvalho Chehab .id_table = dw2102_table, 2454786baecfSMauro Carvalho Chehab }; 2455786baecfSMauro Carvalho Chehab 2456786baecfSMauro Carvalho Chehab module_usb_driver(dw2102_driver); 2457786baecfSMauro Carvalho Chehab 2458786baecfSMauro Carvalho Chehab MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); 2459f319ed91SMauro Carvalho Chehab MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101 USB2.0, TeVii S421, S480, S482, S600, S630, S632, S650, TeVii S660, S662, Prof 1100, 7500 USB2.0, Geniatech SU3000, T220, TechnoTrend S2-4600, Terratec Cinergy S2 devices"); 2460786baecfSMauro Carvalho Chehab MODULE_VERSION("0.1"); 2461786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 24626823627bSRémi Cardona MODULE_FIRMWARE(DW2101_FIRMWARE); 24636823627bSRémi Cardona MODULE_FIRMWARE(DW2102_FIRMWARE); 24646823627bSRémi Cardona MODULE_FIRMWARE(DW2104_FIRMWARE); 24656823627bSRémi Cardona MODULE_FIRMWARE(DW3101_FIRMWARE); 24666823627bSRémi Cardona MODULE_FIRMWARE(S630_FIRMWARE); 24676823627bSRémi Cardona MODULE_FIRMWARE(S660_FIRMWARE); 24686823627bSRémi Cardona MODULE_FIRMWARE(P1100_FIRMWARE); 24696823627bSRémi Cardona MODULE_FIRMWARE(P7500_FIRMWARE); 2470