blob: f7dd973e2c40ac9d663642ca786f4f7fabca06b3 [file] [log] [blame]
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001/* DVB USB framework compliant Linux driver for the
Igor M. Liplianin2f30fb42011-02-25 18:41:23 -03002 * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03003 * TeVii S600, S630, S650, S660, S480, S421, S632
Igor M. Liplianin2f30fb42011-02-25 18:41:23 -03004 * Prof 1100, 7500,
Evgeny Plehov51d882e2013-11-13 20:53:59 -03005 * Geniatech SU3000, T220 Cards
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03006 * Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by)
Igor M. Liplianin2f30fb42011-02-25 18:41:23 -03007 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, version 2.
11 *
12 * see Documentation/dvb/README.dvb-usb for more information
13 */
Igor M Liplianin7fd48282008-07-20 08:05:50 -030014#include "dw2102.h"
Igor M. Liplianin21b007b2008-09-17 19:19:19 -030015#include "si21xx.h"
Igor M Liplianin7fd48282008-07-20 08:05:50 -030016#include "stv0299.h"
17#include "z0194a.h"
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -030018#include "stv0288.h"
19#include "stb6000.h"
20#include "eds1547.h"
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -030021#include "cx24116.h"
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -030022#include "tda1002x.h"
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -030023#include "mt312.h"
24#include "zl10039.h"
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -030025#include "ts2020.h"
Igor M. Liplianin141cc352009-11-27 14:37:35 -030026#include "ds3000.h"
27#include "stv0900.h"
28#include "stv6110.h"
29#include "stb6100.h"
30#include "stb6100_proc.h"
Igor M. Liplianin955d00a2012-05-08 03:53:17 -030031#include "m88rs2000.h"
Evgeny Plehov51d882e2013-11-13 20:53:59 -030032#include "tda18271.h"
33#include "cxd2820r.h"
Igor M Liplianin7fd48282008-07-20 08:05:50 -030034
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -030035/* Max transfer size done by I2C transfer functions */
36#define MAX_XFER_SIZE 64
37
Igor M Liplianin7fd48282008-07-20 08:05:50 -030038#ifndef USB_PID_DW2102
39#define USB_PID_DW2102 0x2102
40#endif
41
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -030042#ifndef USB_PID_DW2104
43#define USB_PID_DW2104 0x2104
44#endif
45
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -030046#ifndef USB_PID_DW3101
47#define USB_PID_DW3101 0x3101
48#endif
49
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -030050#ifndef USB_PID_CINERGY_S
51#define USB_PID_CINERGY_S 0x0064
52#endif
53
Igor M. Liplianin141cc352009-11-27 14:37:35 -030054#ifndef USB_PID_TEVII_S630
55#define USB_PID_TEVII_S630 0xd630
56#endif
57
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -030058#ifndef USB_PID_TEVII_S650
59#define USB_PID_TEVII_S650 0xd650
60#endif
61
Igor M. Liplianin141cc352009-11-27 14:37:35 -030062#ifndef USB_PID_TEVII_S660
63#define USB_PID_TEVII_S660 0xd660
64#endif
65
Igor M. Liplianine8f50552011-02-25 18:41:23 -030066#ifndef USB_PID_TEVII_S480_1
67#define USB_PID_TEVII_S480_1 0xd481
68#endif
69
70#ifndef USB_PID_TEVII_S480_2
71#define USB_PID_TEVII_S480_2 0xd482
72#endif
73
Igor M. Liplianin141cc352009-11-27 14:37:35 -030074#ifndef USB_PID_PROF_1100
75#define USB_PID_PROF_1100 0xb012
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -030076#endif
77
Igor M. Liplianin955d00a2012-05-08 03:53:17 -030078#ifndef USB_PID_TEVII_S421
79#define USB_PID_TEVII_S421 0xd421
80#endif
81
82#ifndef USB_PID_TEVII_S632
83#define USB_PID_TEVII_S632 0xd632
84#endif
85
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -030086#ifndef USB_PID_GOTVIEW_SAT_HD
87#define USB_PID_GOTVIEW_SAT_HD 0x5456
88#endif
89
Igor M. Liplianin21b007b2008-09-17 19:19:19 -030090#define DW210X_READ_MSG 0
91#define DW210X_WRITE_MSG 1
Igor M Liplianin7fd48282008-07-20 08:05:50 -030092
93#define REG_1F_SYMBOLRATE_BYTE0 0x1f
94#define REG_20_SYMBOLRATE_BYTE1 0x20
95#define REG_21_SYMBOLRATE_BYTE2 0x21
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -030096/* on my own*/
Igor M Liplianin7fd48282008-07-20 08:05:50 -030097#define DW2102_VOLTAGE_CTRL (0x1800)
Igor M. Liplianind2ffc442011-02-25 18:41:22 -030098#define SU3000_STREAM_CTRL (0x1900)
Igor M Liplianin7fd48282008-07-20 08:05:50 -030099#define DW2102_RC_QUERY (0x1a00)
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300100#define DW2102_LED_CTRL (0x1b00)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300101
Rémi Cardona68236272012-09-28 08:59:32 -0300102#define DW2101_FIRMWARE "dvb-usb-dw2101.fw"
103#define DW2102_FIRMWARE "dvb-usb-dw2102.fw"
104#define DW2104_FIRMWARE "dvb-usb-dw2104.fw"
105#define DW3101_FIRMWARE "dvb-usb-dw3101.fw"
106#define S630_FIRMWARE "dvb-usb-s630.fw"
107#define S660_FIRMWARE "dvb-usb-s660.fw"
108#define P1100_FIRMWARE "dvb-usb-p1100.fw"
109#define P7500_FIRMWARE "dvb-usb-p7500.fw"
110
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300111#define err_str "did not find the firmware file. (%s) " \
112 "Please see linux/Documentation/dvb/ for more details " \
113 "on firmware-problems."
114
Olli Salonen2c4ffe22015-03-16 14:14:04 -0300115struct dw2102_state {
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300116 u8 initialized;
Olli Salonen70769b22015-03-16 14:14:05 -0300117 struct i2c_client *i2c_client_tuner;
Igor M. Liplianin52c506e2011-02-25 18:41:23 -0300118 int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v);
119};
120
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300121/* debug */
122static int dvb_usb_dw2102_debug;
123module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -0300124MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
125 DVB_USB_DEBUG_STATUS);
126
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300127/* demod probe */
128static int demod_probe = 1;
129module_param_named(demod, demod_probe, int, 0644);
130MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 "
131 "4=stv0903+stb6100(or-able)).");
132
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300133DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
134
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300135static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300136 u16 index, u8 * data, u16 len, int flags)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300137{
138 int ret;
Florian Micklerb47b8502011-03-21 15:33:44 -0300139 u8 *u8buf;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300140 unsigned int pipe = (flags == DW210X_READ_MSG) ?
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300141 usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300142 u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300143
Florian Micklerb47b8502011-03-21 15:33:44 -0300144 u8buf = kmalloc(len, GFP_KERNEL);
145 if (!u8buf)
146 return -ENOMEM;
147
148
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300149 if (flags == DW210X_WRITE_MSG)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300150 memcpy(u8buf, data, len);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300151 ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
152 value, index , u8buf, len, 2000);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300153
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300154 if (flags == DW210X_READ_MSG)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300155 memcpy(data, u8buf, len);
Florian Micklerb47b8502011-03-21 15:33:44 -0300156
157 kfree(u8buf);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300158 return ret;
159}
160
161/* I2C */
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300162static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
163 int num)
164{
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300165 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300166 int i = 0;
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300167 u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300168 u16 value;
169
170 if (!d)
171 return -ENODEV;
172 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
173 return -EAGAIN;
174
175 switch (num) {
176 case 2:
177 /* read stv0299 register */
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300178 value = msg[0].buf[0];/* register */
179 for (i = 0; i < msg[1].len; i++) {
Hans Verkuild51dbec2012-04-20 03:30:11 -0300180 dw210x_op_rw(d->udev, 0xb5, value + i, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300181 buf6, 2, DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300182 msg[1].buf[i] = buf6[0];
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300183 }
184 break;
185 case 1:
186 switch (msg[0].addr) {
187 case 0x68:
188 /* write to stv0299 register */
189 buf6[0] = 0x2a;
190 buf6[1] = msg[0].buf[0];
191 buf6[2] = msg[0].buf[1];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300192 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300193 buf6, 3, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300194 break;
195 case 0x60:
196 if (msg[0].flags == 0) {
197 /* write to tuner pll */
198 buf6[0] = 0x2c;
199 buf6[1] = 5;
200 buf6[2] = 0xc0;
201 buf6[3] = msg[0].buf[0];
202 buf6[4] = msg[0].buf[1];
203 buf6[5] = msg[0].buf[2];
204 buf6[6] = msg[0].buf[3];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300205 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300206 buf6, 7, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300207 } else {
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300208 /* read from tuner */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300209 dw210x_op_rw(d->udev, 0xb5, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300210 buf6, 1, DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300211 msg[0].buf[0] = buf6[0];
212 }
213 break;
214 case (DW2102_RC_QUERY):
Hans Verkuild51dbec2012-04-20 03:30:11 -0300215 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300216 buf6, 2, DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300217 msg[0].buf[0] = buf6[0];
218 msg[0].buf[1] = buf6[1];
219 break;
220 case (DW2102_VOLTAGE_CTRL):
221 buf6[0] = 0x30;
222 buf6[1] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300223 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300224 buf6, 2, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300225 break;
226 }
227
228 break;
229 }
230
231 mutex_unlock(&d->i2c_mutex);
232 return num;
233}
234
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300235static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
236 struct i2c_msg msg[], int num)
237{
238 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300239 u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};
240
241 if (!d)
242 return -ENODEV;
243 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
244 return -EAGAIN;
245
246 switch (num) {
247 case 2:
248 /* read si2109 register by number */
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300249 buf6[0] = msg[0].addr << 1;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300250 buf6[1] = msg[0].len;
251 buf6[2] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300252 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300253 buf6, msg[0].len + 2, DW210X_WRITE_MSG);
254 /* read si2109 register */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300255 dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300256 buf6, msg[1].len + 2, DW210X_READ_MSG);
257 memcpy(msg[1].buf, buf6 + 2, msg[1].len);
258
259 break;
260 case 1:
261 switch (msg[0].addr) {
262 case 0x68:
263 /* write to si2109 register */
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300264 buf6[0] = msg[0].addr << 1;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300265 buf6[1] = msg[0].len;
266 memcpy(buf6 + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300267 dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300268 msg[0].len + 2, DW210X_WRITE_MSG);
269 break;
270 case(DW2102_RC_QUERY):
Hans Verkuild51dbec2012-04-20 03:30:11 -0300271 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300272 buf6, 2, DW210X_READ_MSG);
273 msg[0].buf[0] = buf6[0];
274 msg[0].buf[1] = buf6[1];
275 break;
276 case(DW2102_VOLTAGE_CTRL):
277 buf6[0] = 0x30;
278 buf6[1] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300279 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300280 buf6, 2, DW210X_WRITE_MSG);
281 break;
282 }
283 break;
284 }
285
286 mutex_unlock(&d->i2c_mutex);
287 return num;
288}
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300289
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300290static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
291{
292 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Dan Carpenter324ed532013-11-22 04:56:33 -0300293 int ret;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300294
295 if (!d)
296 return -ENODEV;
297 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
298 return -EAGAIN;
299
300 switch (num) {
301 case 2: {
302 /* read */
303 /* first write first register number */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300304 u8 ibuf[MAX_XFER_SIZE], obuf[3];
305
306 if (2 + msg[1].len > sizeof(ibuf)) {
307 warn("i2c rd: len=%d is too big!\n",
308 msg[1].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300309 ret = -EOPNOTSUPP;
310 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300311 }
312
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300313 obuf[0] = msg[0].addr << 1;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300314 obuf[1] = msg[0].len;
315 obuf[2] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300316 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300317 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
318 /* second read registers */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300319 dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300320 ibuf, msg[1].len + 2, DW210X_READ_MSG);
321 memcpy(msg[1].buf, ibuf + 2, msg[1].len);
322
323 break;
324 }
325 case 1:
326 switch (msg[0].addr) {
327 case 0x68: {
328 /* write to register */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300329 u8 obuf[MAX_XFER_SIZE];
330
331 if (2 + msg[0].len > sizeof(obuf)) {
332 warn("i2c wr: len=%d is too big!\n",
333 msg[1].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300334 ret = -EOPNOTSUPP;
335 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300336 }
337
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300338 obuf[0] = msg[0].addr << 1;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300339 obuf[1] = msg[0].len;
340 memcpy(obuf + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300341 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300342 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
343 break;
344 }
345 case 0x61: {
346 /* write to tuner */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300347 u8 obuf[MAX_XFER_SIZE];
348
349 if (2 + msg[0].len > sizeof(obuf)) {
350 warn("i2c wr: len=%d is too big!\n",
351 msg[1].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300352 ret = -EOPNOTSUPP;
353 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300354 }
355
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300356 obuf[0] = msg[0].addr << 1;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300357 obuf[1] = msg[0].len;
358 memcpy(obuf + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300359 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300360 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
361 break;
362 }
363 case(DW2102_RC_QUERY): {
364 u8 ibuf[2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300365 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300366 ibuf, 2, DW210X_READ_MSG);
367 memcpy(msg[0].buf, ibuf , 2);
368 break;
369 }
370 case(DW2102_VOLTAGE_CTRL): {
371 u8 obuf[2];
372 obuf[0] = 0x30;
373 obuf[1] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300374 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300375 obuf, 2, DW210X_WRITE_MSG);
376 break;
377 }
378 }
379
380 break;
381 }
Dan Carpenter324ed532013-11-22 04:56:33 -0300382 ret = num;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300383
Dan Carpenter324ed532013-11-22 04:56:33 -0300384unlock:
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300385 mutex_unlock(&d->i2c_mutex);
Dan Carpenter324ed532013-11-22 04:56:33 -0300386 return ret;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300387}
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300388
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300389static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
390{
391 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Dan Carpenter324ed532013-11-22 04:56:33 -0300392 int len, i, j, ret;
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300393
394 if (!d)
395 return -ENODEV;
396 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
397 return -EAGAIN;
398
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300399 for (j = 0; j < num; j++) {
400 switch (msg[j].addr) {
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300401 case(DW2102_RC_QUERY): {
402 u8 ibuf[2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300403 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300404 ibuf, 2, DW210X_READ_MSG);
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300405 memcpy(msg[j].buf, ibuf , 2);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300406 break;
407 }
408 case(DW2102_VOLTAGE_CTRL): {
409 u8 obuf[2];
410 obuf[0] = 0x30;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300411 obuf[1] = msg[j].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300412 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300413 obuf, 2, DW210X_WRITE_MSG);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300414 break;
415 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300416 /*case 0x55: cx24116
417 case 0x6a: stv0903
418 case 0x68: ds3000, stv0903
419 case 0x60: ts2020, stv6110, stb6100 */
420 default: {
421 if (msg[j].flags == I2C_M_RD) {
422 /* read registers */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300423 u8 ibuf[MAX_XFER_SIZE];
424
425 if (2 + msg[j].len > sizeof(ibuf)) {
426 warn("i2c rd: len=%d is too big!\n",
427 msg[j].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300428 ret = -EOPNOTSUPP;
429 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300430 }
431
Hans Verkuild51dbec2012-04-20 03:30:11 -0300432 dw210x_op_rw(d->udev, 0xc3,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300433 (msg[j].addr << 1) + 1, 0,
434 ibuf, msg[j].len + 2,
435 DW210X_READ_MSG);
436 memcpy(msg[j].buf, ibuf + 2, msg[j].len);
437 mdelay(10);
438 } else if (((msg[j].buf[0] == 0xb0) &&
439 (msg[j].addr == 0x68)) ||
440 ((msg[j].buf[0] == 0xf7) &&
441 (msg[j].addr == 0x55))) {
442 /* write firmware */
443 u8 obuf[19];
444 obuf[0] = msg[j].addr << 1;
445 obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len);
446 obuf[2] = msg[j].buf[0];
447 len = msg[j].len - 1;
448 i = 1;
449 do {
450 memcpy(obuf + 3, msg[j].buf + i,
451 (len > 16 ? 16 : len));
Hans Verkuild51dbec2012-04-20 03:30:11 -0300452 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300453 obuf, (len > 16 ? 16 : len) + 3,
454 DW210X_WRITE_MSG);
455 i += 16;
456 len -= 16;
457 } while (len > 0);
458 } else {
459 /* write registers */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300460 u8 obuf[MAX_XFER_SIZE];
461
462 if (2 + msg[j].len > sizeof(obuf)) {
463 warn("i2c wr: len=%d is too big!\n",
464 msg[j].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300465 ret = -EOPNOTSUPP;
466 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300467 }
468
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300469 obuf[0] = msg[j].addr << 1;
470 obuf[1] = msg[j].len;
471 memcpy(obuf + 2, msg[j].buf, msg[j].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300472 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300473 obuf, msg[j].len + 2,
474 DW210X_WRITE_MSG);
475 }
476 break;
477 }
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300478 }
479
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300480 }
Dan Carpenter324ed532013-11-22 04:56:33 -0300481 ret = num;
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300482
Dan Carpenter324ed532013-11-22 04:56:33 -0300483unlock:
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300484 mutex_unlock(&d->i2c_mutex);
Dan Carpenter324ed532013-11-22 04:56:33 -0300485 return ret;
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300486}
487
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300488static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
489 int num)
490{
491 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Dan Carpenter324ed532013-11-22 04:56:33 -0300492 int ret;
Hans Verkuild51dbec2012-04-20 03:30:11 -0300493 int i;
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300494
495 if (!d)
496 return -ENODEV;
497 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
498 return -EAGAIN;
499
500 switch (num) {
501 case 2: {
502 /* read */
503 /* first write first register number */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300504 u8 ibuf[MAX_XFER_SIZE], obuf[3];
505
506 if (2 + msg[1].len > sizeof(ibuf)) {
507 warn("i2c rd: len=%d is too big!\n",
508 msg[1].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300509 ret = -EOPNOTSUPP;
510 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300511 }
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300512 obuf[0] = msg[0].addr << 1;
513 obuf[1] = msg[0].len;
514 obuf[2] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300515 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300516 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
517 /* second read registers */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300518 dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300519 ibuf, msg[1].len + 2, DW210X_READ_MSG);
520 memcpy(msg[1].buf, ibuf + 2, msg[1].len);
521
522 break;
523 }
524 case 1:
525 switch (msg[0].addr) {
526 case 0x60:
527 case 0x0c: {
528 /* write to register */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300529 u8 obuf[MAX_XFER_SIZE];
530
531 if (2 + msg[0].len > sizeof(obuf)) {
532 warn("i2c wr: len=%d is too big!\n",
533 msg[0].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300534 ret = -EOPNOTSUPP;
535 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300536 }
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300537 obuf[0] = msg[0].addr << 1;
538 obuf[1] = msg[0].len;
539 memcpy(obuf + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300540 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300541 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
542 break;
543 }
544 case(DW2102_RC_QUERY): {
545 u8 ibuf[2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300546 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300547 ibuf, 2, DW210X_READ_MSG);
548 memcpy(msg[0].buf, ibuf , 2);
549 break;
550 }
551 }
552
553 break;
554 }
555
556 for (i = 0; i < num; i++) {
557 deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
558 msg[i].flags == 0 ? ">>>" : "<<<");
559 debug_dump(msg[i].buf, msg[i].len, deb_xfer);
560 }
Dan Carpenter324ed532013-11-22 04:56:33 -0300561 ret = num;
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300562
Dan Carpenter324ed532013-11-22 04:56:33 -0300563unlock:
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300564 mutex_unlock(&d->i2c_mutex);
Dan Carpenter324ed532013-11-22 04:56:33 -0300565 return ret;
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300566}
567
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300568static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300569 int num)
570{
571 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Julia Lawall21ead032009-12-22 18:00:07 -0300572 struct usb_device *udev;
Dan Carpenter324ed532013-11-22 04:56:33 -0300573 int len, i, j, ret;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300574
575 if (!d)
576 return -ENODEV;
Julia Lawall21ead032009-12-22 18:00:07 -0300577 udev = d->udev;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300578 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
579 return -EAGAIN;
580
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300581 for (j = 0; j < num; j++) {
582 switch (msg[j].addr) {
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300583 case (DW2102_RC_QUERY): {
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -0300584 u8 ibuf[5];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300585 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -0300586 ibuf, 5, DW210X_READ_MSG);
587 memcpy(msg[j].buf, ibuf + 3, 2);
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300588 break;
589 }
590 case (DW2102_VOLTAGE_CTRL): {
591 u8 obuf[2];
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300592
593 obuf[0] = 1;
594 obuf[1] = msg[j].buf[1];/* off-on */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300595 dw210x_op_rw(d->udev, 0x8a, 0, 0,
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300596 obuf, 2, DW210X_WRITE_MSG);
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300597 obuf[0] = 3;
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300598 obuf[1] = msg[j].buf[0];/* 13v-18v */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300599 dw210x_op_rw(d->udev, 0x8a, 0, 0,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300600 obuf, 2, DW210X_WRITE_MSG);
601 break;
602 }
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300603 case (DW2102_LED_CTRL): {
604 u8 obuf[2];
605
606 obuf[0] = 5;
607 obuf[1] = msg[j].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300608 dw210x_op_rw(d->udev, 0x8a, 0, 0,
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300609 obuf, 2, DW210X_WRITE_MSG);
610 break;
611 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300612 /*case 0x55: cx24116
613 case 0x6a: stv0903
Igor M. Liplianin955d00a2012-05-08 03:53:17 -0300614 case 0x68: ds3000, stv0903, rs2000
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300615 case 0x60: ts2020, stv6110, stb6100
616 case 0xa0: eeprom */
617 default: {
618 if (msg[j].flags == I2C_M_RD) {
619 /* read registers */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300620 u8 ibuf[MAX_XFER_SIZE];
621
622 if (msg[j].len > sizeof(ibuf)) {
623 warn("i2c rd: len=%d is too big!\n",
624 msg[j].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300625 ret = -EOPNOTSUPP;
626 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300627 }
628
Hans Verkuild51dbec2012-04-20 03:30:11 -0300629 dw210x_op_rw(d->udev, 0x91, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300630 ibuf, msg[j].len,
631 DW210X_READ_MSG);
632 memcpy(msg[j].buf, ibuf, msg[j].len);
633 break;
634 } else if ((msg[j].buf[0] == 0xb0) &&
635 (msg[j].addr == 0x68)) {
636 /* write firmware */
637 u8 obuf[19];
638 obuf[0] = (msg[j].len > 16 ?
639 18 : msg[j].len + 1);
640 obuf[1] = msg[j].addr << 1;
641 obuf[2] = msg[j].buf[0];
642 len = msg[j].len - 1;
643 i = 1;
644 do {
645 memcpy(obuf + 3, msg[j].buf + i,
646 (len > 16 ? 16 : len));
Hans Verkuild51dbec2012-04-20 03:30:11 -0300647 dw210x_op_rw(d->udev, 0x80, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300648 obuf, (len > 16 ? 16 : len) + 3,
649 DW210X_WRITE_MSG);
650 i += 16;
651 len -= 16;
652 } while (len > 0);
Igor M. Liplianina84adf42011-02-27 16:18:38 -0300653 } else if (j < (num - 1)) {
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300654 /* write register addr before read */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300655 u8 obuf[MAX_XFER_SIZE];
656
657 if (2 + msg[j].len > sizeof(obuf)) {
658 warn("i2c wr: len=%d is too big!\n",
659 msg[j].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300660 ret = -EOPNOTSUPP;
661 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300662 }
663
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300664 obuf[0] = msg[j + 1].len;
665 obuf[1] = (msg[j].addr << 1);
666 memcpy(obuf + 2, msg[j].buf, msg[j].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300667 dw210x_op_rw(d->udev,
Hans Verkuil1ad5d062014-08-20 16:45:27 -0300668 le16_to_cpu(udev->descriptor.idProduct) ==
Igor M. Liplianina84adf42011-02-27 16:18:38 -0300669 0x7500 ? 0x92 : 0x90, 0, 0,
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300670 obuf, msg[j].len + 2,
671 DW210X_WRITE_MSG);
672 break;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300673 } else {
674 /* write registers */
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300675 u8 obuf[MAX_XFER_SIZE];
676
677 if (2 + msg[j].len > sizeof(obuf)) {
678 warn("i2c wr: len=%d is too big!\n",
679 msg[j].len);
Dan Carpenter324ed532013-11-22 04:56:33 -0300680 ret = -EOPNOTSUPP;
681 goto unlock;
Mauro Carvalho Chehab0065a792013-11-02 07:43:40 -0300682 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300683 obuf[0] = msg[j].len + 1;
684 obuf[1] = (msg[j].addr << 1);
685 memcpy(obuf + 2, msg[j].buf, msg[j].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300686 dw210x_op_rw(d->udev, 0x80, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300687 obuf, msg[j].len + 2,
688 DW210X_WRITE_MSG);
689 break;
690 }
691 break;
692 }
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300693 }
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300694 }
Dan Carpenter324ed532013-11-22 04:56:33 -0300695 ret = num;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300696
Dan Carpenter324ed532013-11-22 04:56:33 -0300697unlock:
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300698 mutex_unlock(&d->i2c_mutex);
Dan Carpenter324ed532013-11-22 04:56:33 -0300699 return ret;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300700}
701
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300702static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
703 int num)
704{
705 struct dvb_usb_device *d = i2c_get_adapdata(adap);
706 u8 obuf[0x40], ibuf[0x40];
707
708 if (!d)
709 return -ENODEV;
710 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
711 return -EAGAIN;
712
713 switch (num) {
714 case 1:
715 switch (msg[0].addr) {
716 case SU3000_STREAM_CTRL:
717 obuf[0] = msg[0].buf[0] + 0x36;
718 obuf[1] = 3;
719 obuf[2] = 0;
720 if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0)
721 err("i2c transfer failed.");
722 break;
723 case DW2102_RC_QUERY:
724 obuf[0] = 0x10;
725 if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0)
726 err("i2c transfer failed.");
727 msg[0].buf[1] = ibuf[0];
728 msg[0].buf[0] = ibuf[1];
729 break;
730 default:
731 /* always i2c write*/
732 obuf[0] = 0x08;
733 obuf[1] = msg[0].addr;
734 obuf[2] = msg[0].len;
735
736 memcpy(&obuf[3], msg[0].buf, msg[0].len);
737
738 if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3,
739 ibuf, 1, 0) < 0)
740 err("i2c transfer failed.");
741
742 }
743 break;
744 case 2:
745 /* always i2c read */
746 obuf[0] = 0x09;
747 obuf[1] = msg[0].len;
748 obuf[2] = msg[1].len;
749 obuf[3] = msg[0].addr;
750 memcpy(&obuf[4], msg[0].buf, msg[0].len);
751
752 if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4,
753 ibuf, msg[1].len + 1, 0) < 0)
754 err("i2c transfer failed.");
755
756 memcpy(msg[1].buf, &ibuf[1], msg[1].len);
757 break;
758 default:
759 warn("more than 2 i2c messages at a time is not handled yet.");
760 break;
761 }
762 mutex_unlock(&d->i2c_mutex);
763 return num;
764}
765
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300766static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300767{
768 return I2C_FUNC_I2C;
769}
770
771static struct i2c_algorithm dw2102_i2c_algo = {
772 .master_xfer = dw2102_i2c_transfer,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300773 .functionality = dw210x_i2c_func,
774};
775
776static struct i2c_algorithm dw2102_serit_i2c_algo = {
777 .master_xfer = dw2102_serit_i2c_transfer,
778 .functionality = dw210x_i2c_func,
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300779};
780
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300781static struct i2c_algorithm dw2102_earda_i2c_algo = {
782 .master_xfer = dw2102_earda_i2c_transfer,
783 .functionality = dw210x_i2c_func,
784};
785
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300786static struct i2c_algorithm dw2104_i2c_algo = {
787 .master_xfer = dw2104_i2c_transfer,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300788 .functionality = dw210x_i2c_func,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300789};
790
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300791static struct i2c_algorithm dw3101_i2c_algo = {
792 .master_xfer = dw3101_i2c_transfer,
793 .functionality = dw210x_i2c_func,
794};
795
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300796static struct i2c_algorithm s6x0_i2c_algo = {
797 .master_xfer = s6x0_i2c_transfer,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300798 .functionality = dw210x_i2c_func,
799};
800
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300801static struct i2c_algorithm su3000_i2c_algo = {
802 .master_xfer = su3000_i2c_transfer,
803 .functionality = dw210x_i2c_func,
804};
805
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300806static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300807{
808 int i;
809 u8 ibuf[] = {0, 0};
810 u8 eeprom[256], eepromline[16];
811
812 for (i = 0; i < 256; i++) {
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300813 if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300814 err("read eeprom failed.");
815 return -1;
816 } else {
817 eepromline[i%16] = ibuf[0];
818 eeprom[i] = ibuf[0];
819 }
820 if ((i % 16) == 15) {
821 deb_xfer("%02x: ", i - 15);
822 debug_dump(eepromline, 16, deb_xfer);
823 }
824 }
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300825
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300826 memcpy(mac, eeprom + 8, 6);
827 return 0;
828};
829
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300830static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300831{
832 int i, ret;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300833 u8 ibuf[] = { 0 }, obuf[] = { 0 };
834 u8 eeprom[256], eepromline[16];
835 struct i2c_msg msg[] = {
836 {
837 .addr = 0xa0 >> 1,
838 .flags = 0,
839 .buf = obuf,
840 .len = 1,
841 }, {
842 .addr = 0xa0 >> 1,
843 .flags = I2C_M_RD,
844 .buf = ibuf,
845 .len = 1,
846 }
847 };
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300848
849 for (i = 0; i < 256; i++) {
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300850 obuf[0] = i;
851 ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2);
852 if (ret != 2) {
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300853 err("read eeprom failed.");
854 return -1;
855 } else {
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300856 eepromline[i % 16] = ibuf[0];
857 eeprom[i] = ibuf[0];
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300858 }
859
860 if ((i % 16) == 15) {
861 deb_xfer("%02x: ", i - 15);
862 debug_dump(eepromline, 16, deb_xfer);
863 }
864 }
865
866 memcpy(mac, eeprom + 16, 6);
867 return 0;
868};
869
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300870static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
871{
872 static u8 command_start[] = {0x00};
873 static u8 command_stop[] = {0x01};
874 struct i2c_msg msg = {
875 .addr = SU3000_STREAM_CTRL,
876 .flags = 0,
877 .buf = onoff ? command_start : command_stop,
878 .len = 1
879 };
880
881 i2c_transfer(&adap->dev->i2c_adap, &msg, 1);
882
883 return 0;
884}
885
886static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
887{
Olli Salonen2c4ffe22015-03-16 14:14:04 -0300888 struct dw2102_state *state = (struct dw2102_state *)d->priv;
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300889 u8 obuf[] = {0xde, 0};
890
891 info("%s: %d, initialized %d\n", __func__, i, state->initialized);
892
893 if (i && !state->initialized) {
894 state->initialized = 1;
895 /* reset board */
896 dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
897 }
898
899 return 0;
900}
901
902static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
903{
904 int i;
905 u8 obuf[] = { 0x1f, 0xf0 };
906 u8 ibuf[] = { 0 };
907 struct i2c_msg msg[] = {
908 {
909 .addr = 0x51,
910 .flags = 0,
911 .buf = obuf,
912 .len = 2,
913 }, {
914 .addr = 0x51,
915 .flags = I2C_M_RD,
916 .buf = ibuf,
917 .len = 1,
918
919 }
920 };
921
922 for (i = 0; i < 6; i++) {
923 obuf[1] = 0xf0 + i;
924 if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
925 break;
926 else
927 mac[i] = ibuf[0];
928
929 debug_dump(mac, 6, printk);
930 }
931
932 return 0;
933}
934
935static int su3000_identify_state(struct usb_device *udev,
936 struct dvb_usb_device_properties *props,
937 struct dvb_usb_device_description **desc,
938 int *cold)
939{
940 info("%s\n", __func__);
941
942 *cold = 0;
943 return 0;
944}
945
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300946static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300947{
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300948 static u8 command_13v[] = {0x00, 0x01};
949 static u8 command_18v[] = {0x01, 0x01};
950 static u8 command_off[] = {0x00, 0x00};
951 struct i2c_msg msg = {
952 .addr = DW2102_VOLTAGE_CTRL,
953 .flags = 0,
954 .buf = command_off,
955 .len = 2,
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300956 };
957
958 struct dvb_usb_adapter *udev_adap =
959 (struct dvb_usb_adapter *)(fe->dvb->priv);
960 if (voltage == SEC_VOLTAGE_18)
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300961 msg.buf = command_18v;
962 else if (voltage == SEC_VOLTAGE_13)
963 msg.buf = command_13v;
964
965 i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
966
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300967 return 0;
968}
969
Igor M. Liplianin52c506e2011-02-25 18:41:23 -0300970static int s660_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
971{
972 struct dvb_usb_adapter *d =
973 (struct dvb_usb_adapter *)(fe->dvb->priv);
Olli Salonen2c4ffe22015-03-16 14:14:04 -0300974 struct dw2102_state *st = (struct dw2102_state *)d->dev->priv;
Igor M. Liplianin52c506e2011-02-25 18:41:23 -0300975
976 dw210x_set_voltage(fe, voltage);
977 if (st->old_set_voltage)
978 st->old_set_voltage(fe, voltage);
979
980 return 0;
981}
982
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300983static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
984{
985 static u8 led_off[] = { 0 };
986 static u8 led_on[] = { 1 };
987 struct i2c_msg msg = {
988 .addr = DW2102_LED_CTRL,
989 .flags = 0,
990 .buf = led_off,
991 .len = 1
992 };
993 struct dvb_usb_adapter *udev_adap =
994 (struct dvb_usb_adapter *)(fe->dvb->priv);
995
996 if (offon)
997 msg.buf = led_on;
998 i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
999}
1000
Igor M. Liplianind4305c62008-10-17 13:45:55 -03001001static struct stv0299_config sharp_z0194a_config = {
1002 .demod_address = 0x68,
1003 .inittab = sharp_z0194a_inittab,
1004 .mclk = 88000000UL,
1005 .invert = 1,
1006 .skip_reinit = 0,
1007 .lock_output = STV0299_LOCKOUTPUT_1,
1008 .volt13_op0_op1 = STV0299_VOLT13_OP1,
1009 .min_delay_ms = 100,
1010 .set_symbol_rate = sharp_z0194a_set_symbol_rate,
1011};
1012
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001013static struct cx24116_config dw2104_config = {
1014 .demod_address = 0x55,
Igor M. Liplianincc8c4f32008-09-09 13:57:47 -03001015 .mpg_clk_pos_pol = 0x01,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001016};
1017
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001018static struct si21xx_config serit_sp1511lhb_config = {
1019 .demod_address = 0x68,
1020 .min_delay_ms = 100,
1021
1022};
1023
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001024static struct tda10023_config dw3101_tda10023_config = {
1025 .demod_address = 0x0c,
1026 .invert = 1,
1027};
1028
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001029static struct mt312_config zl313_config = {
1030 .demod_address = 0x0e,
1031};
1032
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001033static struct ds3000_config dw2104_ds3000_config = {
1034 .demod_address = 0x68,
1035};
1036
John Horan03a67272013-08-28 09:37:37 -03001037static struct ts2020_config dw2104_ts2020_config = {
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001038 .tuner_address = 0x60,
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001039 .clk_out_div = 1,
John Horan03a67272013-08-28 09:37:37 -03001040 .frequency_div = 1060000,
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001041};
1042
Igor M. Liplianin43385c82012-12-28 19:40:24 -03001043static struct ds3000_config s660_ds3000_config = {
1044 .demod_address = 0x68,
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001045 .ci_mode = 1,
Igor M. Liplianin43385c82012-12-28 19:40:24 -03001046 .set_lock_led = dw210x_led_ctrl,
1047};
1048
John Horan03a67272013-08-28 09:37:37 -03001049static struct ts2020_config s660_ts2020_config = {
1050 .tuner_address = 0x60,
1051 .clk_out_div = 1,
1052 .frequency_div = 1146000,
1053};
1054
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001055static struct stv0900_config dw2104a_stv0900_config = {
1056 .demod_address = 0x6a,
1057 .demod_mode = 0,
1058 .xtal = 27000000,
1059 .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
1060 .diseqc_mode = 2,/* 2/3 PWM */
1061 .tun1_maddress = 0,/* 0x60 */
1062 .tun1_adc = 0,/* 2 Vpp */
1063 .path1_mode = 3,
1064};
1065
1066static struct stb6100_config dw2104a_stb6100_config = {
1067 .tuner_address = 0x60,
1068 .refclock = 27000000,
1069};
1070
1071static struct stv0900_config dw2104_stv0900_config = {
1072 .demod_address = 0x68,
1073 .demod_mode = 0,
1074 .xtal = 8000000,
1075 .clkmode = 3,
1076 .diseqc_mode = 2,
1077 .tun1_maddress = 0,
1078 .tun1_adc = 1,/* 1 Vpp */
1079 .path1_mode = 3,
1080};
1081
1082static struct stv6110_config dw2104_stv6110_config = {
1083 .i2c_address = 0x60,
1084 .mclk = 16000000,
1085 .clk_div = 1,
1086};
1087
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001088static struct stv0900_config prof_7500_stv0900_config = {
1089 .demod_address = 0x6a,
1090 .demod_mode = 0,
1091 .xtal = 27000000,
1092 .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
1093 .diseqc_mode = 2,/* 2/3 PWM */
1094 .tun1_maddress = 0,/* 0x60 */
1095 .tun1_adc = 0,/* 2 Vpp */
1096 .path1_mode = 3,
1097 .tun1_type = 3,
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -03001098 .set_lock_led = dw210x_led_ctrl,
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001099};
1100
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001101static struct ds3000_config su3000_ds3000_config = {
1102 .demod_address = 0x68,
1103 .ci_mode = 1,
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001104 .set_lock_led = dw210x_led_ctrl,
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001105};
1106
Evgeny Plehov51d882e2013-11-13 20:53:59 -03001107static struct cxd2820r_config cxd2820r_config = {
1108 .i2c_address = 0x6c, /* (0xd8 >> 1) */
1109 .ts_mode = 0x38,
CrazyCat7b71ef72014-06-03 14:22:44 -03001110 .ts_clock_inv = 1,
Evgeny Plehov51d882e2013-11-13 20:53:59 -03001111};
1112
1113static struct tda18271_config tda18271_config = {
1114 .output_opt = TDA18271_OUTPUT_LT_OFF,
1115 .gate = TDA18271_GATE_DIGITAL,
1116};
1117
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001118static u8 m88rs2000_inittab[] = {
1119 DEMOD_WRITE, 0x9a, 0x30,
1120 DEMOD_WRITE, 0x00, 0x01,
1121 WRITE_DELAY, 0x19, 0x00,
1122 DEMOD_WRITE, 0x00, 0x00,
1123 DEMOD_WRITE, 0x9a, 0xb0,
1124 DEMOD_WRITE, 0x81, 0xc1,
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001125 DEMOD_WRITE, 0x81, 0x81,
1126 DEMOD_WRITE, 0x86, 0xc6,
1127 DEMOD_WRITE, 0x9a, 0x30,
1128 DEMOD_WRITE, 0xf0, 0x80,
1129 DEMOD_WRITE, 0xf1, 0xbf,
1130 DEMOD_WRITE, 0xb0, 0x45,
1131 DEMOD_WRITE, 0xb2, 0x01,
1132 DEMOD_WRITE, 0x9a, 0xb0,
1133 0xff, 0xaa, 0xff
1134};
1135
1136static struct m88rs2000_config s421_m88rs2000_config = {
1137 .demod_addr = 0x68,
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001138 .inittab = m88rs2000_inittab,
1139};
1140
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001141static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
1142{
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001143 struct dvb_tuner_ops *tuner_ops = NULL;
1144
1145 if (demod_probe & 4) {
Michael Krufky77eed212011-09-06 09:31:57 -03001146 d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001147 &d->dev->i2c_adap, 0);
Michael Krufky77eed212011-09-06 09:31:57 -03001148 if (d->fe_adap[0].fe != NULL) {
1149 if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001150 &dw2104a_stb6100_config,
1151 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001152 tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001153 tuner_ops->set_frequency = stb6100_set_freq;
1154 tuner_ops->get_frequency = stb6100_get_freq;
1155 tuner_ops->set_bandwidth = stb6100_set_bandw;
1156 tuner_ops->get_bandwidth = stb6100_get_bandw;
Michael Krufky77eed212011-09-06 09:31:57 -03001157 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001158 info("Attached STV0900+STB6100!\n");
1159 return 0;
1160 }
1161 }
1162 }
1163
1164 if (demod_probe & 2) {
Michael Krufky77eed212011-09-06 09:31:57 -03001165 d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001166 &d->dev->i2c_adap, 0);
Michael Krufky77eed212011-09-06 09:31:57 -03001167 if (d->fe_adap[0].fe != NULL) {
1168 if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001169 &dw2104_stv6110_config,
1170 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001171 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001172 info("Attached STV0900+STV6110A!\n");
1173 return 0;
1174 }
1175 }
1176 }
1177
1178 if (demod_probe & 1) {
Michael Krufky77eed212011-09-06 09:31:57 -03001179 d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001180 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001181 if (d->fe_adap[0].fe != NULL) {
1182 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001183 info("Attached cx24116!\n");
1184 return 0;
1185 }
1186 }
1187
Michael Krufky77eed212011-09-06 09:31:57 -03001188 d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001189 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001190 if (d->fe_adap[0].fe != NULL) {
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001191 dvb_attach(ts2020_attach, d->fe_adap[0].fe,
1192 &dw2104_ts2020_config, &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001193 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001194 info("Attached DS3000!\n");
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001195 return 0;
1196 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001197
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001198 return -EIO;
1199}
1200
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001201static struct dvb_usb_device_properties dw2102_properties;
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001202static struct dvb_usb_device_properties dw2104_properties;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001203static struct dvb_usb_device_properties s6x0_properties;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001204
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001205static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
1206{
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001207 if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
1208 /*dw2102_properties.adapter->tuner_attach = NULL;*/
Michael Krufky77eed212011-09-06 09:31:57 -03001209 d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001210 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001211 if (d->fe_adap[0].fe != NULL) {
1212 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001213 info("Attached si21xx!\n");
1214 return 0;
1215 }
1216 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001217
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001218 if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
Michael Krufky77eed212011-09-06 09:31:57 -03001219 d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001220 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001221 if (d->fe_adap[0].fe != NULL) {
1222 if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001223 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001224 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001225 info("Attached stv0288!\n");
1226 return 0;
1227 }
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001228 }
1229 }
1230
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001231 if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
1232 /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
Michael Krufky77eed212011-09-06 09:31:57 -03001233 d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001234 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001235 if (d->fe_adap[0].fe != NULL) {
1236 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001237 info("Attached stv0299!\n");
1238 return 0;
1239 }
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001240 }
1241 return -EIO;
1242}
1243
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001244static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
1245{
Michael Krufky77eed212011-09-06 09:31:57 -03001246 d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001247 &d->dev->i2c_adap, 0x48);
Michael Krufky77eed212011-09-06 09:31:57 -03001248 if (d->fe_adap[0].fe != NULL) {
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001249 info("Attached tda10023!\n");
1250 return 0;
1251 }
1252 return -EIO;
1253}
1254
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001255static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001256{
Michael Krufky77eed212011-09-06 09:31:57 -03001257 d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001258 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001259 if (d->fe_adap[0].fe != NULL) {
1260 if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001261 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001262 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001263 info("Attached zl100313+zl10039!\n");
1264 return 0;
1265 }
1266 }
1267
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001268 return -EIO;
1269}
1270
1271static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
1272{
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001273 u8 obuf[] = {7, 1};
1274
Michael Krufky77eed212011-09-06 09:31:57 -03001275 d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001276 &d->dev->i2c_adap);
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001277
Michael Krufky77eed212011-09-06 09:31:57 -03001278 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001279 return -EIO;
1280
Michael Krufky77eed212011-09-06 09:31:57 -03001281 if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001282 return -EIO;
1283
Michael Krufky77eed212011-09-06 09:31:57 -03001284 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001285
1286 dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
1287
1288 info("Attached stv0288+stb6000!\n");
1289
1290 return 0;
1291
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001292}
1293
1294static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
1295{
Olli Salonen2c4ffe22015-03-16 14:14:04 -03001296 struct dw2102_state *st = d->dev->priv;
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -03001297 u8 obuf[] = {7, 1};
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001298
Igor M. Liplianin43385c82012-12-28 19:40:24 -03001299 d->fe_adap[0].fe = dvb_attach(ds3000_attach, &s660_ds3000_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001300 &d->dev->i2c_adap);
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001301
Michael Krufky77eed212011-09-06 09:31:57 -03001302 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001303 return -EIO;
1304
John Horan03a67272013-08-28 09:37:37 -03001305 dvb_attach(ts2020_attach, d->fe_adap[0].fe, &s660_ts2020_config,
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001306 &d->dev->i2c_adap);
1307
Michael Krufky77eed212011-09-06 09:31:57 -03001308 st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
1309 d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -03001310
1311 dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
1312
John Horan03a67272013-08-28 09:37:37 -03001313 info("Attached ds3000+ts2020!\n");
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001314
1315 return 0;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001316}
1317
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001318static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
1319{
Igor M. Liplianin4e59df82011-02-25 18:41:23 -03001320 u8 obuf[] = {7, 1};
1321
Michael Krufky77eed212011-09-06 09:31:57 -03001322 d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001323 &d->dev->i2c_adap, 0);
Michael Krufky77eed212011-09-06 09:31:57 -03001324 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001325 return -EIO;
Igor M. Liplianin4e59df82011-02-25 18:41:23 -03001326
Michael Krufky77eed212011-09-06 09:31:57 -03001327 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001328
Igor M. Liplianin4e59df82011-02-25 18:41:23 -03001329 dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
1330
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001331 info("Attached STV0900+STB6100A!\n");
1332
1333 return 0;
1334}
1335
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001336static int su3000_frontend_attach(struct dvb_usb_adapter *d)
1337{
1338 u8 obuf[3] = { 0xe, 0x80, 0 };
1339 u8 ibuf[] = { 0 };
1340
1341 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1342 err("command 0x0e transfer failed.");
1343
1344 obuf[0] = 0xe;
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001345 obuf[1] = 0x02;
1346 obuf[2] = 1;
1347
1348 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1349 err("command 0x0e transfer failed.");
1350 msleep(300);
1351
1352 obuf[0] = 0xe;
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001353 obuf[1] = 0x83;
1354 obuf[2] = 0;
1355
1356 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1357 err("command 0x0e transfer failed.");
1358
1359 obuf[0] = 0xe;
1360 obuf[1] = 0x83;
1361 obuf[2] = 1;
1362
1363 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1364 err("command 0x0e transfer failed.");
1365
1366 obuf[0] = 0x51;
1367
1368 if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
1369 err("command 0x51 transfer failed.");
1370
Michael Krufky77eed212011-09-06 09:31:57 -03001371 d->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001372 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001373 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001374 return -EIO;
1375
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001376 if (dvb_attach(ts2020_attach, d->fe_adap[0].fe,
1377 &dw2104_ts2020_config,
1378 &d->dev->i2c_adap)) {
1379 info("Attached DS3000/TS2020!\n");
1380 return 0;
1381 }
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001382
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001383 info("Failed to attach DS3000/TS2020!\n");
1384 return -EIO;
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001385}
1386
Evgeny Plehov51d882e2013-11-13 20:53:59 -03001387static int t220_frontend_attach(struct dvb_usb_adapter *d)
1388{
CrazyCat7b71ef72014-06-03 14:22:44 -03001389 u8 obuf[3] = { 0xe, 0x87, 0 };
Evgeny Plehov51d882e2013-11-13 20:53:59 -03001390 u8 ibuf[] = { 0 };
1391
1392 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1393 err("command 0x0e transfer failed.");
1394
1395 obuf[0] = 0xe;
CrazyCat7b71ef72014-06-03 14:22:44 -03001396 obuf[1] = 0x86;
1397 obuf[2] = 1;
1398
1399 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1400 err("command 0x0e transfer failed.");
1401
1402 obuf[0] = 0xe;
1403 obuf[1] = 0x80;
Evgeny Plehov51d882e2013-11-13 20:53:59 -03001404 obuf[2] = 0;
1405
1406 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1407 err("command 0x0e transfer failed.");
1408
CrazyCat7b71ef72014-06-03 14:22:44 -03001409 msleep(50);
Evgeny Plehov51d882e2013-11-13 20:53:59 -03001410
1411 obuf[0] = 0xe;
1412 obuf[1] = 0x80;
1413 obuf[2] = 1;
1414
1415 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1416 err("command 0x0e transfer failed.");
1417
1418 obuf[0] = 0x51;
1419
1420 if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
1421 err("command 0x51 transfer failed.");
1422
1423 d->fe_adap[0].fe = dvb_attach(cxd2820r_attach, &cxd2820r_config,
1424 &d->dev->i2c_adap, NULL);
1425 if (d->fe_adap[0].fe != NULL) {
1426 if (dvb_attach(tda18271_attach, d->fe_adap[0].fe, 0x60,
1427 &d->dev->i2c_adap, &tda18271_config)) {
1428 info("Attached TDA18271HD/CXD2820R!\n");
1429 return 0;
1430 }
1431 }
1432
1433 info("Failed to attach TDA18271HD/CXD2820R!\n");
1434 return -EIO;
1435}
1436
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001437static int m88rs2000_frontend_attach(struct dvb_usb_adapter *d)
1438{
1439 u8 obuf[] = { 0x51 };
1440 u8 ibuf[] = { 0 };
1441
1442 if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
1443 err("command 0x51 transfer failed.");
1444
1445 d->fe_adap[0].fe = dvb_attach(m88rs2000_attach, &s421_m88rs2000_config,
1446 &d->dev->i2c_adap);
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001447
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001448 if (d->fe_adap[0].fe == NULL)
1449 return -EIO;
1450
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001451 if (dvb_attach(ts2020_attach, d->fe_adap[0].fe,
1452 &dw2104_ts2020_config,
1453 &d->dev->i2c_adap)) {
1454 info("Attached RS2000/TS2020!\n");
1455 return 0;
1456 }
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001457
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001458 info("Failed to attach RS2000/TS2020!\n");
1459 return -EIO;
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001460}
1461
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001462static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
1463{
Michael Krufky77eed212011-09-06 09:31:57 -03001464 dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001465 &adap->dev->i2c_adap, DVB_PLL_OPERA1);
1466 return 0;
1467}
1468
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001469static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
1470{
Michael Krufky77eed212011-09-06 09:31:57 -03001471 dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001472 &adap->dev->i2c_adap, DVB_PLL_TUA6034);
1473
1474 return 0;
1475}
1476
Evgeny Plehova49de262013-11-15 16:43:33 -03001477static int dw2102_rc_query(struct dvb_usb_device *d)
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001478{
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001479 u8 key[2];
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001480 struct i2c_msg msg = {
1481 .addr = DW2102_RC_QUERY,
1482 .flags = I2C_M_RD,
1483 .buf = key,
1484 .len = 2
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001485 };
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001486
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001487 if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
Evgeny Plehova49de262013-11-15 16:43:33 -03001488 if (msg.buf[0] != 0xff) {
1489 deb_rc("%s: rc code: %x, %x\n",
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001490 __func__, key[0], key[1]);
David Härdeman120703f2014-04-03 20:31:30 -03001491 rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0], 0);
Evgeny Plehova49de262013-11-15 16:43:33 -03001492 }
1493 }
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001494
Evgeny Plehova49de262013-11-15 16:43:33 -03001495 return 0;
1496}
1497
1498static int prof_rc_query(struct dvb_usb_device *d)
1499{
1500 u8 key[2];
1501 struct i2c_msg msg = {
1502 .addr = DW2102_RC_QUERY,
1503 .flags = I2C_M_RD,
1504 .buf = key,
1505 .len = 2
1506 };
1507
1508 if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
1509 if (msg.buf[0] != 0xff) {
1510 deb_rc("%s: rc code: %x, %x\n",
1511 __func__, key[0], key[1]);
David Härdeman120703f2014-04-03 20:31:30 -03001512 rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0]^0xff, 0);
Evgeny Plehova49de262013-11-15 16:43:33 -03001513 }
1514 }
1515
1516 return 0;
1517}
1518
1519static int su3000_rc_query(struct dvb_usb_device *d)
1520{
1521 u8 key[2];
1522 struct i2c_msg msg = {
1523 .addr = DW2102_RC_QUERY,
1524 .flags = I2C_M_RD,
1525 .buf = key,
1526 .len = 2
1527 };
1528
1529 if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
1530 if (msg.buf[0] != 0xff) {
1531 deb_rc("%s: rc code: %x, %x\n",
1532 __func__, key[0], key[1]);
David Härdeman120703f2014-04-03 20:31:30 -03001533 rc_keydown(d->rc_dev, RC_TYPE_RC5,
1534 RC_SCANCODE_RC5(key[1], key[0]), 0);
Evgeny Plehova49de262013-11-15 16:43:33 -03001535 }
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001536 }
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001537
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001538 return 0;
1539}
1540
Jonathan Nieder27351b12011-12-23 19:00:45 -03001541enum dw2102_table_entry {
1542 CYPRESS_DW2102,
1543 CYPRESS_DW2101,
1544 CYPRESS_DW2104,
1545 TEVII_S650,
1546 TERRATEC_CINERGY_S,
1547 CYPRESS_DW3101,
1548 TEVII_S630,
1549 PROF_1100,
1550 TEVII_S660,
1551 PROF_7500,
1552 GENIATECH_SU3000,
1553 TERRATEC_CINERGY_S2,
1554 TEVII_S480_1,
1555 TEVII_S480_2,
1556 X3M_SPC1400HD,
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001557 TEVII_S421,
1558 TEVII_S632,
Igor M. Liplianin44122dd2013-02-21 08:11:41 -03001559 TERRATEC_CINERGY_S2_R2,
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -03001560 GOTVIEW_SAT_HD,
Evgeny Plehov51d882e2013-11-13 20:53:59 -03001561 GENIATECH_T220,
Jonathan Nieder27351b12011-12-23 19:00:45 -03001562};
1563
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001564static struct usb_device_id dw2102_table[] = {
Jonathan Nieder27351b12011-12-23 19:00:45 -03001565 [CYPRESS_DW2102] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
1566 [CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
1567 [CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
1568 [TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
1569 [TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
1570 [CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
1571 [TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
1572 [PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
1573 [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
1574 [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)},
1575 [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)},
1576 [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
1577 [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
1578 [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
1579 [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)},
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001580 [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)},
1581 [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)},
Igor M. Liplianin44122dd2013-02-21 08:11:41 -03001582 [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)},
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -03001583 [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)},
Evgeny Plehov51d882e2013-11-13 20:53:59 -03001584 [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001585 { }
1586};
1587
1588MODULE_DEVICE_TABLE(usb, dw2102_table);
1589
1590static int dw2102_load_firmware(struct usb_device *dev,
1591 const struct firmware *frmwr)
1592{
1593 u8 *b, *p;
1594 int ret = 0, i;
1595 u8 reset;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001596 u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001597 const struct firmware *fw;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001598
Hans Verkuil1ad5d062014-08-20 16:45:27 -03001599 switch (le16_to_cpu(dev->descriptor.idProduct)) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001600 case 0x2101:
Rémi Cardona68236272012-09-28 08:59:32 -03001601 ret = request_firmware(&fw, DW2101_FIRMWARE, &dev->dev);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001602 if (ret != 0) {
Rémi Cardona68236272012-09-28 08:59:32 -03001603 err(err_str, DW2101_FIRMWARE);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001604 return ret;
1605 }
1606 break;
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001607 default:
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001608 fw = frmwr;
1609 break;
1610 }
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001611 info("start downloading DW210X firmware");
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001612 p = kmalloc(fw->size, GFP_KERNEL);
1613 reset = 1;
1614 /*stop the CPU*/
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001615 dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);
1616 dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001617
1618 if (p != NULL) {
1619 memcpy(p, fw->data, fw->size);
1620 for (i = 0; i < fw->size; i += 0x40) {
1621 b = (u8 *) p + i;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001622 if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,
1623 DW210X_WRITE_MSG) != 0x40) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001624 err("error while transferring firmware");
1625 ret = -EINVAL;
1626 break;
1627 }
1628 }
1629 /* restart the CPU */
1630 reset = 0;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001631 if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
1632 DW210X_WRITE_MSG) != 1) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001633 err("could not restart the USB controller CPU.");
1634 ret = -EINVAL;
1635 }
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001636 if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
1637 DW210X_WRITE_MSG) != 1) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001638 err("could not restart the USB controller CPU.");
1639 ret = -EINVAL;
1640 }
1641 /* init registers */
Hans Verkuil1ad5d062014-08-20 16:45:27 -03001642 switch (le16_to_cpu(dev->descriptor.idProduct)) {
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001643 case USB_PID_TEVII_S650:
Evgeny Plehova49de262013-11-15 16:43:33 -03001644 dw2104_properties.rc.core.rc_codes = RC_MAP_TEVII_NEC;
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001645 case USB_PID_DW2104:
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001646 reset = 1;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001647 dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
1648 DW210X_WRITE_MSG);
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001649 /* break omitted intentionally */
1650 case USB_PID_DW3101:
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001651 reset = 0;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001652 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
1653 DW210X_WRITE_MSG);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001654 break;
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001655 case USB_PID_CINERGY_S:
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001656 case USB_PID_DW2102:
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001657 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
1658 DW210X_WRITE_MSG);
1659 dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
1660 DW210X_READ_MSG);
1661 /* check STV0299 frontend */
1662 dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,
1663 DW210X_READ_MSG);
Igor M. Liplianinea023df2008-12-04 12:49:23 -03001664 if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001665 dw2102_properties.i2c_algo = &dw2102_i2c_algo;
Michael Krufky77eed212011-09-06 09:31:57 -03001666 dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001667 break;
1668 } else {
1669 /* check STV0288 frontend */
1670 reset16[0] = 0xd0;
1671 reset16[1] = 1;
1672 reset16[2] = 0;
1673 dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,
1674 DW210X_WRITE_MSG);
1675 dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,
1676 DW210X_READ_MSG);
1677 if (reset16[2] == 0x11) {
1678 dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001679 break;
1680 }
1681 }
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001682 case 0x2101:
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001683 dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,
1684 DW210X_READ_MSG);
1685 dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
1686 DW210X_READ_MSG);
1687 dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
1688 DW210X_READ_MSG);
1689 dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
1690 DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001691 break;
1692 }
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001693
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001694 msleep(100);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001695 kfree(p);
1696 }
1697 return ret;
1698}
1699
1700static struct dvb_usb_device_properties dw2102_properties = {
1701 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1702 .usb_ctrl = DEVICE_SPECIFIC,
Rémi Cardona68236272012-09-28 08:59:32 -03001703 .firmware = DW2102_FIRMWARE,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001704 .no_reconnect = 1,
1705
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001706 .i2c_algo = &dw2102_serit_i2c_algo,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001707
Evgeny Plehova49de262013-11-15 16:43:33 -03001708 .rc.core = {
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001709 .rc_interval = 150,
Evgeny Plehova49de262013-11-15 16:43:33 -03001710 .rc_codes = RC_MAP_DM1105_NEC,
1711 .module_name = "dw2102",
1712 .allowed_protos = RC_BIT_NEC,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001713 .rc_query = dw2102_rc_query,
1714 },
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001715
1716 .generic_bulk_ctrl_endpoint = 0x81,
1717 /* parameter for the MPEG2-data transfer */
1718 .num_adapters = 1,
1719 .download_firmware = dw2102_load_firmware,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001720 .read_mac_address = dw210x_read_mac_address,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001721 .adapter = {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001722 {
Michael Krufky77eed212011-09-06 09:31:57 -03001723 .num_frontends = 1,
1724 .fe = {{
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001725 .frontend_attach = dw2102_frontend_attach,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001726 .stream = {
1727 .type = USB_BULK,
1728 .count = 8,
1729 .endpoint = 0x82,
1730 .u = {
1731 .bulk = {
1732 .buffersize = 4096,
1733 }
1734 }
1735 },
Michael Krufky77eed212011-09-06 09:31:57 -03001736 }},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001737 }
1738 },
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001739 .num_device_descs = 3,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001740 .devices = {
1741 {"DVBWorld DVB-S 2102 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001742 {&dw2102_table[CYPRESS_DW2102], NULL},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001743 {NULL},
1744 },
1745 {"DVBWorld DVB-S 2101 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001746 {&dw2102_table[CYPRESS_DW2101], NULL},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001747 {NULL},
1748 },
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001749 {"TerraTec Cinergy S USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001750 {&dw2102_table[TERRATEC_CINERGY_S], NULL},
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001751 {NULL},
1752 },
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001753 }
1754};
1755
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001756static struct dvb_usb_device_properties dw2104_properties = {
1757 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1758 .usb_ctrl = DEVICE_SPECIFIC,
Rémi Cardona68236272012-09-28 08:59:32 -03001759 .firmware = DW2104_FIRMWARE,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001760 .no_reconnect = 1,
1761
1762 .i2c_algo = &dw2104_i2c_algo,
Evgeny Plehova49de262013-11-15 16:43:33 -03001763 .rc.core = {
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001764 .rc_interval = 150,
Evgeny Plehova49de262013-11-15 16:43:33 -03001765 .rc_codes = RC_MAP_DM1105_NEC,
1766 .module_name = "dw2102",
1767 .allowed_protos = RC_BIT_NEC,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001768 .rc_query = dw2102_rc_query,
1769 },
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001770
1771 .generic_bulk_ctrl_endpoint = 0x81,
1772 /* parameter for the MPEG2-data transfer */
1773 .num_adapters = 1,
1774 .download_firmware = dw2102_load_firmware,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001775 .read_mac_address = dw210x_read_mac_address,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001776 .adapter = {
1777 {
Michael Krufky77eed212011-09-06 09:31:57 -03001778 .num_frontends = 1,
1779 .fe = {{
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001780 .frontend_attach = dw2104_frontend_attach,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001781 .stream = {
1782 .type = USB_BULK,
1783 .count = 8,
1784 .endpoint = 0x82,
1785 .u = {
1786 .bulk = {
1787 .buffersize = 4096,
1788 }
1789 }
1790 },
Michael Krufky77eed212011-09-06 09:31:57 -03001791 }},
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001792 }
1793 },
1794 .num_device_descs = 2,
1795 .devices = {
1796 { "DVBWorld DW2104 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001797 {&dw2102_table[CYPRESS_DW2104], NULL},
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001798 {NULL},
1799 },
1800 { "TeVii S650 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001801 {&dw2102_table[TEVII_S650], NULL},
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001802 {NULL},
1803 },
1804 }
1805};
1806
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001807static struct dvb_usb_device_properties dw3101_properties = {
1808 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1809 .usb_ctrl = DEVICE_SPECIFIC,
Rémi Cardona68236272012-09-28 08:59:32 -03001810 .firmware = DW3101_FIRMWARE,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001811 .no_reconnect = 1,
1812
1813 .i2c_algo = &dw3101_i2c_algo,
Evgeny Plehova49de262013-11-15 16:43:33 -03001814 .rc.core = {
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001815 .rc_interval = 150,
Evgeny Plehova49de262013-11-15 16:43:33 -03001816 .rc_codes = RC_MAP_DM1105_NEC,
1817 .module_name = "dw2102",
1818 .allowed_protos = RC_BIT_NEC,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001819 .rc_query = dw2102_rc_query,
1820 },
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001821
1822 .generic_bulk_ctrl_endpoint = 0x81,
1823 /* parameter for the MPEG2-data transfer */
1824 .num_adapters = 1,
1825 .download_firmware = dw2102_load_firmware,
1826 .read_mac_address = dw210x_read_mac_address,
1827 .adapter = {
1828 {
Michael Krufky77eed212011-09-06 09:31:57 -03001829 .num_frontends = 1,
1830 .fe = {{
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001831 .frontend_attach = dw3101_frontend_attach,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001832 .tuner_attach = dw3101_tuner_attach,
1833 .stream = {
1834 .type = USB_BULK,
1835 .count = 8,
1836 .endpoint = 0x82,
1837 .u = {
1838 .bulk = {
1839 .buffersize = 4096,
1840 }
1841 }
1842 },
Michael Krufky77eed212011-09-06 09:31:57 -03001843 }},
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001844 }
1845 },
1846 .num_device_descs = 1,
1847 .devices = {
1848 { "DVBWorld DVB-C 3101 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001849 {&dw2102_table[CYPRESS_DW3101], NULL},
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001850 {NULL},
1851 },
1852 }
1853};
1854
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001855static struct dvb_usb_device_properties s6x0_properties = {
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001856 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1857 .usb_ctrl = DEVICE_SPECIFIC,
Olli Salonen2c4ffe22015-03-16 14:14:04 -03001858 .size_of_priv = sizeof(struct dw2102_state),
Rémi Cardona68236272012-09-28 08:59:32 -03001859 .firmware = S630_FIRMWARE,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001860 .no_reconnect = 1,
1861
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001862 .i2c_algo = &s6x0_i2c_algo,
Evgeny Plehova49de262013-11-15 16:43:33 -03001863 .rc.core = {
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001864 .rc_interval = 150,
Evgeny Plehova49de262013-11-15 16:43:33 -03001865 .rc_codes = RC_MAP_TEVII_NEC,
1866 .module_name = "dw2102",
1867 .allowed_protos = RC_BIT_NEC,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001868 .rc_query = dw2102_rc_query,
1869 },
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001870
1871 .generic_bulk_ctrl_endpoint = 0x81,
1872 .num_adapters = 1,
1873 .download_firmware = dw2102_load_firmware,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001874 .read_mac_address = s6x0_read_mac_address,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001875 .adapter = {
1876 {
Michael Krufky77eed212011-09-06 09:31:57 -03001877 .num_frontends = 1,
1878 .fe = {{
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001879 .frontend_attach = zl100313_frontend_attach,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001880 .stream = {
1881 .type = USB_BULK,
1882 .count = 8,
1883 .endpoint = 0x82,
1884 .u = {
1885 .bulk = {
1886 .buffersize = 4096,
1887 }
1888 }
1889 },
Michael Krufky77eed212011-09-06 09:31:57 -03001890 }},
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001891 }
1892 },
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001893 .num_device_descs = 1,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001894 .devices = {
1895 {"TeVii S630 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001896 {&dw2102_table[TEVII_S630], NULL},
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001897 {NULL},
1898 },
1899 }
1900};
1901
Hans Verkuil1ad5d062014-08-20 16:45:27 -03001902static struct dvb_usb_device_properties *p1100;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001903static struct dvb_usb_device_description d1100 = {
1904 "Prof 1100 USB ",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001905 {&dw2102_table[PROF_1100], NULL},
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001906 {NULL},
1907};
1908
Hans Verkuil1ad5d062014-08-20 16:45:27 -03001909static struct dvb_usb_device_properties *s660;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001910static struct dvb_usb_device_description d660 = {
1911 "TeVii S660 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001912 {&dw2102_table[TEVII_S660], NULL},
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001913 {NULL},
1914};
1915
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001916static struct dvb_usb_device_description d480_1 = {
1917 "TeVii S480.1 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001918 {&dw2102_table[TEVII_S480_1], NULL},
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001919 {NULL},
1920};
1921
1922static struct dvb_usb_device_description d480_2 = {
1923 "TeVii S480.2 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001924 {&dw2102_table[TEVII_S480_2], NULL},
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001925 {NULL},
1926};
1927
Hans Verkuil1ad5d062014-08-20 16:45:27 -03001928static struct dvb_usb_device_properties *p7500;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001929static struct dvb_usb_device_description d7500 = {
1930 "Prof 7500 USB DVB-S2",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001931 {&dw2102_table[PROF_7500], NULL},
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001932 {NULL},
1933};
1934
Hans Verkuil1ad5d062014-08-20 16:45:27 -03001935static struct dvb_usb_device_properties *s421;
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001936static struct dvb_usb_device_description d421 = {
1937 "TeVii S421 PCI",
1938 {&dw2102_table[TEVII_S421], NULL},
1939 {NULL},
1940};
1941
1942static struct dvb_usb_device_description d632 = {
1943 "TeVii S632 USB",
1944 {&dw2102_table[TEVII_S632], NULL},
1945 {NULL},
1946};
1947
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001948static struct dvb_usb_device_properties su3000_properties = {
1949 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1950 .usb_ctrl = DEVICE_SPECIFIC,
Olli Salonen2c4ffe22015-03-16 14:14:04 -03001951 .size_of_priv = sizeof(struct dw2102_state),
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001952 .power_ctrl = su3000_power_ctrl,
1953 .num_adapters = 1,
1954 .identify_state = su3000_identify_state,
1955 .i2c_algo = &su3000_i2c_algo,
1956
Evgeny Plehova49de262013-11-15 16:43:33 -03001957 .rc.core = {
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001958 .rc_interval = 150,
Evgeny Plehova49de262013-11-15 16:43:33 -03001959 .rc_codes = RC_MAP_SU3000,
1960 .module_name = "dw2102",
1961 .allowed_protos = RC_BIT_RC5,
1962 .rc_query = su3000_rc_query,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001963 },
1964
1965 .read_mac_address = su3000_read_mac_address,
1966
1967 .generic_bulk_ctrl_endpoint = 0x01,
1968
1969 .adapter = {
1970 {
Michael Krufky77eed212011-09-06 09:31:57 -03001971 .num_frontends = 1,
1972 .fe = {{
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001973 .streaming_ctrl = su3000_streaming_ctrl,
1974 .frontend_attach = su3000_frontend_attach,
1975 .stream = {
1976 .type = USB_BULK,
1977 .count = 8,
1978 .endpoint = 0x82,
1979 .u = {
1980 .bulk = {
1981 .buffersize = 4096,
1982 }
1983 }
1984 }
Michael Krufky77eed212011-09-06 09:31:57 -03001985 }},
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001986 }
1987 },
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -03001988 .num_device_descs = 5,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001989 .devices = {
1990 { "SU3000HD DVB-S USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001991 { &dw2102_table[GENIATECH_SU3000], NULL },
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001992 { NULL },
1993 },
Igor M. Liplianin2adc5912011-02-25 18:41:22 -03001994 { "Terratec Cinergy S2 USB HD",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001995 { &dw2102_table[TERRATEC_CINERGY_S2], NULL },
Igor M. Liplianin2adc5912011-02-25 18:41:22 -03001996 { NULL },
1997 },
Igor M. Liplianin5265ea52011-02-27 16:17:25 -03001998 { "X3M TV SPC1400HD PCI",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001999 { &dw2102_table[X3M_SPC1400HD], NULL },
Igor M. Liplianin5265ea52011-02-27 16:17:25 -03002000 { NULL },
2001 },
Igor M. Liplianin44122dd2013-02-21 08:11:41 -03002002 { "Terratec Cinergy S2 USB HD Rev.2",
2003 { &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL },
2004 { NULL },
2005 },
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -03002006 { "GOTVIEW Satellite HD",
2007 { &dw2102_table[GOTVIEW_SAT_HD], NULL },
2008 { NULL },
2009 },
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03002010 }
2011};
2012
Evgeny Plehov51d882e2013-11-13 20:53:59 -03002013static struct dvb_usb_device_properties t220_properties = {
2014 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
2015 .usb_ctrl = DEVICE_SPECIFIC,
Olli Salonen2c4ffe22015-03-16 14:14:04 -03002016 .size_of_priv = sizeof(struct dw2102_state),
Evgeny Plehov51d882e2013-11-13 20:53:59 -03002017 .power_ctrl = su3000_power_ctrl,
2018 .num_adapters = 1,
2019 .identify_state = su3000_identify_state,
2020 .i2c_algo = &su3000_i2c_algo,
2021
Evgeny Plehova49de262013-11-15 16:43:33 -03002022 .rc.core = {
Evgeny Plehov51d882e2013-11-13 20:53:59 -03002023 .rc_interval = 150,
Evgeny Plehova49de262013-11-15 16:43:33 -03002024 .rc_codes = RC_MAP_SU3000,
2025 .module_name = "dw2102",
2026 .allowed_protos = RC_BIT_RC5,
2027 .rc_query = su3000_rc_query,
Evgeny Plehov51d882e2013-11-13 20:53:59 -03002028 },
2029
2030 .read_mac_address = su3000_read_mac_address,
2031
2032 .generic_bulk_ctrl_endpoint = 0x01,
2033
2034 .adapter = {
2035 {
2036 .num_frontends = 1,
2037 .fe = { {
2038 .streaming_ctrl = su3000_streaming_ctrl,
2039 .frontend_attach = t220_frontend_attach,
2040 .stream = {
2041 .type = USB_BULK,
2042 .count = 8,
2043 .endpoint = 0x82,
2044 .u = {
2045 .bulk = {
2046 .buffersize = 4096,
2047 }
2048 }
2049 }
2050 } },
2051 }
2052 },
2053 .num_device_descs = 1,
2054 .devices = {
2055 { "Geniatech T220 DVB-T/T2 USB2.0",
2056 { &dw2102_table[GENIATECH_T220], NULL },
2057 { NULL },
2058 },
2059 }
2060};
2061
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002062static int dw2102_probe(struct usb_interface *intf,
2063 const struct usb_device_id *id)
2064{
Thomas Meyer68dd9dd2011-11-17 18:43:40 -03002065 p1100 = kmemdup(&s6x0_properties,
2066 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002067 if (!p1100)
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002068 return -ENOMEM;
2069 /* copy default structure */
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002070 /* fill only different fields */
Rémi Cardona68236272012-09-28 08:59:32 -03002071 p1100->firmware = P1100_FIRMWARE;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002072 p1100->devices[0] = d1100;
Evgeny Plehova49de262013-11-15 16:43:33 -03002073 p1100->rc.core.rc_query = prof_rc_query;
2074 p1100->rc.core.rc_codes = RC_MAP_TBS_NEC;
Michael Krufky77eed212011-09-06 09:31:57 -03002075 p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002076
Thomas Meyer68dd9dd2011-11-17 18:43:40 -03002077 s660 = kmemdup(&s6x0_properties,
2078 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002079 if (!s660) {
2080 kfree(p1100);
2081 return -ENOMEM;
2082 }
Rémi Cardona68236272012-09-28 08:59:32 -03002083 s660->firmware = S660_FIRMWARE;
Igor M. Liplianine8f50552011-02-25 18:41:23 -03002084 s660->num_device_descs = 3;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002085 s660->devices[0] = d660;
Igor M. Liplianine8f50552011-02-25 18:41:23 -03002086 s660->devices[1] = d480_1;
2087 s660->devices[2] = d480_2;
Michael Krufky77eed212011-09-06 09:31:57 -03002088 s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002089
Thomas Meyer68dd9dd2011-11-17 18:43:40 -03002090 p7500 = kmemdup(&s6x0_properties,
2091 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002092 if (!p7500) {
2093 kfree(p1100);
2094 kfree(s660);
2095 return -ENOMEM;
2096 }
Rémi Cardona68236272012-09-28 08:59:32 -03002097 p7500->firmware = P7500_FIRMWARE;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002098 p7500->devices[0] = d7500;
Evgeny Plehova49de262013-11-15 16:43:33 -03002099 p7500->rc.core.rc_query = prof_rc_query;
2100 p7500->rc.core.rc_codes = RC_MAP_TBS_NEC;
Michael Krufky77eed212011-09-06 09:31:57 -03002101 p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002102
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03002103
2104 s421 = kmemdup(&su3000_properties,
2105 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
2106 if (!s421) {
2107 kfree(p1100);
2108 kfree(s660);
2109 kfree(p7500);
2110 return -ENOMEM;
2111 }
2112 s421->num_device_descs = 2;
2113 s421->devices[0] = d421;
2114 s421->devices[1] = d632;
2115 s421->adapter->fe[0].frontend_attach = m88rs2000_frontend_attach;
2116
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03002117 if (0 == dvb_usb_device_init(intf, &dw2102_properties,
2118 THIS_MODULE, NULL, adapter_nr) ||
2119 0 == dvb_usb_device_init(intf, &dw2104_properties,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03002120 THIS_MODULE, NULL, adapter_nr) ||
2121 0 == dvb_usb_device_init(intf, &dw3101_properties,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03002122 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianin141cc352009-11-27 14:37:35 -03002123 0 == dvb_usb_device_init(intf, &s6x0_properties,
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002124 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002125 0 == dvb_usb_device_init(intf, p1100,
2126 THIS_MODULE, NULL, adapter_nr) ||
2127 0 == dvb_usb_device_init(intf, s660,
2128 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002129 0 == dvb_usb_device_init(intf, p7500,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03002130 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03002131 0 == dvb_usb_device_init(intf, s421,
2132 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03002133 0 == dvb_usb_device_init(intf, &su3000_properties,
Evgeny Plehov51d882e2013-11-13 20:53:59 -03002134 THIS_MODULE, NULL, adapter_nr) ||
2135 0 == dvb_usb_device_init(intf, &t220_properties,
2136 THIS_MODULE, NULL, adapter_nr))
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03002137 return 0;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03002138
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03002139 return -ENODEV;
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002140}
2141
Olli Salonen70769b22015-03-16 14:14:05 -03002142static void dw2102_disconnect(struct usb_interface *intf)
2143{
2144 struct dvb_usb_device *d = usb_get_intfdata(intf);
2145 struct dw2102_state *st = (struct dw2102_state *)d->priv;
2146 struct i2c_client *client;
2147
2148 /* remove I2C client for tuner */
2149 client = st->i2c_client_tuner;
2150 if (client) {
2151 module_put(client->dev.driver->owner);
2152 i2c_unregister_device(client);
2153 }
2154
2155 dvb_usb_device_exit(intf);
2156}
2157
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002158static struct usb_driver dw2102_driver = {
2159 .name = "dw2102",
2160 .probe = dw2102_probe,
Olli Salonen70769b22015-03-16 14:14:05 -03002161 .disconnect = dw2102_disconnect,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002162 .id_table = dw2102_table,
2163};
2164
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002165module_usb_driver(dw2102_driver);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002166
2167MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03002168MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03002169 " DVB-C 3101 USB2.0,"
2170 " TeVii S600, S630, S650, S660, S480, S421, S632"
2171 " Prof 1100, 7500 USB2.0,"
Evgeny Plehov51d882e2013-11-13 20:53:59 -03002172 " Geniatech SU3000, T220 devices");
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002173MODULE_VERSION("0.1");
2174MODULE_LICENSE("GPL");
Rémi Cardona68236272012-09-28 08:59:32 -03002175MODULE_FIRMWARE(DW2101_FIRMWARE);
2176MODULE_FIRMWARE(DW2102_FIRMWARE);
2177MODULE_FIRMWARE(DW2104_FIRMWARE);
2178MODULE_FIRMWARE(DW3101_FIRMWARE);
2179MODULE_FIRMWARE(S630_FIRMWARE);
2180MODULE_FIRMWARE(S660_FIRMWARE);
2181MODULE_FIRMWARE(P1100_FIRMWARE);
2182MODULE_FIRMWARE(P7500_FIRMWARE);