blob: d5957b0299d322bc42853a24971db4a30a497385 [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,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03005 * Geniatech SU3000 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"
Igor M. Liplianinb858c332012-12-28 19:40:33 -030032#include "ts2020.h"
Igor M Liplianin7fd48282008-07-20 08:05:50 -030033
34#ifndef USB_PID_DW2102
35#define USB_PID_DW2102 0x2102
36#endif
37
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -030038#ifndef USB_PID_DW2104
39#define USB_PID_DW2104 0x2104
40#endif
41
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -030042#ifndef USB_PID_DW3101
43#define USB_PID_DW3101 0x3101
44#endif
45
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -030046#ifndef USB_PID_CINERGY_S
47#define USB_PID_CINERGY_S 0x0064
48#endif
49
Igor M. Liplianin141cc352009-11-27 14:37:35 -030050#ifndef USB_PID_TEVII_S630
51#define USB_PID_TEVII_S630 0xd630
52#endif
53
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -030054#ifndef USB_PID_TEVII_S650
55#define USB_PID_TEVII_S650 0xd650
56#endif
57
Igor M. Liplianin141cc352009-11-27 14:37:35 -030058#ifndef USB_PID_TEVII_S660
59#define USB_PID_TEVII_S660 0xd660
60#endif
61
Igor M. Liplianine8f50552011-02-25 18:41:23 -030062#ifndef USB_PID_TEVII_S480_1
63#define USB_PID_TEVII_S480_1 0xd481
64#endif
65
66#ifndef USB_PID_TEVII_S480_2
67#define USB_PID_TEVII_S480_2 0xd482
68#endif
69
Igor M. Liplianin141cc352009-11-27 14:37:35 -030070#ifndef USB_PID_PROF_1100
71#define USB_PID_PROF_1100 0xb012
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -030072#endif
73
Igor M. Liplianin955d00a2012-05-08 03:53:17 -030074#ifndef USB_PID_TEVII_S421
75#define USB_PID_TEVII_S421 0xd421
76#endif
77
78#ifndef USB_PID_TEVII_S632
79#define USB_PID_TEVII_S632 0xd632
80#endif
81
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -030082#ifndef USB_PID_GOTVIEW_SAT_HD
83#define USB_PID_GOTVIEW_SAT_HD 0x5456
84#endif
85
Igor M. Liplianin21b007b2008-09-17 19:19:19 -030086#define DW210X_READ_MSG 0
87#define DW210X_WRITE_MSG 1
Igor M Liplianin7fd48282008-07-20 08:05:50 -030088
89#define REG_1F_SYMBOLRATE_BYTE0 0x1f
90#define REG_20_SYMBOLRATE_BYTE1 0x20
91#define REG_21_SYMBOLRATE_BYTE2 0x21
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -030092/* on my own*/
Igor M Liplianin7fd48282008-07-20 08:05:50 -030093#define DW2102_VOLTAGE_CTRL (0x1800)
Igor M. Liplianind2ffc442011-02-25 18:41:22 -030094#define SU3000_STREAM_CTRL (0x1900)
Igor M Liplianin7fd48282008-07-20 08:05:50 -030095#define DW2102_RC_QUERY (0x1a00)
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -030096#define DW2102_LED_CTRL (0x1b00)
Igor M Liplianin7fd48282008-07-20 08:05:50 -030097
Rémi Cardona68236272012-09-28 08:59:32 -030098#define DW2101_FIRMWARE "dvb-usb-dw2101.fw"
99#define DW2102_FIRMWARE "dvb-usb-dw2102.fw"
100#define DW2104_FIRMWARE "dvb-usb-dw2104.fw"
101#define DW3101_FIRMWARE "dvb-usb-dw3101.fw"
102#define S630_FIRMWARE "dvb-usb-s630.fw"
103#define S660_FIRMWARE "dvb-usb-s660.fw"
104#define P1100_FIRMWARE "dvb-usb-p1100.fw"
105#define P7500_FIRMWARE "dvb-usb-p7500.fw"
106
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300107#define err_str "did not find the firmware file. (%s) " \
108 "Please see linux/Documentation/dvb/ for more details " \
109 "on firmware-problems."
110
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -0300111struct rc_map_dvb_usb_table_table {
112 struct rc_map_table *rc_keys;
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -0300113 int rc_keys_size;
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300114};
115
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300116struct su3000_state {
117 u8 initialized;
118};
119
Igor M. Liplianin52c506e2011-02-25 18:41:23 -0300120struct s6x0_state {
121 int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v);
122};
123
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300124/* debug */
125static int dvb_usb_dw2102_debug;
126module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -0300127MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
128 DVB_USB_DEBUG_STATUS);
129
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -0300130/* keymaps */
131static int ir_keymap;
132module_param_named(keymap, ir_keymap, int, 0644);
Igor M. Liplianinfeb16e92011-02-25 18:41:22 -0300133MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ..."
134 " 256=none");
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300135
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300136/* demod probe */
137static int demod_probe = 1;
138module_param_named(demod, demod_probe, int, 0644);
139MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 "
140 "4=stv0903+stb6100(or-able)).");
141
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300142DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
143
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300144static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300145 u16 index, u8 * data, u16 len, int flags)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300146{
147 int ret;
Florian Micklerb47b8502011-03-21 15:33:44 -0300148 u8 *u8buf;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300149 unsigned int pipe = (flags == DW210X_READ_MSG) ?
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300150 usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300151 u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300152
Florian Micklerb47b8502011-03-21 15:33:44 -0300153 u8buf = kmalloc(len, GFP_KERNEL);
154 if (!u8buf)
155 return -ENOMEM;
156
157
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300158 if (flags == DW210X_WRITE_MSG)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300159 memcpy(u8buf, data, len);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300160 ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
161 value, index , u8buf, len, 2000);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300162
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300163 if (flags == DW210X_READ_MSG)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300164 memcpy(data, u8buf, len);
Florian Micklerb47b8502011-03-21 15:33:44 -0300165
166 kfree(u8buf);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300167 return ret;
168}
169
170/* I2C */
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300171static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
172 int num)
173{
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300174 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300175 int i = 0;
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300176 u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300177 u16 value;
178
179 if (!d)
180 return -ENODEV;
181 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
182 return -EAGAIN;
183
184 switch (num) {
185 case 2:
186 /* read stv0299 register */
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300187 value = msg[0].buf[0];/* register */
188 for (i = 0; i < msg[1].len; i++) {
Hans Verkuild51dbec2012-04-20 03:30:11 -0300189 dw210x_op_rw(d->udev, 0xb5, value + i, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300190 buf6, 2, DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300191 msg[1].buf[i] = buf6[0];
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300192 }
193 break;
194 case 1:
195 switch (msg[0].addr) {
196 case 0x68:
197 /* write to stv0299 register */
198 buf6[0] = 0x2a;
199 buf6[1] = msg[0].buf[0];
200 buf6[2] = msg[0].buf[1];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300201 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300202 buf6, 3, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300203 break;
204 case 0x60:
205 if (msg[0].flags == 0) {
206 /* write to tuner pll */
207 buf6[0] = 0x2c;
208 buf6[1] = 5;
209 buf6[2] = 0xc0;
210 buf6[3] = msg[0].buf[0];
211 buf6[4] = msg[0].buf[1];
212 buf6[5] = msg[0].buf[2];
213 buf6[6] = msg[0].buf[3];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300214 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300215 buf6, 7, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300216 } else {
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300217 /* read from tuner */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300218 dw210x_op_rw(d->udev, 0xb5, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300219 buf6, 1, DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300220 msg[0].buf[0] = buf6[0];
221 }
222 break;
223 case (DW2102_RC_QUERY):
Hans Verkuild51dbec2012-04-20 03:30:11 -0300224 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300225 buf6, 2, DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300226 msg[0].buf[0] = buf6[0];
227 msg[0].buf[1] = buf6[1];
228 break;
229 case (DW2102_VOLTAGE_CTRL):
230 buf6[0] = 0x30;
231 buf6[1] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300232 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300233 buf6, 2, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300234 break;
235 }
236
237 break;
238 }
239
240 mutex_unlock(&d->i2c_mutex);
241 return num;
242}
243
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300244static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
245 struct i2c_msg msg[], int num)
246{
247 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300248 u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};
249
250 if (!d)
251 return -ENODEV;
252 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
253 return -EAGAIN;
254
255 switch (num) {
256 case 2:
257 /* read si2109 register by number */
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300258 buf6[0] = msg[0].addr << 1;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300259 buf6[1] = msg[0].len;
260 buf6[2] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300261 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300262 buf6, msg[0].len + 2, DW210X_WRITE_MSG);
263 /* read si2109 register */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300264 dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300265 buf6, msg[1].len + 2, DW210X_READ_MSG);
266 memcpy(msg[1].buf, buf6 + 2, msg[1].len);
267
268 break;
269 case 1:
270 switch (msg[0].addr) {
271 case 0x68:
272 /* write to si2109 register */
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300273 buf6[0] = msg[0].addr << 1;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300274 buf6[1] = msg[0].len;
275 memcpy(buf6 + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300276 dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300277 msg[0].len + 2, DW210X_WRITE_MSG);
278 break;
279 case(DW2102_RC_QUERY):
Hans Verkuild51dbec2012-04-20 03:30:11 -0300280 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300281 buf6, 2, DW210X_READ_MSG);
282 msg[0].buf[0] = buf6[0];
283 msg[0].buf[1] = buf6[1];
284 break;
285 case(DW2102_VOLTAGE_CTRL):
286 buf6[0] = 0x30;
287 buf6[1] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300288 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300289 buf6, 2, DW210X_WRITE_MSG);
290 break;
291 }
292 break;
293 }
294
295 mutex_unlock(&d->i2c_mutex);
296 return num;
297}
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300298
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300299static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
300{
301 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300302
303 if (!d)
304 return -ENODEV;
305 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
306 return -EAGAIN;
307
308 switch (num) {
309 case 2: {
310 /* read */
311 /* first write first register number */
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300312 u8 ibuf[msg[1].len + 2], obuf[3];
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 */
329 u8 obuf[msg[0].len + 2];
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300330 obuf[0] = msg[0].addr << 1;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300331 obuf[1] = msg[0].len;
332 memcpy(obuf + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300333 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300334 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
335 break;
336 }
337 case 0x61: {
338 /* write to tuner */
339 u8 obuf[msg[0].len + 2];
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300340 obuf[0] = msg[0].addr << 1;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300341 obuf[1] = msg[0].len;
342 memcpy(obuf + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300343 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300344 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
345 break;
346 }
347 case(DW2102_RC_QUERY): {
348 u8 ibuf[2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300349 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300350 ibuf, 2, DW210X_READ_MSG);
351 memcpy(msg[0].buf, ibuf , 2);
352 break;
353 }
354 case(DW2102_VOLTAGE_CTRL): {
355 u8 obuf[2];
356 obuf[0] = 0x30;
357 obuf[1] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300358 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300359 obuf, 2, DW210X_WRITE_MSG);
360 break;
361 }
362 }
363
364 break;
365 }
366
367 mutex_unlock(&d->i2c_mutex);
368 return num;
369}
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300370
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300371static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
372{
373 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300374 int len, i, j;
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300375
376 if (!d)
377 return -ENODEV;
378 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
379 return -EAGAIN;
380
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300381 for (j = 0; j < num; j++) {
382 switch (msg[j].addr) {
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300383 case(DW2102_RC_QUERY): {
384 u8 ibuf[2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300385 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300386 ibuf, 2, DW210X_READ_MSG);
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300387 memcpy(msg[j].buf, ibuf , 2);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300388 break;
389 }
390 case(DW2102_VOLTAGE_CTRL): {
391 u8 obuf[2];
392 obuf[0] = 0x30;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300393 obuf[1] = msg[j].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300394 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300395 obuf, 2, DW210X_WRITE_MSG);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300396 break;
397 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300398 /*case 0x55: cx24116
399 case 0x6a: stv0903
400 case 0x68: ds3000, stv0903
401 case 0x60: ts2020, stv6110, stb6100 */
402 default: {
403 if (msg[j].flags == I2C_M_RD) {
404 /* read registers */
405 u8 ibuf[msg[j].len + 2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300406 dw210x_op_rw(d->udev, 0xc3,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300407 (msg[j].addr << 1) + 1, 0,
408 ibuf, msg[j].len + 2,
409 DW210X_READ_MSG);
410 memcpy(msg[j].buf, ibuf + 2, msg[j].len);
411 mdelay(10);
412 } else if (((msg[j].buf[0] == 0xb0) &&
413 (msg[j].addr == 0x68)) ||
414 ((msg[j].buf[0] == 0xf7) &&
415 (msg[j].addr == 0x55))) {
416 /* write firmware */
417 u8 obuf[19];
418 obuf[0] = msg[j].addr << 1;
419 obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len);
420 obuf[2] = msg[j].buf[0];
421 len = msg[j].len - 1;
422 i = 1;
423 do {
424 memcpy(obuf + 3, msg[j].buf + i,
425 (len > 16 ? 16 : len));
Hans Verkuild51dbec2012-04-20 03:30:11 -0300426 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300427 obuf, (len > 16 ? 16 : len) + 3,
428 DW210X_WRITE_MSG);
429 i += 16;
430 len -= 16;
431 } while (len > 0);
432 } else {
433 /* write registers */
434 u8 obuf[msg[j].len + 2];
435 obuf[0] = msg[j].addr << 1;
436 obuf[1] = msg[j].len;
437 memcpy(obuf + 2, msg[j].buf, msg[j].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300438 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300439 obuf, msg[j].len + 2,
440 DW210X_WRITE_MSG);
441 }
442 break;
443 }
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300444 }
445
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300446 }
447
448 mutex_unlock(&d->i2c_mutex);
449 return num;
450}
451
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300452static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
453 int num)
454{
455 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300456 int i;
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300457
458 if (!d)
459 return -ENODEV;
460 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
461 return -EAGAIN;
462
463 switch (num) {
464 case 2: {
465 /* read */
466 /* first write first register number */
467 u8 ibuf[msg[1].len + 2], obuf[3];
468 obuf[0] = msg[0].addr << 1;
469 obuf[1] = msg[0].len;
470 obuf[2] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300471 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300472 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
473 /* second read registers */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300474 dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300475 ibuf, msg[1].len + 2, DW210X_READ_MSG);
476 memcpy(msg[1].buf, ibuf + 2, msg[1].len);
477
478 break;
479 }
480 case 1:
481 switch (msg[0].addr) {
482 case 0x60:
483 case 0x0c: {
484 /* write to register */
485 u8 obuf[msg[0].len + 2];
486 obuf[0] = msg[0].addr << 1;
487 obuf[1] = msg[0].len;
488 memcpy(obuf + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300489 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300490 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
491 break;
492 }
493 case(DW2102_RC_QUERY): {
494 u8 ibuf[2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300495 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300496 ibuf, 2, DW210X_READ_MSG);
497 memcpy(msg[0].buf, ibuf , 2);
498 break;
499 }
500 }
501
502 break;
503 }
504
505 for (i = 0; i < num; i++) {
506 deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
507 msg[i].flags == 0 ? ">>>" : "<<<");
508 debug_dump(msg[i].buf, msg[i].len, deb_xfer);
509 }
510
511 mutex_unlock(&d->i2c_mutex);
512 return num;
513}
514
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300515static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300516 int num)
517{
518 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Julia Lawall21ead032009-12-22 18:00:07 -0300519 struct usb_device *udev;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300520 int len, i, j;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300521
522 if (!d)
523 return -ENODEV;
Julia Lawall21ead032009-12-22 18:00:07 -0300524 udev = d->udev;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300525 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
526 return -EAGAIN;
527
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300528 for (j = 0; j < num; j++) {
529 switch (msg[j].addr) {
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300530 case (DW2102_RC_QUERY): {
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -0300531 u8 ibuf[5];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300532 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -0300533 ibuf, 5, DW210X_READ_MSG);
534 memcpy(msg[j].buf, ibuf + 3, 2);
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300535 break;
536 }
537 case (DW2102_VOLTAGE_CTRL): {
538 u8 obuf[2];
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300539
540 obuf[0] = 1;
541 obuf[1] = msg[j].buf[1];/* off-on */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300542 dw210x_op_rw(d->udev, 0x8a, 0, 0,
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300543 obuf, 2, DW210X_WRITE_MSG);
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300544 obuf[0] = 3;
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300545 obuf[1] = msg[j].buf[0];/* 13v-18v */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300546 dw210x_op_rw(d->udev, 0x8a, 0, 0,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300547 obuf, 2, DW210X_WRITE_MSG);
548 break;
549 }
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300550 case (DW2102_LED_CTRL): {
551 u8 obuf[2];
552
553 obuf[0] = 5;
554 obuf[1] = msg[j].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300555 dw210x_op_rw(d->udev, 0x8a, 0, 0,
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300556 obuf, 2, DW210X_WRITE_MSG);
557 break;
558 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300559 /*case 0x55: cx24116
560 case 0x6a: stv0903
Igor M. Liplianin955d00a2012-05-08 03:53:17 -0300561 case 0x68: ds3000, stv0903, rs2000
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300562 case 0x60: ts2020, stv6110, stb6100
563 case 0xa0: eeprom */
564 default: {
565 if (msg[j].flags == I2C_M_RD) {
566 /* read registers */
567 u8 ibuf[msg[j].len];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300568 dw210x_op_rw(d->udev, 0x91, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300569 ibuf, msg[j].len,
570 DW210X_READ_MSG);
571 memcpy(msg[j].buf, ibuf, msg[j].len);
572 break;
573 } else if ((msg[j].buf[0] == 0xb0) &&
574 (msg[j].addr == 0x68)) {
575 /* write firmware */
576 u8 obuf[19];
577 obuf[0] = (msg[j].len > 16 ?
578 18 : msg[j].len + 1);
579 obuf[1] = msg[j].addr << 1;
580 obuf[2] = msg[j].buf[0];
581 len = msg[j].len - 1;
582 i = 1;
583 do {
584 memcpy(obuf + 3, msg[j].buf + i,
585 (len > 16 ? 16 : len));
Hans Verkuild51dbec2012-04-20 03:30:11 -0300586 dw210x_op_rw(d->udev, 0x80, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300587 obuf, (len > 16 ? 16 : len) + 3,
588 DW210X_WRITE_MSG);
589 i += 16;
590 len -= 16;
591 } while (len > 0);
Igor M. Liplianina84adf42011-02-27 16:18:38 -0300592 } else if (j < (num - 1)) {
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300593 /* write register addr before read */
594 u8 obuf[msg[j].len + 2];
595 obuf[0] = msg[j + 1].len;
596 obuf[1] = (msg[j].addr << 1);
597 memcpy(obuf + 2, msg[j].buf, msg[j].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300598 dw210x_op_rw(d->udev,
Igor M. Liplianina84adf42011-02-27 16:18:38 -0300599 udev->descriptor.idProduct ==
600 0x7500 ? 0x92 : 0x90, 0, 0,
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300601 obuf, msg[j].len + 2,
602 DW210X_WRITE_MSG);
603 break;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300604 } else {
605 /* write registers */
606 u8 obuf[msg[j].len + 2];
607 obuf[0] = msg[j].len + 1;
608 obuf[1] = (msg[j].addr << 1);
609 memcpy(obuf + 2, msg[j].buf, msg[j].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300610 dw210x_op_rw(d->udev, 0x80, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300611 obuf, msg[j].len + 2,
612 DW210X_WRITE_MSG);
613 break;
614 }
615 break;
616 }
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300617 }
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300618 }
619
620 mutex_unlock(&d->i2c_mutex);
621 return num;
622}
623
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300624static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
625 int num)
626{
627 struct dvb_usb_device *d = i2c_get_adapdata(adap);
628 u8 obuf[0x40], ibuf[0x40];
629
630 if (!d)
631 return -ENODEV;
632 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
633 return -EAGAIN;
634
635 switch (num) {
636 case 1:
637 switch (msg[0].addr) {
638 case SU3000_STREAM_CTRL:
639 obuf[0] = msg[0].buf[0] + 0x36;
640 obuf[1] = 3;
641 obuf[2] = 0;
642 if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0)
643 err("i2c transfer failed.");
644 break;
645 case DW2102_RC_QUERY:
646 obuf[0] = 0x10;
647 if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0)
648 err("i2c transfer failed.");
649 msg[0].buf[1] = ibuf[0];
650 msg[0].buf[0] = ibuf[1];
651 break;
652 default:
653 /* always i2c write*/
654 obuf[0] = 0x08;
655 obuf[1] = msg[0].addr;
656 obuf[2] = msg[0].len;
657
658 memcpy(&obuf[3], msg[0].buf, msg[0].len);
659
660 if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3,
661 ibuf, 1, 0) < 0)
662 err("i2c transfer failed.");
663
664 }
665 break;
666 case 2:
667 /* always i2c read */
668 obuf[0] = 0x09;
669 obuf[1] = msg[0].len;
670 obuf[2] = msg[1].len;
671 obuf[3] = msg[0].addr;
672 memcpy(&obuf[4], msg[0].buf, msg[0].len);
673
674 if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4,
675 ibuf, msg[1].len + 1, 0) < 0)
676 err("i2c transfer failed.");
677
678 memcpy(msg[1].buf, &ibuf[1], msg[1].len);
679 break;
680 default:
681 warn("more than 2 i2c messages at a time is not handled yet.");
682 break;
683 }
684 mutex_unlock(&d->i2c_mutex);
685 return num;
686}
687
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300688static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300689{
690 return I2C_FUNC_I2C;
691}
692
693static struct i2c_algorithm dw2102_i2c_algo = {
694 .master_xfer = dw2102_i2c_transfer,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300695 .functionality = dw210x_i2c_func,
696};
697
698static struct i2c_algorithm dw2102_serit_i2c_algo = {
699 .master_xfer = dw2102_serit_i2c_transfer,
700 .functionality = dw210x_i2c_func,
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300701};
702
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300703static struct i2c_algorithm dw2102_earda_i2c_algo = {
704 .master_xfer = dw2102_earda_i2c_transfer,
705 .functionality = dw210x_i2c_func,
706};
707
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300708static struct i2c_algorithm dw2104_i2c_algo = {
709 .master_xfer = dw2104_i2c_transfer,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300710 .functionality = dw210x_i2c_func,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300711};
712
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300713static struct i2c_algorithm dw3101_i2c_algo = {
714 .master_xfer = dw3101_i2c_transfer,
715 .functionality = dw210x_i2c_func,
716};
717
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300718static struct i2c_algorithm s6x0_i2c_algo = {
719 .master_xfer = s6x0_i2c_transfer,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300720 .functionality = dw210x_i2c_func,
721};
722
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300723static struct i2c_algorithm su3000_i2c_algo = {
724 .master_xfer = su3000_i2c_transfer,
725 .functionality = dw210x_i2c_func,
726};
727
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300728static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300729{
730 int i;
731 u8 ibuf[] = {0, 0};
732 u8 eeprom[256], eepromline[16];
733
734 for (i = 0; i < 256; i++) {
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300735 if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300736 err("read eeprom failed.");
737 return -1;
738 } else {
739 eepromline[i%16] = ibuf[0];
740 eeprom[i] = ibuf[0];
741 }
742 if ((i % 16) == 15) {
743 deb_xfer("%02x: ", i - 15);
744 debug_dump(eepromline, 16, deb_xfer);
745 }
746 }
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300747
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300748 memcpy(mac, eeprom + 8, 6);
749 return 0;
750};
751
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300752static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300753{
754 int i, ret;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300755 u8 ibuf[] = { 0 }, obuf[] = { 0 };
756 u8 eeprom[256], eepromline[16];
757 struct i2c_msg msg[] = {
758 {
759 .addr = 0xa0 >> 1,
760 .flags = 0,
761 .buf = obuf,
762 .len = 1,
763 }, {
764 .addr = 0xa0 >> 1,
765 .flags = I2C_M_RD,
766 .buf = ibuf,
767 .len = 1,
768 }
769 };
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300770
771 for (i = 0; i < 256; i++) {
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300772 obuf[0] = i;
773 ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2);
774 if (ret != 2) {
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300775 err("read eeprom failed.");
776 return -1;
777 } else {
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300778 eepromline[i % 16] = ibuf[0];
779 eeprom[i] = ibuf[0];
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300780 }
781
782 if ((i % 16) == 15) {
783 deb_xfer("%02x: ", i - 15);
784 debug_dump(eepromline, 16, deb_xfer);
785 }
786 }
787
788 memcpy(mac, eeprom + 16, 6);
789 return 0;
790};
791
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300792static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
793{
794 static u8 command_start[] = {0x00};
795 static u8 command_stop[] = {0x01};
796 struct i2c_msg msg = {
797 .addr = SU3000_STREAM_CTRL,
798 .flags = 0,
799 .buf = onoff ? command_start : command_stop,
800 .len = 1
801 };
802
803 i2c_transfer(&adap->dev->i2c_adap, &msg, 1);
804
805 return 0;
806}
807
808static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
809{
810 struct su3000_state *state = (struct su3000_state *)d->priv;
811 u8 obuf[] = {0xde, 0};
812
813 info("%s: %d, initialized %d\n", __func__, i, state->initialized);
814
815 if (i && !state->initialized) {
816 state->initialized = 1;
817 /* reset board */
818 dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
819 }
820
821 return 0;
822}
823
824static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
825{
826 int i;
827 u8 obuf[] = { 0x1f, 0xf0 };
828 u8 ibuf[] = { 0 };
829 struct i2c_msg msg[] = {
830 {
831 .addr = 0x51,
832 .flags = 0,
833 .buf = obuf,
834 .len = 2,
835 }, {
836 .addr = 0x51,
837 .flags = I2C_M_RD,
838 .buf = ibuf,
839 .len = 1,
840
841 }
842 };
843
844 for (i = 0; i < 6; i++) {
845 obuf[1] = 0xf0 + i;
846 if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
847 break;
848 else
849 mac[i] = ibuf[0];
850
851 debug_dump(mac, 6, printk);
852 }
853
854 return 0;
855}
856
857static int su3000_identify_state(struct usb_device *udev,
858 struct dvb_usb_device_properties *props,
859 struct dvb_usb_device_description **desc,
860 int *cold)
861{
862 info("%s\n", __func__);
863
864 *cold = 0;
865 return 0;
866}
867
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300868static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300869{
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300870 static u8 command_13v[] = {0x00, 0x01};
871 static u8 command_18v[] = {0x01, 0x01};
872 static u8 command_off[] = {0x00, 0x00};
873 struct i2c_msg msg = {
874 .addr = DW2102_VOLTAGE_CTRL,
875 .flags = 0,
876 .buf = command_off,
877 .len = 2,
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300878 };
879
880 struct dvb_usb_adapter *udev_adap =
881 (struct dvb_usb_adapter *)(fe->dvb->priv);
882 if (voltage == SEC_VOLTAGE_18)
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300883 msg.buf = command_18v;
884 else if (voltage == SEC_VOLTAGE_13)
885 msg.buf = command_13v;
886
887 i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
888
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300889 return 0;
890}
891
Igor M. Liplianin52c506e2011-02-25 18:41:23 -0300892static int s660_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
893{
894 struct dvb_usb_adapter *d =
895 (struct dvb_usb_adapter *)(fe->dvb->priv);
896 struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
897
898 dw210x_set_voltage(fe, voltage);
899 if (st->old_set_voltage)
900 st->old_set_voltage(fe, voltage);
901
902 return 0;
903}
904
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300905static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
906{
907 static u8 led_off[] = { 0 };
908 static u8 led_on[] = { 1 };
909 struct i2c_msg msg = {
910 .addr = DW2102_LED_CTRL,
911 .flags = 0,
912 .buf = led_off,
913 .len = 1
914 };
915 struct dvb_usb_adapter *udev_adap =
916 (struct dvb_usb_adapter *)(fe->dvb->priv);
917
918 if (offon)
919 msg.buf = led_on;
920 i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
921}
922
Igor M. Liplianind4305c62008-10-17 13:45:55 -0300923static struct stv0299_config sharp_z0194a_config = {
924 .demod_address = 0x68,
925 .inittab = sharp_z0194a_inittab,
926 .mclk = 88000000UL,
927 .invert = 1,
928 .skip_reinit = 0,
929 .lock_output = STV0299_LOCKOUTPUT_1,
930 .volt13_op0_op1 = STV0299_VOLT13_OP1,
931 .min_delay_ms = 100,
932 .set_symbol_rate = sharp_z0194a_set_symbol_rate,
933};
934
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300935static struct cx24116_config dw2104_config = {
936 .demod_address = 0x55,
Igor M. Liplianincc8c4f32008-09-09 13:57:47 -0300937 .mpg_clk_pos_pol = 0x01,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300938};
939
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300940static struct si21xx_config serit_sp1511lhb_config = {
941 .demod_address = 0x68,
942 .min_delay_ms = 100,
943
944};
945
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300946static struct tda10023_config dw3101_tda10023_config = {
947 .demod_address = 0x0c,
948 .invert = 1,
949};
950
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300951static struct mt312_config zl313_config = {
952 .demod_address = 0x0e,
953};
954
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300955static struct ds3000_config dw2104_ds3000_config = {
956 .demod_address = 0x68,
957};
958
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -0300959static struct ts2020_config dw2104_ts2020_config = {
960 .tuner_address = 0x60,
Igor M. Liplianinb858c332012-12-28 19:40:33 -0300961 .clk_out_div = 1,
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -0300962};
963
Igor M. Liplianin43385c82012-12-28 19:40:24 -0300964static struct ds3000_config s660_ds3000_config = {
965 .demod_address = 0x68,
Igor M. Liplianinb858c332012-12-28 19:40:33 -0300966 .ci_mode = 1,
Igor M. Liplianin43385c82012-12-28 19:40:24 -0300967 .set_lock_led = dw210x_led_ctrl,
968};
969
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300970static struct stv0900_config dw2104a_stv0900_config = {
971 .demod_address = 0x6a,
972 .demod_mode = 0,
973 .xtal = 27000000,
974 .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
975 .diseqc_mode = 2,/* 2/3 PWM */
976 .tun1_maddress = 0,/* 0x60 */
977 .tun1_adc = 0,/* 2 Vpp */
978 .path1_mode = 3,
979};
980
981static struct stb6100_config dw2104a_stb6100_config = {
982 .tuner_address = 0x60,
983 .refclock = 27000000,
984};
985
986static struct stv0900_config dw2104_stv0900_config = {
987 .demod_address = 0x68,
988 .demod_mode = 0,
989 .xtal = 8000000,
990 .clkmode = 3,
991 .diseqc_mode = 2,
992 .tun1_maddress = 0,
993 .tun1_adc = 1,/* 1 Vpp */
994 .path1_mode = 3,
995};
996
997static struct stv6110_config dw2104_stv6110_config = {
998 .i2c_address = 0x60,
999 .mclk = 16000000,
1000 .clk_div = 1,
1001};
1002
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001003static struct stv0900_config prof_7500_stv0900_config = {
1004 .demod_address = 0x6a,
1005 .demod_mode = 0,
1006 .xtal = 27000000,
1007 .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
1008 .diseqc_mode = 2,/* 2/3 PWM */
1009 .tun1_maddress = 0,/* 0x60 */
1010 .tun1_adc = 0,/* 2 Vpp */
1011 .path1_mode = 3,
1012 .tun1_type = 3,
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -03001013 .set_lock_led = dw210x_led_ctrl,
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001014};
1015
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001016static struct ds3000_config su3000_ds3000_config = {
1017 .demod_address = 0x68,
1018 .ci_mode = 1,
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001019 .set_lock_led = dw210x_led_ctrl,
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001020};
1021
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001022static u8 m88rs2000_inittab[] = {
1023 DEMOD_WRITE, 0x9a, 0x30,
1024 DEMOD_WRITE, 0x00, 0x01,
1025 WRITE_DELAY, 0x19, 0x00,
1026 DEMOD_WRITE, 0x00, 0x00,
1027 DEMOD_WRITE, 0x9a, 0xb0,
1028 DEMOD_WRITE, 0x81, 0xc1,
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001029 DEMOD_WRITE, 0x81, 0x81,
1030 DEMOD_WRITE, 0x86, 0xc6,
1031 DEMOD_WRITE, 0x9a, 0x30,
1032 DEMOD_WRITE, 0xf0, 0x80,
1033 DEMOD_WRITE, 0xf1, 0xbf,
1034 DEMOD_WRITE, 0xb0, 0x45,
1035 DEMOD_WRITE, 0xb2, 0x01,
1036 DEMOD_WRITE, 0x9a, 0xb0,
1037 0xff, 0xaa, 0xff
1038};
1039
1040static struct m88rs2000_config s421_m88rs2000_config = {
1041 .demod_addr = 0x68,
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001042 .inittab = m88rs2000_inittab,
1043};
1044
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001045static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
1046{
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001047 struct dvb_tuner_ops *tuner_ops = NULL;
1048
1049 if (demod_probe & 4) {
Michael Krufky77eed212011-09-06 09:31:57 -03001050 d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001051 &d->dev->i2c_adap, 0);
Michael Krufky77eed212011-09-06 09:31:57 -03001052 if (d->fe_adap[0].fe != NULL) {
1053 if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001054 &dw2104a_stb6100_config,
1055 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001056 tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001057 tuner_ops->set_frequency = stb6100_set_freq;
1058 tuner_ops->get_frequency = stb6100_get_freq;
1059 tuner_ops->set_bandwidth = stb6100_set_bandw;
1060 tuner_ops->get_bandwidth = stb6100_get_bandw;
Michael Krufky77eed212011-09-06 09:31:57 -03001061 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001062 info("Attached STV0900+STB6100!\n");
1063 return 0;
1064 }
1065 }
1066 }
1067
1068 if (demod_probe & 2) {
Michael Krufky77eed212011-09-06 09:31:57 -03001069 d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001070 &d->dev->i2c_adap, 0);
Michael Krufky77eed212011-09-06 09:31:57 -03001071 if (d->fe_adap[0].fe != NULL) {
1072 if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001073 &dw2104_stv6110_config,
1074 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001075 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001076 info("Attached STV0900+STV6110A!\n");
1077 return 0;
1078 }
1079 }
1080 }
1081
1082 if (demod_probe & 1) {
Michael Krufky77eed212011-09-06 09:31:57 -03001083 d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001084 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001085 if (d->fe_adap[0].fe != NULL) {
1086 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001087 info("Attached cx24116!\n");
1088 return 0;
1089 }
1090 }
1091
Michael Krufky77eed212011-09-06 09:31:57 -03001092 d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001093 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001094 if (d->fe_adap[0].fe != NULL) {
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001095 dvb_attach(ts2020_attach, d->fe_adap[0].fe,
1096 &dw2104_ts2020_config, &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001097 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001098 info("Attached DS3000!\n");
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001099 return 0;
1100 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001101
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001102 return -EIO;
1103}
1104
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001105static struct dvb_usb_device_properties dw2102_properties;
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001106static struct dvb_usb_device_properties dw2104_properties;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001107static struct dvb_usb_device_properties s6x0_properties;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001108
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001109static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
1110{
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001111 if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
1112 /*dw2102_properties.adapter->tuner_attach = NULL;*/
Michael Krufky77eed212011-09-06 09:31:57 -03001113 d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001114 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001115 if (d->fe_adap[0].fe != NULL) {
1116 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001117 info("Attached si21xx!\n");
1118 return 0;
1119 }
1120 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001121
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001122 if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
Michael Krufky77eed212011-09-06 09:31:57 -03001123 d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001124 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001125 if (d->fe_adap[0].fe != NULL) {
1126 if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001127 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001128 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001129 info("Attached stv0288!\n");
1130 return 0;
1131 }
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001132 }
1133 }
1134
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001135 if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
1136 /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
Michael Krufky77eed212011-09-06 09:31:57 -03001137 d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001138 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001139 if (d->fe_adap[0].fe != NULL) {
1140 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001141 info("Attached stv0299!\n");
1142 return 0;
1143 }
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001144 }
1145 return -EIO;
1146}
1147
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001148static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
1149{
Michael Krufky77eed212011-09-06 09:31:57 -03001150 d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001151 &d->dev->i2c_adap, 0x48);
Michael Krufky77eed212011-09-06 09:31:57 -03001152 if (d->fe_adap[0].fe != NULL) {
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001153 info("Attached tda10023!\n");
1154 return 0;
1155 }
1156 return -EIO;
1157}
1158
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001159static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001160{
Michael Krufky77eed212011-09-06 09:31:57 -03001161 d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001162 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001163 if (d->fe_adap[0].fe != NULL) {
1164 if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001165 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001166 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001167 info("Attached zl100313+zl10039!\n");
1168 return 0;
1169 }
1170 }
1171
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001172 return -EIO;
1173}
1174
1175static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
1176{
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001177 u8 obuf[] = {7, 1};
1178
Michael Krufky77eed212011-09-06 09:31:57 -03001179 d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001180 &d->dev->i2c_adap);
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001181
Michael Krufky77eed212011-09-06 09:31:57 -03001182 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001183 return -EIO;
1184
Michael Krufky77eed212011-09-06 09:31:57 -03001185 if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001186 return -EIO;
1187
Michael Krufky77eed212011-09-06 09:31:57 -03001188 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001189
1190 dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
1191
1192 info("Attached stv0288+stb6000!\n");
1193
1194 return 0;
1195
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001196}
1197
1198static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
1199{
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001200 struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -03001201 u8 obuf[] = {7, 1};
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001202
Igor M. Liplianin43385c82012-12-28 19:40:24 -03001203 d->fe_adap[0].fe = dvb_attach(ds3000_attach, &s660_ds3000_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001204 &d->dev->i2c_adap);
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001205
Michael Krufky77eed212011-09-06 09:31:57 -03001206 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001207 return -EIO;
1208
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001209 dvb_attach(ts2020_attach, d->fe_adap[0].fe, &dw2104_ts2020_config,
1210 &d->dev->i2c_adap);
1211
Michael Krufky77eed212011-09-06 09:31:57 -03001212 st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
1213 d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -03001214
1215 dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
1216
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001217 info("Attached ds3000+ds2020!\n");
1218
1219 return 0;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001220}
1221
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001222static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
1223{
Igor M. Liplianin4e59df82011-02-25 18:41:23 -03001224 u8 obuf[] = {7, 1};
1225
Michael Krufky77eed212011-09-06 09:31:57 -03001226 d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001227 &d->dev->i2c_adap, 0);
Michael Krufky77eed212011-09-06 09:31:57 -03001228 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001229 return -EIO;
Igor M. Liplianin4e59df82011-02-25 18:41:23 -03001230
Michael Krufky77eed212011-09-06 09:31:57 -03001231 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001232
Igor M. Liplianin4e59df82011-02-25 18:41:23 -03001233 dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
1234
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001235 info("Attached STV0900+STB6100A!\n");
1236
1237 return 0;
1238}
1239
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001240static int su3000_frontend_attach(struct dvb_usb_adapter *d)
1241{
1242 u8 obuf[3] = { 0xe, 0x80, 0 };
1243 u8 ibuf[] = { 0 };
1244
1245 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1246 err("command 0x0e transfer failed.");
1247
1248 obuf[0] = 0xe;
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001249 obuf[1] = 0x02;
1250 obuf[2] = 1;
1251
1252 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1253 err("command 0x0e transfer failed.");
1254 msleep(300);
1255
1256 obuf[0] = 0xe;
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001257 obuf[1] = 0x83;
1258 obuf[2] = 0;
1259
1260 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1261 err("command 0x0e transfer failed.");
1262
1263 obuf[0] = 0xe;
1264 obuf[1] = 0x83;
1265 obuf[2] = 1;
1266
1267 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1268 err("command 0x0e transfer failed.");
1269
1270 obuf[0] = 0x51;
1271
1272 if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
1273 err("command 0x51 transfer failed.");
1274
Michael Krufky77eed212011-09-06 09:31:57 -03001275 d->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001276 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001277 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001278 return -EIO;
1279
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001280 if (dvb_attach(ts2020_attach, d->fe_adap[0].fe,
1281 &dw2104_ts2020_config,
1282 &d->dev->i2c_adap)) {
1283 info("Attached DS3000/TS2020!\n");
1284 return 0;
1285 }
Konstantin Dimitrov73f0af42012-12-23 19:25:38 -03001286
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001287 info("Failed to attach DS3000/TS2020!\n");
1288 return -EIO;
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001289}
1290
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001291static int m88rs2000_frontend_attach(struct dvb_usb_adapter *d)
1292{
1293 u8 obuf[] = { 0x51 };
1294 u8 ibuf[] = { 0 };
1295
1296 if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
1297 err("command 0x51 transfer failed.");
1298
1299 d->fe_adap[0].fe = dvb_attach(m88rs2000_attach, &s421_m88rs2000_config,
1300 &d->dev->i2c_adap);
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001301
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001302 if (d->fe_adap[0].fe == NULL)
1303 return -EIO;
1304
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001305 if (dvb_attach(ts2020_attach, d->fe_adap[0].fe,
1306 &dw2104_ts2020_config,
1307 &d->dev->i2c_adap)) {
1308 info("Attached RS2000/TS2020!\n");
1309 return 0;
1310 }
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001311
Igor M. Liplianinb858c332012-12-28 19:40:33 -03001312 info("Failed to attach RS2000/TS2020!\n");
1313 return -EIO;
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001314}
1315
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001316static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
1317{
Michael Krufky77eed212011-09-06 09:31:57 -03001318 dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001319 &adap->dev->i2c_adap, DVB_PLL_OPERA1);
1320 return 0;
1321}
1322
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001323static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
1324{
Michael Krufky77eed212011-09-06 09:31:57 -03001325 dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001326 &adap->dev->i2c_adap, DVB_PLL_TUA6034);
1327
1328 return 0;
1329}
1330
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001331static struct rc_map_table rc_map_dw210x_table[] = {
Mauro Carvalho Chehab991bd3c2011-01-24 12:18:40 -03001332 { 0xf80a, KEY_POWER2 }, /*power*/
1333 { 0xf80c, KEY_MUTE }, /*mute*/
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001334 { 0xf811, KEY_1 },
1335 { 0xf812, KEY_2 },
1336 { 0xf813, KEY_3 },
1337 { 0xf814, KEY_4 },
1338 { 0xf815, KEY_5 },
1339 { 0xf816, KEY_6 },
1340 { 0xf817, KEY_7 },
1341 { 0xf818, KEY_8 },
1342 { 0xf819, KEY_9 },
1343 { 0xf810, KEY_0 },
Mauro Carvalho Chehab991bd3c2011-01-24 12:18:40 -03001344 { 0xf81c, KEY_CHANNELUP }, /*ch+*/
1345 { 0xf80f, KEY_CHANNELDOWN }, /*ch-*/
1346 { 0xf81a, KEY_VOLUMEUP }, /*vol+*/
1347 { 0xf80e, KEY_VOLUMEDOWN }, /*vol-*/
1348 { 0xf804, KEY_RECORD }, /*rec*/
1349 { 0xf809, KEY_FAVORITES }, /*fav*/
1350 { 0xf808, KEY_REWIND }, /*rewind*/
1351 { 0xf807, KEY_FASTFORWARD }, /*fast*/
1352 { 0xf80b, KEY_PAUSE }, /*pause*/
1353 { 0xf802, KEY_ESC }, /*cancel*/
1354 { 0xf803, KEY_TAB }, /*tab*/
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001355 { 0xf800, KEY_UP }, /*up*/
Mauro Carvalho Chehab991bd3c2011-01-24 12:18:40 -03001356 { 0xf81f, KEY_OK }, /*ok*/
1357 { 0xf801, KEY_DOWN }, /*down*/
1358 { 0xf805, KEY_CAMERA }, /*cap*/
1359 { 0xf806, KEY_STOP }, /*stop*/
1360 { 0xf840, KEY_ZOOM }, /*full*/
1361 { 0xf81e, KEY_TV }, /*tvmode*/
1362 { 0xf81b, KEY_LAST }, /*recall*/
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001363};
1364
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001365static struct rc_map_table rc_map_tevii_table[] = {
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001366 { 0xf80a, KEY_POWER },
1367 { 0xf80c, KEY_MUTE },
1368 { 0xf811, KEY_1 },
1369 { 0xf812, KEY_2 },
1370 { 0xf813, KEY_3 },
1371 { 0xf814, KEY_4 },
1372 { 0xf815, KEY_5 },
1373 { 0xf816, KEY_6 },
1374 { 0xf817, KEY_7 },
1375 { 0xf818, KEY_8 },
1376 { 0xf819, KEY_9 },
1377 { 0xf810, KEY_0 },
1378 { 0xf81c, KEY_MENU },
1379 { 0xf80f, KEY_VOLUMEDOWN },
1380 { 0xf81a, KEY_LAST },
1381 { 0xf80e, KEY_OPEN },
1382 { 0xf804, KEY_RECORD },
1383 { 0xf809, KEY_VOLUMEUP },
1384 { 0xf808, KEY_CHANNELUP },
1385 { 0xf807, KEY_PVR },
1386 { 0xf80b, KEY_TIME },
1387 { 0xf802, KEY_RIGHT },
1388 { 0xf803, KEY_LEFT },
1389 { 0xf800, KEY_UP },
1390 { 0xf81f, KEY_OK },
1391 { 0xf801, KEY_DOWN },
1392 { 0xf805, KEY_TUNER },
1393 { 0xf806, KEY_CHANNELDOWN },
1394 { 0xf840, KEY_PLAYPAUSE },
1395 { 0xf81e, KEY_REWIND },
1396 { 0xf81b, KEY_FAVORITES },
1397 { 0xf81d, KEY_BACK },
1398 { 0xf84d, KEY_FASTFORWARD },
1399 { 0xf844, KEY_EPG },
1400 { 0xf84c, KEY_INFO },
1401 { 0xf841, KEY_AB },
1402 { 0xf843, KEY_AUDIO },
1403 { 0xf845, KEY_SUBTITLE },
1404 { 0xf84a, KEY_LIST },
1405 { 0xf846, KEY_F1 },
1406 { 0xf847, KEY_F2 },
1407 { 0xf85e, KEY_F3 },
1408 { 0xf85c, KEY_F4 },
1409 { 0xf852, KEY_F5 },
1410 { 0xf85a, KEY_F6 },
1411 { 0xf856, KEY_MODE },
1412 { 0xf858, KEY_SWITCHVIDEOMODE },
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001413};
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001414
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001415static struct rc_map_table rc_map_tbs_table[] = {
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001416 { 0xf884, KEY_POWER },
1417 { 0xf894, KEY_MUTE },
1418 { 0xf887, KEY_1 },
1419 { 0xf886, KEY_2 },
1420 { 0xf885, KEY_3 },
1421 { 0xf88b, KEY_4 },
1422 { 0xf88a, KEY_5 },
1423 { 0xf889, KEY_6 },
1424 { 0xf88f, KEY_7 },
1425 { 0xf88e, KEY_8 },
1426 { 0xf88d, KEY_9 },
1427 { 0xf892, KEY_0 },
1428 { 0xf896, KEY_CHANNELUP },
1429 { 0xf891, KEY_CHANNELDOWN },
1430 { 0xf893, KEY_VOLUMEUP },
1431 { 0xf88c, KEY_VOLUMEDOWN },
1432 { 0xf883, KEY_RECORD },
1433 { 0xf898, KEY_PAUSE },
1434 { 0xf899, KEY_OK },
1435 { 0xf89a, KEY_SHUFFLE },
1436 { 0xf881, KEY_UP },
1437 { 0xf890, KEY_LEFT },
1438 { 0xf882, KEY_RIGHT },
1439 { 0xf888, KEY_DOWN },
1440 { 0xf895, KEY_FAVORITES },
1441 { 0xf897, KEY_SUBTITLE },
1442 { 0xf89d, KEY_ZOOM },
1443 { 0xf89f, KEY_EXIT },
1444 { 0xf89e, KEY_MENU },
1445 { 0xf89c, KEY_EPG },
1446 { 0xf880, KEY_PREVIOUS },
1447 { 0xf89b, KEY_MODE }
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001448};
1449
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001450static struct rc_map_table rc_map_su3000_table[] = {
1451 { 0x25, KEY_POWER }, /* right-bottom Red */
1452 { 0x0a, KEY_MUTE }, /* -/-- */
1453 { 0x01, KEY_1 },
1454 { 0x02, KEY_2 },
1455 { 0x03, KEY_3 },
1456 { 0x04, KEY_4 },
1457 { 0x05, KEY_5 },
1458 { 0x06, KEY_6 },
1459 { 0x07, KEY_7 },
1460 { 0x08, KEY_8 },
1461 { 0x09, KEY_9 },
1462 { 0x00, KEY_0 },
1463 { 0x20, KEY_UP }, /* CH+ */
1464 { 0x21, KEY_DOWN }, /* CH+ */
1465 { 0x12, KEY_VOLUMEUP }, /* Brightness Up */
1466 { 0x13, KEY_VOLUMEDOWN },/* Brightness Down */
1467 { 0x1f, KEY_RECORD },
1468 { 0x17, KEY_PLAY },
1469 { 0x16, KEY_PAUSE },
1470 { 0x0b, KEY_STOP },
1471 { 0x27, KEY_FASTFORWARD },/* >> */
1472 { 0x26, KEY_REWIND }, /* << */
1473 { 0x0d, KEY_OK }, /* Mute */
1474 { 0x11, KEY_LEFT }, /* VOL- */
1475 { 0x10, KEY_RIGHT }, /* VOL+ */
1476 { 0x29, KEY_BACK }, /* button under 9 */
1477 { 0x2c, KEY_MENU }, /* TTX */
1478 { 0x2b, KEY_EPG }, /* EPG */
1479 { 0x1e, KEY_RED }, /* OSD */
1480 { 0x0e, KEY_GREEN }, /* Window */
1481 { 0x2d, KEY_YELLOW }, /* button under << */
1482 { 0x0f, KEY_BLUE }, /* bottom yellow button */
1483 { 0x14, KEY_AUDIO }, /* Snapshot */
1484 { 0x38, KEY_TV }, /* TV/Radio */
Justin P. Mattock70f23fd2011-05-10 10:16:21 +02001485 { 0x0c, KEY_ESC } /* upper Red button */
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001486};
1487
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001488static struct rc_map_dvb_usb_table_table keys_tables[] = {
1489 { rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) },
1490 { rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) },
1491 { rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) },
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001492 { rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) },
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001493};
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001494
1495static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
1496{
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001497 struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
1498 int keymap_size = d->props.rc.legacy.rc_map_size;
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001499 u8 key[2];
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001500 struct i2c_msg msg = {
1501 .addr = DW2102_RC_QUERY,
1502 .flags = I2C_M_RD,
1503 .buf = key,
1504 .len = 2
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001505 };
1506 int i;
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001507 /* override keymap */
1508 if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) {
1509 keymap = keys_tables[ir_keymap - 1].rc_keys ;
1510 keymap_size = keys_tables[ir_keymap - 1].rc_keys_size;
Igor M. Liplianinfeb16e92011-02-25 18:41:22 -03001511 } else if (ir_keymap > ARRAY_SIZE(keys_tables))
1512 return 0; /* none */
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001513
1514 *state = REMOTE_NO_KEY_PRESSED;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001515 if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001516 for (i = 0; i < keymap_size ; i++) {
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001517 if (rc5_data(&keymap[i]) == msg.buf[0]) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001518 *state = REMOTE_KEY_PRESSED;
Mauro Carvalho Chehab34abf212010-07-31 11:24:57 -03001519 *event = keymap[i].keycode;
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001520 break;
1521 }
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001522
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001523 }
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001524
1525 if ((*state) == REMOTE_KEY_PRESSED)
1526 deb_rc("%s: found rc key: %x, %x, event: %x\n",
1527 __func__, key[0], key[1], (*event));
1528 else if (key[0] != 0xff)
1529 deb_rc("%s: unknown rc key: %x, %x\n",
1530 __func__, key[0], key[1]);
1531
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001532 }
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001533
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001534 return 0;
1535}
1536
Jonathan Nieder27351b12011-12-23 19:00:45 -03001537enum dw2102_table_entry {
1538 CYPRESS_DW2102,
1539 CYPRESS_DW2101,
1540 CYPRESS_DW2104,
1541 TEVII_S650,
1542 TERRATEC_CINERGY_S,
1543 CYPRESS_DW3101,
1544 TEVII_S630,
1545 PROF_1100,
1546 TEVII_S660,
1547 PROF_7500,
1548 GENIATECH_SU3000,
1549 TERRATEC_CINERGY_S2,
1550 TEVII_S480_1,
1551 TEVII_S480_2,
1552 X3M_SPC1400HD,
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001553 TEVII_S421,
1554 TEVII_S632,
Igor M. Liplianin44122dd2013-02-21 08:11:41 -03001555 TERRATEC_CINERGY_S2_R2,
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -03001556 GOTVIEW_SAT_HD,
Jonathan Nieder27351b12011-12-23 19:00:45 -03001557};
1558
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001559static struct usb_device_id dw2102_table[] = {
Jonathan Nieder27351b12011-12-23 19:00:45 -03001560 [CYPRESS_DW2102] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
1561 [CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
1562 [CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
1563 [TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
1564 [TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
1565 [CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
1566 [TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
1567 [PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
1568 [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
1569 [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)},
1570 [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)},
1571 [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
1572 [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
1573 [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
1574 [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)},
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001575 [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)},
1576 [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)},
Igor M. Liplianin44122dd2013-02-21 08:11:41 -03001577 [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)},
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -03001578 [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001579 { }
1580};
1581
1582MODULE_DEVICE_TABLE(usb, dw2102_table);
1583
1584static int dw2102_load_firmware(struct usb_device *dev,
1585 const struct firmware *frmwr)
1586{
1587 u8 *b, *p;
1588 int ret = 0, i;
1589 u8 reset;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001590 u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001591 const struct firmware *fw;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001592
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001593 switch (dev->descriptor.idProduct) {
1594 case 0x2101:
Rémi Cardona68236272012-09-28 08:59:32 -03001595 ret = request_firmware(&fw, DW2101_FIRMWARE, &dev->dev);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001596 if (ret != 0) {
Rémi Cardona68236272012-09-28 08:59:32 -03001597 err(err_str, DW2101_FIRMWARE);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001598 return ret;
1599 }
1600 break;
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001601 default:
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001602 fw = frmwr;
1603 break;
1604 }
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001605 info("start downloading DW210X firmware");
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001606 p = kmalloc(fw->size, GFP_KERNEL);
1607 reset = 1;
1608 /*stop the CPU*/
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001609 dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);
1610 dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001611
1612 if (p != NULL) {
1613 memcpy(p, fw->data, fw->size);
1614 for (i = 0; i < fw->size; i += 0x40) {
1615 b = (u8 *) p + i;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001616 if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,
1617 DW210X_WRITE_MSG) != 0x40) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001618 err("error while transferring firmware");
1619 ret = -EINVAL;
1620 break;
1621 }
1622 }
1623 /* restart the CPU */
1624 reset = 0;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001625 if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
1626 DW210X_WRITE_MSG) != 1) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001627 err("could not restart the USB controller CPU.");
1628 ret = -EINVAL;
1629 }
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001630 if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
1631 DW210X_WRITE_MSG) != 1) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001632 err("could not restart the USB controller CPU.");
1633 ret = -EINVAL;
1634 }
1635 /* init registers */
1636 switch (dev->descriptor.idProduct) {
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001637 case USB_PID_TEVII_S650:
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001638 dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table;
1639 dw2104_properties.rc.legacy.rc_map_size =
1640 ARRAY_SIZE(rc_map_tevii_table);
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001641 case USB_PID_DW2104:
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001642 reset = 1;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001643 dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
1644 DW210X_WRITE_MSG);
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001645 /* break omitted intentionally */
1646 case USB_PID_DW3101:
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001647 reset = 0;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001648 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
1649 DW210X_WRITE_MSG);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001650 break;
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001651 case USB_PID_CINERGY_S:
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001652 case USB_PID_DW2102:
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001653 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
1654 DW210X_WRITE_MSG);
1655 dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
1656 DW210X_READ_MSG);
1657 /* check STV0299 frontend */
1658 dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,
1659 DW210X_READ_MSG);
Igor M. Liplianinea023df2008-12-04 12:49:23 -03001660 if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001661 dw2102_properties.i2c_algo = &dw2102_i2c_algo;
Michael Krufky77eed212011-09-06 09:31:57 -03001662 dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001663 break;
1664 } else {
1665 /* check STV0288 frontend */
1666 reset16[0] = 0xd0;
1667 reset16[1] = 1;
1668 reset16[2] = 0;
1669 dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,
1670 DW210X_WRITE_MSG);
1671 dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,
1672 DW210X_READ_MSG);
1673 if (reset16[2] == 0x11) {
1674 dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001675 break;
1676 }
1677 }
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001678 case 0x2101:
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001679 dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,
1680 DW210X_READ_MSG);
1681 dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
1682 DW210X_READ_MSG);
1683 dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
1684 DW210X_READ_MSG);
1685 dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
1686 DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001687 break;
1688 }
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001689
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001690 msleep(100);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001691 kfree(p);
1692 }
1693 return ret;
1694}
1695
1696static struct dvb_usb_device_properties dw2102_properties = {
1697 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1698 .usb_ctrl = DEVICE_SPECIFIC,
Rémi Cardona68236272012-09-28 08:59:32 -03001699 .firmware = DW2102_FIRMWARE,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001700 .no_reconnect = 1,
1701
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001702 .i2c_algo = &dw2102_serit_i2c_algo,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001703
1704 .rc.legacy = {
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001705 .rc_map_table = rc_map_dw210x_table,
1706 .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001707 .rc_interval = 150,
1708 .rc_query = dw2102_rc_query,
1709 },
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001710
1711 .generic_bulk_ctrl_endpoint = 0x81,
1712 /* parameter for the MPEG2-data transfer */
1713 .num_adapters = 1,
1714 .download_firmware = dw2102_load_firmware,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001715 .read_mac_address = dw210x_read_mac_address,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001716 .adapter = {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001717 {
Michael Krufky77eed212011-09-06 09:31:57 -03001718 .num_frontends = 1,
1719 .fe = {{
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001720 .frontend_attach = dw2102_frontend_attach,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001721 .stream = {
1722 .type = USB_BULK,
1723 .count = 8,
1724 .endpoint = 0x82,
1725 .u = {
1726 .bulk = {
1727 .buffersize = 4096,
1728 }
1729 }
1730 },
Michael Krufky77eed212011-09-06 09:31:57 -03001731 }},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001732 }
1733 },
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001734 .num_device_descs = 3,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001735 .devices = {
1736 {"DVBWorld DVB-S 2102 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001737 {&dw2102_table[CYPRESS_DW2102], NULL},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001738 {NULL},
1739 },
1740 {"DVBWorld DVB-S 2101 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001741 {&dw2102_table[CYPRESS_DW2101], NULL},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001742 {NULL},
1743 },
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001744 {"TerraTec Cinergy S USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001745 {&dw2102_table[TERRATEC_CINERGY_S], NULL},
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001746 {NULL},
1747 },
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001748 }
1749};
1750
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001751static struct dvb_usb_device_properties dw2104_properties = {
1752 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1753 .usb_ctrl = DEVICE_SPECIFIC,
Rémi Cardona68236272012-09-28 08:59:32 -03001754 .firmware = DW2104_FIRMWARE,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001755 .no_reconnect = 1,
1756
1757 .i2c_algo = &dw2104_i2c_algo,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001758 .rc.legacy = {
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001759 .rc_map_table = rc_map_dw210x_table,
1760 .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001761 .rc_interval = 150,
1762 .rc_query = dw2102_rc_query,
1763 },
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001764
1765 .generic_bulk_ctrl_endpoint = 0x81,
1766 /* parameter for the MPEG2-data transfer */
1767 .num_adapters = 1,
1768 .download_firmware = dw2102_load_firmware,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001769 .read_mac_address = dw210x_read_mac_address,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001770 .adapter = {
1771 {
Michael Krufky77eed212011-09-06 09:31:57 -03001772 .num_frontends = 1,
1773 .fe = {{
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001774 .frontend_attach = dw2104_frontend_attach,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001775 .stream = {
1776 .type = USB_BULK,
1777 .count = 8,
1778 .endpoint = 0x82,
1779 .u = {
1780 .bulk = {
1781 .buffersize = 4096,
1782 }
1783 }
1784 },
Michael Krufky77eed212011-09-06 09:31:57 -03001785 }},
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001786 }
1787 },
1788 .num_device_descs = 2,
1789 .devices = {
1790 { "DVBWorld DW2104 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001791 {&dw2102_table[CYPRESS_DW2104], NULL},
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001792 {NULL},
1793 },
1794 { "TeVii S650 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001795 {&dw2102_table[TEVII_S650], NULL},
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001796 {NULL},
1797 },
1798 }
1799};
1800
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001801static struct dvb_usb_device_properties dw3101_properties = {
1802 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1803 .usb_ctrl = DEVICE_SPECIFIC,
Rémi Cardona68236272012-09-28 08:59:32 -03001804 .firmware = DW3101_FIRMWARE,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001805 .no_reconnect = 1,
1806
1807 .i2c_algo = &dw3101_i2c_algo,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001808 .rc.legacy = {
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001809 .rc_map_table = rc_map_dw210x_table,
1810 .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001811 .rc_interval = 150,
1812 .rc_query = dw2102_rc_query,
1813 },
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001814
1815 .generic_bulk_ctrl_endpoint = 0x81,
1816 /* parameter for the MPEG2-data transfer */
1817 .num_adapters = 1,
1818 .download_firmware = dw2102_load_firmware,
1819 .read_mac_address = dw210x_read_mac_address,
1820 .adapter = {
1821 {
Michael Krufky77eed212011-09-06 09:31:57 -03001822 .num_frontends = 1,
1823 .fe = {{
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001824 .frontend_attach = dw3101_frontend_attach,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001825 .tuner_attach = dw3101_tuner_attach,
1826 .stream = {
1827 .type = USB_BULK,
1828 .count = 8,
1829 .endpoint = 0x82,
1830 .u = {
1831 .bulk = {
1832 .buffersize = 4096,
1833 }
1834 }
1835 },
Michael Krufky77eed212011-09-06 09:31:57 -03001836 }},
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001837 }
1838 },
1839 .num_device_descs = 1,
1840 .devices = {
1841 { "DVBWorld DVB-C 3101 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001842 {&dw2102_table[CYPRESS_DW3101], NULL},
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001843 {NULL},
1844 },
1845 }
1846};
1847
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001848static struct dvb_usb_device_properties s6x0_properties = {
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001849 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1850 .usb_ctrl = DEVICE_SPECIFIC,
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001851 .size_of_priv = sizeof(struct s6x0_state),
Rémi Cardona68236272012-09-28 08:59:32 -03001852 .firmware = S630_FIRMWARE,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001853 .no_reconnect = 1,
1854
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001855 .i2c_algo = &s6x0_i2c_algo,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001856 .rc.legacy = {
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001857 .rc_map_table = rc_map_tevii_table,
1858 .rc_map_size = ARRAY_SIZE(rc_map_tevii_table),
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001859 .rc_interval = 150,
1860 .rc_query = dw2102_rc_query,
1861 },
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001862
1863 .generic_bulk_ctrl_endpoint = 0x81,
1864 .num_adapters = 1,
1865 .download_firmware = dw2102_load_firmware,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001866 .read_mac_address = s6x0_read_mac_address,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001867 .adapter = {
1868 {
Michael Krufky77eed212011-09-06 09:31:57 -03001869 .num_frontends = 1,
1870 .fe = {{
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001871 .frontend_attach = zl100313_frontend_attach,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001872 .stream = {
1873 .type = USB_BULK,
1874 .count = 8,
1875 .endpoint = 0x82,
1876 .u = {
1877 .bulk = {
1878 .buffersize = 4096,
1879 }
1880 }
1881 },
Michael Krufky77eed212011-09-06 09:31:57 -03001882 }},
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001883 }
1884 },
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001885 .num_device_descs = 1,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001886 .devices = {
1887 {"TeVii S630 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001888 {&dw2102_table[TEVII_S630], NULL},
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001889 {NULL},
1890 },
1891 }
1892};
1893
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001894struct dvb_usb_device_properties *p1100;
1895static struct dvb_usb_device_description d1100 = {
1896 "Prof 1100 USB ",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001897 {&dw2102_table[PROF_1100], NULL},
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001898 {NULL},
1899};
1900
1901struct dvb_usb_device_properties *s660;
1902static struct dvb_usb_device_description d660 = {
1903 "TeVii S660 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001904 {&dw2102_table[TEVII_S660], NULL},
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001905 {NULL},
1906};
1907
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001908static struct dvb_usb_device_description d480_1 = {
1909 "TeVii S480.1 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001910 {&dw2102_table[TEVII_S480_1], NULL},
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001911 {NULL},
1912};
1913
1914static struct dvb_usb_device_description d480_2 = {
1915 "TeVii S480.2 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001916 {&dw2102_table[TEVII_S480_2], NULL},
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001917 {NULL},
1918};
1919
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001920struct dvb_usb_device_properties *p7500;
1921static struct dvb_usb_device_description d7500 = {
1922 "Prof 7500 USB DVB-S2",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001923 {&dw2102_table[PROF_7500], NULL},
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001924 {NULL},
1925};
1926
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03001927struct dvb_usb_device_properties *s421;
1928static struct dvb_usb_device_description d421 = {
1929 "TeVii S421 PCI",
1930 {&dw2102_table[TEVII_S421], NULL},
1931 {NULL},
1932};
1933
1934static struct dvb_usb_device_description d632 = {
1935 "TeVii S632 USB",
1936 {&dw2102_table[TEVII_S632], NULL},
1937 {NULL},
1938};
1939
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001940static struct dvb_usb_device_properties su3000_properties = {
1941 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1942 .usb_ctrl = DEVICE_SPECIFIC,
1943 .size_of_priv = sizeof(struct su3000_state),
1944 .power_ctrl = su3000_power_ctrl,
1945 .num_adapters = 1,
1946 .identify_state = su3000_identify_state,
1947 .i2c_algo = &su3000_i2c_algo,
1948
1949 .rc.legacy = {
1950 .rc_map_table = rc_map_su3000_table,
1951 .rc_map_size = ARRAY_SIZE(rc_map_su3000_table),
1952 .rc_interval = 150,
1953 .rc_query = dw2102_rc_query,
1954 },
1955
1956 .read_mac_address = su3000_read_mac_address,
1957
1958 .generic_bulk_ctrl_endpoint = 0x01,
1959
1960 .adapter = {
1961 {
Michael Krufky77eed212011-09-06 09:31:57 -03001962 .num_frontends = 1,
1963 .fe = {{
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001964 .streaming_ctrl = su3000_streaming_ctrl,
1965 .frontend_attach = su3000_frontend_attach,
1966 .stream = {
1967 .type = USB_BULK,
1968 .count = 8,
1969 .endpoint = 0x82,
1970 .u = {
1971 .bulk = {
1972 .buffersize = 4096,
1973 }
1974 }
1975 }
Michael Krufky77eed212011-09-06 09:31:57 -03001976 }},
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001977 }
1978 },
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -03001979 .num_device_descs = 5,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001980 .devices = {
1981 { "SU3000HD DVB-S USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001982 { &dw2102_table[GENIATECH_SU3000], NULL },
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001983 { NULL },
1984 },
Igor M. Liplianin2adc5912011-02-25 18:41:22 -03001985 { "Terratec Cinergy S2 USB HD",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001986 { &dw2102_table[TERRATEC_CINERGY_S2], NULL },
Igor M. Liplianin2adc5912011-02-25 18:41:22 -03001987 { NULL },
1988 },
Igor M. Liplianin5265ea52011-02-27 16:17:25 -03001989 { "X3M TV SPC1400HD PCI",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001990 { &dw2102_table[X3M_SPC1400HD], NULL },
Igor M. Liplianin5265ea52011-02-27 16:17:25 -03001991 { NULL },
1992 },
Igor M. Liplianin44122dd2013-02-21 08:11:41 -03001993 { "Terratec Cinergy S2 USB HD Rev.2",
1994 { &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL },
1995 { NULL },
1996 },
Andrey Pavlenkof08e9f02013-03-07 09:36:22 -03001997 { "GOTVIEW Satellite HD",
1998 { &dw2102_table[GOTVIEW_SAT_HD], NULL },
1999 { NULL },
2000 },
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03002001 }
2002};
2003
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002004static int dw2102_probe(struct usb_interface *intf,
2005 const struct usb_device_id *id)
2006{
Thomas Meyer68dd9dd2011-11-17 18:43:40 -03002007 p1100 = kmemdup(&s6x0_properties,
2008 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002009 if (!p1100)
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002010 return -ENOMEM;
2011 /* copy default structure */
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002012 /* fill only different fields */
Rémi Cardona68236272012-09-28 08:59:32 -03002013 p1100->firmware = P1100_FIRMWARE;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002014 p1100->devices[0] = d1100;
2015 p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
2016 p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
Michael Krufky77eed212011-09-06 09:31:57 -03002017 p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002018
Thomas Meyer68dd9dd2011-11-17 18:43:40 -03002019 s660 = kmemdup(&s6x0_properties,
2020 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002021 if (!s660) {
2022 kfree(p1100);
2023 return -ENOMEM;
2024 }
Rémi Cardona68236272012-09-28 08:59:32 -03002025 s660->firmware = S660_FIRMWARE;
Igor M. Liplianine8f50552011-02-25 18:41:23 -03002026 s660->num_device_descs = 3;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002027 s660->devices[0] = d660;
Igor M. Liplianine8f50552011-02-25 18:41:23 -03002028 s660->devices[1] = d480_1;
2029 s660->devices[2] = d480_2;
Michael Krufky77eed212011-09-06 09:31:57 -03002030 s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002031
Thomas Meyer68dd9dd2011-11-17 18:43:40 -03002032 p7500 = kmemdup(&s6x0_properties,
2033 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002034 if (!p7500) {
2035 kfree(p1100);
2036 kfree(s660);
2037 return -ENOMEM;
2038 }
Rémi Cardona68236272012-09-28 08:59:32 -03002039 p7500->firmware = P7500_FIRMWARE;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002040 p7500->devices[0] = d7500;
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03002041 p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
2042 p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
Michael Krufky77eed212011-09-06 09:31:57 -03002043 p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002044
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03002045
2046 s421 = kmemdup(&su3000_properties,
2047 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
2048 if (!s421) {
2049 kfree(p1100);
2050 kfree(s660);
2051 kfree(p7500);
2052 return -ENOMEM;
2053 }
2054 s421->num_device_descs = 2;
2055 s421->devices[0] = d421;
2056 s421->devices[1] = d632;
2057 s421->adapter->fe[0].frontend_attach = m88rs2000_frontend_attach;
2058
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03002059 if (0 == dvb_usb_device_init(intf, &dw2102_properties,
2060 THIS_MODULE, NULL, adapter_nr) ||
2061 0 == dvb_usb_device_init(intf, &dw2104_properties,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03002062 THIS_MODULE, NULL, adapter_nr) ||
2063 0 == dvb_usb_device_init(intf, &dw3101_properties,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03002064 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianin141cc352009-11-27 14:37:35 -03002065 0 == dvb_usb_device_init(intf, &s6x0_properties,
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002066 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianin195288d2011-02-25 18:41:22 -03002067 0 == dvb_usb_device_init(intf, p1100,
2068 THIS_MODULE, NULL, adapter_nr) ||
2069 0 == dvb_usb_device_init(intf, s660,
2070 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianincd79d332009-12-14 20:24:56 -03002071 0 == dvb_usb_device_init(intf, p7500,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03002072 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03002073 0 == dvb_usb_device_init(intf, s421,
2074 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03002075 0 == dvb_usb_device_init(intf, &su3000_properties,
2076 THIS_MODULE, NULL, adapter_nr))
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03002077 return 0;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03002078
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03002079 return -ENODEV;
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002080}
2081
2082static struct usb_driver dw2102_driver = {
2083 .name = "dw2102",
2084 .probe = dw2102_probe,
2085 .disconnect = dvb_usb_device_exit,
2086 .id_table = dw2102_table,
2087};
2088
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002089module_usb_driver(dw2102_driver);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002090
2091MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03002092MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
Igor M. Liplianin955d00a2012-05-08 03:53:17 -03002093 " DVB-C 3101 USB2.0,"
2094 " TeVii S600, S630, S650, S660, S480, S421, S632"
2095 " Prof 1100, 7500 USB2.0,"
2096 " Geniatech SU3000 devices");
Igor M Liplianin7fd48282008-07-20 08:05:50 -03002097MODULE_VERSION("0.1");
2098MODULE_LICENSE("GPL");
Rémi Cardona68236272012-09-28 08:59:32 -03002099MODULE_FIRMWARE(DW2101_FIRMWARE);
2100MODULE_FIRMWARE(DW2102_FIRMWARE);
2101MODULE_FIRMWARE(DW2104_FIRMWARE);
2102MODULE_FIRMWARE(DW3101_FIRMWARE);
2103MODULE_FIRMWARE(S630_FIRMWARE);
2104MODULE_FIRMWARE(S660_FIRMWARE);
2105MODULE_FIRMWARE(P1100_FIRMWARE);
2106MODULE_FIRMWARE(P7500_FIRMWARE);