blob: 937c744217c8c2470264692b758f02ec8c1c0e20 [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,
3 * TeVii S600, S630, S650, S660, S480,
4 * Prof 1100, 7500,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03005 * Geniatech SU3000 Cards
Igor M. Liplianin2f30fb42011-02-25 18:41:23 -03006 * Copyright (C) 2008-2011 Igor M. Liplianin (liplianin@me.by)
7 *
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"
Igor M. Liplianin141cc352009-11-27 14:37:35 -030025#include "ds3000.h"
26#include "stv0900.h"
27#include "stv6110.h"
28#include "stb6100.h"
29#include "stb6100_proc.h"
Igor M Liplianin7fd48282008-07-20 08:05:50 -030030
31#ifndef USB_PID_DW2102
32#define USB_PID_DW2102 0x2102
33#endif
34
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -030035#ifndef USB_PID_DW2104
36#define USB_PID_DW2104 0x2104
37#endif
38
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -030039#ifndef USB_PID_DW3101
40#define USB_PID_DW3101 0x3101
41#endif
42
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -030043#ifndef USB_PID_CINERGY_S
44#define USB_PID_CINERGY_S 0x0064
45#endif
46
Igor M. Liplianin141cc352009-11-27 14:37:35 -030047#ifndef USB_PID_TEVII_S630
48#define USB_PID_TEVII_S630 0xd630
49#endif
50
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -030051#ifndef USB_PID_TEVII_S650
52#define USB_PID_TEVII_S650 0xd650
53#endif
54
Igor M. Liplianin141cc352009-11-27 14:37:35 -030055#ifndef USB_PID_TEVII_S660
56#define USB_PID_TEVII_S660 0xd660
57#endif
58
Igor M. Liplianine8f50552011-02-25 18:41:23 -030059#ifndef USB_PID_TEVII_S480_1
60#define USB_PID_TEVII_S480_1 0xd481
61#endif
62
63#ifndef USB_PID_TEVII_S480_2
64#define USB_PID_TEVII_S480_2 0xd482
65#endif
66
Igor M. Liplianin141cc352009-11-27 14:37:35 -030067#ifndef USB_PID_PROF_1100
68#define USB_PID_PROF_1100 0xb012
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -030069#endif
70
Igor M. Liplianin21b007b2008-09-17 19:19:19 -030071#define DW210X_READ_MSG 0
72#define DW210X_WRITE_MSG 1
Igor M Liplianin7fd48282008-07-20 08:05:50 -030073
74#define REG_1F_SYMBOLRATE_BYTE0 0x1f
75#define REG_20_SYMBOLRATE_BYTE1 0x20
76#define REG_21_SYMBOLRATE_BYTE2 0x21
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -030077/* on my own*/
Igor M Liplianin7fd48282008-07-20 08:05:50 -030078#define DW2102_VOLTAGE_CTRL (0x1800)
Igor M. Liplianind2ffc442011-02-25 18:41:22 -030079#define SU3000_STREAM_CTRL (0x1900)
Igor M Liplianin7fd48282008-07-20 08:05:50 -030080#define DW2102_RC_QUERY (0x1a00)
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -030081#define DW2102_LED_CTRL (0x1b00)
Igor M Liplianin7fd48282008-07-20 08:05:50 -030082
Rémi Cardona68236272012-09-28 08:59:32 -030083#define DW2101_FIRMWARE "dvb-usb-dw2101.fw"
84#define DW2102_FIRMWARE "dvb-usb-dw2102.fw"
85#define DW2104_FIRMWARE "dvb-usb-dw2104.fw"
86#define DW3101_FIRMWARE "dvb-usb-dw3101.fw"
87#define S630_FIRMWARE "dvb-usb-s630.fw"
88#define S660_FIRMWARE "dvb-usb-s660.fw"
89#define P1100_FIRMWARE "dvb-usb-p1100.fw"
90#define P7500_FIRMWARE "dvb-usb-p7500.fw"
91
Igor M. Liplianin141cc352009-11-27 14:37:35 -030092#define err_str "did not find the firmware file. (%s) " \
93 "Please see linux/Documentation/dvb/ for more details " \
94 "on firmware-problems."
95
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -030096struct rc_map_dvb_usb_table_table {
97 struct rc_map_table *rc_keys;
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -030098 int rc_keys_size;
Igor M Liplianin7fd48282008-07-20 08:05:50 -030099};
100
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300101struct su3000_state {
102 u8 initialized;
103};
104
Igor M. Liplianin52c506e2011-02-25 18:41:23 -0300105struct s6x0_state {
106 int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v);
107};
108
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300109/* debug */
110static int dvb_usb_dw2102_debug;
111module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -0300112MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
113 DVB_USB_DEBUG_STATUS);
114
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -0300115/* keymaps */
116static int ir_keymap;
117module_param_named(keymap, ir_keymap, int, 0644);
Igor M. Liplianinfeb16e92011-02-25 18:41:22 -0300118MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ..."
119 " 256=none");
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300120
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300121/* demod probe */
122static int demod_probe = 1;
123module_param_named(demod, demod_probe, int, 0644);
124MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 "
125 "4=stv0903+stb6100(or-able)).");
126
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300127DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
128
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300129static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300130 u16 index, u8 * data, u16 len, int flags)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300131{
132 int ret;
Florian Micklerb47b8502011-03-21 15:33:44 -0300133 u8 *u8buf;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300134 unsigned int pipe = (flags == DW210X_READ_MSG) ?
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300135 usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300136 u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300137
Florian Micklerb47b8502011-03-21 15:33:44 -0300138 u8buf = kmalloc(len, GFP_KERNEL);
139 if (!u8buf)
140 return -ENOMEM;
141
142
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300143 if (flags == DW210X_WRITE_MSG)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300144 memcpy(u8buf, data, len);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300145 ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
146 value, index , u8buf, len, 2000);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300147
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300148 if (flags == DW210X_READ_MSG)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300149 memcpy(data, u8buf, len);
Florian Micklerb47b8502011-03-21 15:33:44 -0300150
151 kfree(u8buf);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300152 return ret;
153}
154
155/* I2C */
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300156static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
157 int num)
158{
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300159 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300160 int i = 0;
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300161 u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300162 u16 value;
163
164 if (!d)
165 return -ENODEV;
166 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
167 return -EAGAIN;
168
169 switch (num) {
170 case 2:
171 /* read stv0299 register */
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300172 value = msg[0].buf[0];/* register */
173 for (i = 0; i < msg[1].len; i++) {
Hans Verkuild51dbec2012-04-20 03:30:11 -0300174 dw210x_op_rw(d->udev, 0xb5, value + i, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300175 buf6, 2, DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300176 msg[1].buf[i] = buf6[0];
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300177 }
178 break;
179 case 1:
180 switch (msg[0].addr) {
181 case 0x68:
182 /* write to stv0299 register */
183 buf6[0] = 0x2a;
184 buf6[1] = msg[0].buf[0];
185 buf6[2] = msg[0].buf[1];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300186 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300187 buf6, 3, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300188 break;
189 case 0x60:
190 if (msg[0].flags == 0) {
191 /* write to tuner pll */
192 buf6[0] = 0x2c;
193 buf6[1] = 5;
194 buf6[2] = 0xc0;
195 buf6[3] = msg[0].buf[0];
196 buf6[4] = msg[0].buf[1];
197 buf6[5] = msg[0].buf[2];
198 buf6[6] = msg[0].buf[3];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300199 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300200 buf6, 7, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300201 } else {
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300202 /* read from tuner */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300203 dw210x_op_rw(d->udev, 0xb5, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300204 buf6, 1, DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300205 msg[0].buf[0] = buf6[0];
206 }
207 break;
208 case (DW2102_RC_QUERY):
Hans Verkuild51dbec2012-04-20 03:30:11 -0300209 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300210 buf6, 2, DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300211 msg[0].buf[0] = buf6[0];
212 msg[0].buf[1] = buf6[1];
213 break;
214 case (DW2102_VOLTAGE_CTRL):
215 buf6[0] = 0x30;
216 buf6[1] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300217 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300218 buf6, 2, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300219 break;
220 }
221
222 break;
223 }
224
225 mutex_unlock(&d->i2c_mutex);
226 return num;
227}
228
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300229static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
230 struct i2c_msg msg[], int num)
231{
232 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300233 u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};
234
235 if (!d)
236 return -ENODEV;
237 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
238 return -EAGAIN;
239
240 switch (num) {
241 case 2:
242 /* read si2109 register by number */
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300243 buf6[0] = msg[0].addr << 1;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300244 buf6[1] = msg[0].len;
245 buf6[2] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300246 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300247 buf6, msg[0].len + 2, DW210X_WRITE_MSG);
248 /* read si2109 register */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300249 dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300250 buf6, msg[1].len + 2, DW210X_READ_MSG);
251 memcpy(msg[1].buf, buf6 + 2, msg[1].len);
252
253 break;
254 case 1:
255 switch (msg[0].addr) {
256 case 0x68:
257 /* write to si2109 register */
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 memcpy(buf6 + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300261 dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300262 msg[0].len + 2, DW210X_WRITE_MSG);
263 break;
264 case(DW2102_RC_QUERY):
Hans Verkuild51dbec2012-04-20 03:30:11 -0300265 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300266 buf6, 2, DW210X_READ_MSG);
267 msg[0].buf[0] = buf6[0];
268 msg[0].buf[1] = buf6[1];
269 break;
270 case(DW2102_VOLTAGE_CTRL):
271 buf6[0] = 0x30;
272 buf6[1] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300273 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300274 buf6, 2, DW210X_WRITE_MSG);
275 break;
276 }
277 break;
278 }
279
280 mutex_unlock(&d->i2c_mutex);
281 return num;
282}
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300283
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300284static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
285{
286 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300287
288 if (!d)
289 return -ENODEV;
290 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
291 return -EAGAIN;
292
293 switch (num) {
294 case 2: {
295 /* read */
296 /* first write first register number */
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300297 u8 ibuf[msg[1].len + 2], obuf[3];
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300298 obuf[0] = msg[0].addr << 1;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300299 obuf[1] = msg[0].len;
300 obuf[2] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300301 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300302 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
303 /* second read registers */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300304 dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300305 ibuf, msg[1].len + 2, DW210X_READ_MSG);
306 memcpy(msg[1].buf, ibuf + 2, msg[1].len);
307
308 break;
309 }
310 case 1:
311 switch (msg[0].addr) {
312 case 0x68: {
313 /* write to register */
314 u8 obuf[msg[0].len + 2];
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300315 obuf[0] = msg[0].addr << 1;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300316 obuf[1] = msg[0].len;
317 memcpy(obuf + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300318 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300319 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
320 break;
321 }
322 case 0x61: {
323 /* write to tuner */
324 u8 obuf[msg[0].len + 2];
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300325 obuf[0] = msg[0].addr << 1;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300326 obuf[1] = msg[0].len;
327 memcpy(obuf + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300328 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300329 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
330 break;
331 }
332 case(DW2102_RC_QUERY): {
333 u8 ibuf[2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300334 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300335 ibuf, 2, DW210X_READ_MSG);
336 memcpy(msg[0].buf, ibuf , 2);
337 break;
338 }
339 case(DW2102_VOLTAGE_CTRL): {
340 u8 obuf[2];
341 obuf[0] = 0x30;
342 obuf[1] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300343 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300344 obuf, 2, DW210X_WRITE_MSG);
345 break;
346 }
347 }
348
349 break;
350 }
351
352 mutex_unlock(&d->i2c_mutex);
353 return num;
354}
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300355
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300356static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
357{
358 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300359 int len, i, j;
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300360
361 if (!d)
362 return -ENODEV;
363 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
364 return -EAGAIN;
365
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300366 for (j = 0; j < num; j++) {
367 switch (msg[j].addr) {
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300368 case(DW2102_RC_QUERY): {
369 u8 ibuf[2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300370 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300371 ibuf, 2, DW210X_READ_MSG);
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300372 memcpy(msg[j].buf, ibuf , 2);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300373 break;
374 }
375 case(DW2102_VOLTAGE_CTRL): {
376 u8 obuf[2];
377 obuf[0] = 0x30;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300378 obuf[1] = msg[j].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300379 dw210x_op_rw(d->udev, 0xb2, 0, 0,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300380 obuf, 2, DW210X_WRITE_MSG);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300381 break;
382 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300383 /*case 0x55: cx24116
384 case 0x6a: stv0903
385 case 0x68: ds3000, stv0903
386 case 0x60: ts2020, stv6110, stb6100 */
387 default: {
388 if (msg[j].flags == I2C_M_RD) {
389 /* read registers */
390 u8 ibuf[msg[j].len + 2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300391 dw210x_op_rw(d->udev, 0xc3,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300392 (msg[j].addr << 1) + 1, 0,
393 ibuf, msg[j].len + 2,
394 DW210X_READ_MSG);
395 memcpy(msg[j].buf, ibuf + 2, msg[j].len);
396 mdelay(10);
397 } else if (((msg[j].buf[0] == 0xb0) &&
398 (msg[j].addr == 0x68)) ||
399 ((msg[j].buf[0] == 0xf7) &&
400 (msg[j].addr == 0x55))) {
401 /* write firmware */
402 u8 obuf[19];
403 obuf[0] = msg[j].addr << 1;
404 obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len);
405 obuf[2] = msg[j].buf[0];
406 len = msg[j].len - 1;
407 i = 1;
408 do {
409 memcpy(obuf + 3, msg[j].buf + i,
410 (len > 16 ? 16 : len));
Hans Verkuild51dbec2012-04-20 03:30:11 -0300411 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300412 obuf, (len > 16 ? 16 : len) + 3,
413 DW210X_WRITE_MSG);
414 i += 16;
415 len -= 16;
416 } while (len > 0);
417 } else {
418 /* write registers */
419 u8 obuf[msg[j].len + 2];
420 obuf[0] = msg[j].addr << 1;
421 obuf[1] = msg[j].len;
422 memcpy(obuf + 2, msg[j].buf, msg[j].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300423 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300424 obuf, msg[j].len + 2,
425 DW210X_WRITE_MSG);
426 }
427 break;
428 }
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300429 }
430
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300431 }
432
433 mutex_unlock(&d->i2c_mutex);
434 return num;
435}
436
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300437static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
438 int num)
439{
440 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300441 int i;
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300442
443 if (!d)
444 return -ENODEV;
445 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
446 return -EAGAIN;
447
448 switch (num) {
449 case 2: {
450 /* read */
451 /* first write first register number */
452 u8 ibuf[msg[1].len + 2], obuf[3];
453 obuf[0] = msg[0].addr << 1;
454 obuf[1] = msg[0].len;
455 obuf[2] = msg[0].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300456 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300457 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
458 /* second read registers */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300459 dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300460 ibuf, msg[1].len + 2, DW210X_READ_MSG);
461 memcpy(msg[1].buf, ibuf + 2, msg[1].len);
462
463 break;
464 }
465 case 1:
466 switch (msg[0].addr) {
467 case 0x60:
468 case 0x0c: {
469 /* write to register */
470 u8 obuf[msg[0].len + 2];
471 obuf[0] = msg[0].addr << 1;
472 obuf[1] = msg[0].len;
473 memcpy(obuf + 2, msg[0].buf, msg[0].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300474 dw210x_op_rw(d->udev, 0xc2, 0, 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300475 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
476 break;
477 }
478 case(DW2102_RC_QUERY): {
479 u8 ibuf[2];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300480 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300481 ibuf, 2, DW210X_READ_MSG);
482 memcpy(msg[0].buf, ibuf , 2);
483 break;
484 }
485 }
486
487 break;
488 }
489
490 for (i = 0; i < num; i++) {
491 deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
492 msg[i].flags == 0 ? ">>>" : "<<<");
493 debug_dump(msg[i].buf, msg[i].len, deb_xfer);
494 }
495
496 mutex_unlock(&d->i2c_mutex);
497 return num;
498}
499
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300500static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300501 int num)
502{
503 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Julia Lawall21ead032009-12-22 18:00:07 -0300504 struct usb_device *udev;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300505 int len, i, j;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300506
507 if (!d)
508 return -ENODEV;
Julia Lawall21ead032009-12-22 18:00:07 -0300509 udev = d->udev;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300510 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
511 return -EAGAIN;
512
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300513 for (j = 0; j < num; j++) {
514 switch (msg[j].addr) {
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300515 case (DW2102_RC_QUERY): {
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -0300516 u8 ibuf[5];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300517 dw210x_op_rw(d->udev, 0xb8, 0, 0,
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -0300518 ibuf, 5, DW210X_READ_MSG);
519 memcpy(msg[j].buf, ibuf + 3, 2);
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300520 break;
521 }
522 case (DW2102_VOLTAGE_CTRL): {
523 u8 obuf[2];
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300524
525 obuf[0] = 1;
526 obuf[1] = msg[j].buf[1];/* off-on */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300527 dw210x_op_rw(d->udev, 0x8a, 0, 0,
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300528 obuf, 2, DW210X_WRITE_MSG);
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300529 obuf[0] = 3;
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300530 obuf[1] = msg[j].buf[0];/* 13v-18v */
Hans Verkuild51dbec2012-04-20 03:30:11 -0300531 dw210x_op_rw(d->udev, 0x8a, 0, 0,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300532 obuf, 2, DW210X_WRITE_MSG);
533 break;
534 }
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300535 case (DW2102_LED_CTRL): {
536 u8 obuf[2];
537
538 obuf[0] = 5;
539 obuf[1] = msg[j].buf[0];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300540 dw210x_op_rw(d->udev, 0x8a, 0, 0,
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300541 obuf, 2, DW210X_WRITE_MSG);
542 break;
543 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300544 /*case 0x55: cx24116
545 case 0x6a: stv0903
546 case 0x68: ds3000, stv0903
547 case 0x60: ts2020, stv6110, stb6100
548 case 0xa0: eeprom */
549 default: {
550 if (msg[j].flags == I2C_M_RD) {
551 /* read registers */
552 u8 ibuf[msg[j].len];
Hans Verkuild51dbec2012-04-20 03:30:11 -0300553 dw210x_op_rw(d->udev, 0x91, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300554 ibuf, msg[j].len,
555 DW210X_READ_MSG);
556 memcpy(msg[j].buf, ibuf, msg[j].len);
557 break;
558 } else if ((msg[j].buf[0] == 0xb0) &&
559 (msg[j].addr == 0x68)) {
560 /* write firmware */
561 u8 obuf[19];
562 obuf[0] = (msg[j].len > 16 ?
563 18 : msg[j].len + 1);
564 obuf[1] = msg[j].addr << 1;
565 obuf[2] = msg[j].buf[0];
566 len = msg[j].len - 1;
567 i = 1;
568 do {
569 memcpy(obuf + 3, msg[j].buf + i,
570 (len > 16 ? 16 : len));
Hans Verkuild51dbec2012-04-20 03:30:11 -0300571 dw210x_op_rw(d->udev, 0x80, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300572 obuf, (len > 16 ? 16 : len) + 3,
573 DW210X_WRITE_MSG);
574 i += 16;
575 len -= 16;
576 } while (len > 0);
Igor M. Liplianina84adf42011-02-27 16:18:38 -0300577 } else if (j < (num - 1)) {
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300578 /* write register addr before read */
579 u8 obuf[msg[j].len + 2];
580 obuf[0] = msg[j + 1].len;
581 obuf[1] = (msg[j].addr << 1);
582 memcpy(obuf + 2, msg[j].buf, msg[j].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300583 dw210x_op_rw(d->udev,
Igor M. Liplianina84adf42011-02-27 16:18:38 -0300584 udev->descriptor.idProduct ==
585 0x7500 ? 0x92 : 0x90, 0, 0,
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300586 obuf, msg[j].len + 2,
587 DW210X_WRITE_MSG);
588 break;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300589 } else {
590 /* write registers */
591 u8 obuf[msg[j].len + 2];
592 obuf[0] = msg[j].len + 1;
593 obuf[1] = (msg[j].addr << 1);
594 memcpy(obuf + 2, msg[j].buf, msg[j].len);
Hans Verkuild51dbec2012-04-20 03:30:11 -0300595 dw210x_op_rw(d->udev, 0x80, 0, 0,
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300596 obuf, msg[j].len + 2,
597 DW210X_WRITE_MSG);
598 break;
599 }
600 break;
601 }
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300602 }
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300603 }
604
605 mutex_unlock(&d->i2c_mutex);
606 return num;
607}
608
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300609static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
610 int num)
611{
612 struct dvb_usb_device *d = i2c_get_adapdata(adap);
613 u8 obuf[0x40], ibuf[0x40];
614
615 if (!d)
616 return -ENODEV;
617 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
618 return -EAGAIN;
619
620 switch (num) {
621 case 1:
622 switch (msg[0].addr) {
623 case SU3000_STREAM_CTRL:
624 obuf[0] = msg[0].buf[0] + 0x36;
625 obuf[1] = 3;
626 obuf[2] = 0;
627 if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0)
628 err("i2c transfer failed.");
629 break;
630 case DW2102_RC_QUERY:
631 obuf[0] = 0x10;
632 if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0)
633 err("i2c transfer failed.");
634 msg[0].buf[1] = ibuf[0];
635 msg[0].buf[0] = ibuf[1];
636 break;
637 default:
638 /* always i2c write*/
639 obuf[0] = 0x08;
640 obuf[1] = msg[0].addr;
641 obuf[2] = msg[0].len;
642
643 memcpy(&obuf[3], msg[0].buf, msg[0].len);
644
645 if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3,
646 ibuf, 1, 0) < 0)
647 err("i2c transfer failed.");
648
649 }
650 break;
651 case 2:
652 /* always i2c read */
653 obuf[0] = 0x09;
654 obuf[1] = msg[0].len;
655 obuf[2] = msg[1].len;
656 obuf[3] = msg[0].addr;
657 memcpy(&obuf[4], msg[0].buf, msg[0].len);
658
659 if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4,
660 ibuf, msg[1].len + 1, 0) < 0)
661 err("i2c transfer failed.");
662
663 memcpy(msg[1].buf, &ibuf[1], msg[1].len);
664 break;
665 default:
666 warn("more than 2 i2c messages at a time is not handled yet.");
667 break;
668 }
669 mutex_unlock(&d->i2c_mutex);
670 return num;
671}
672
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300673static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300674{
675 return I2C_FUNC_I2C;
676}
677
678static struct i2c_algorithm dw2102_i2c_algo = {
679 .master_xfer = dw2102_i2c_transfer,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300680 .functionality = dw210x_i2c_func,
681};
682
683static struct i2c_algorithm dw2102_serit_i2c_algo = {
684 .master_xfer = dw2102_serit_i2c_transfer,
685 .functionality = dw210x_i2c_func,
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300686};
687
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -0300688static struct i2c_algorithm dw2102_earda_i2c_algo = {
689 .master_xfer = dw2102_earda_i2c_transfer,
690 .functionality = dw210x_i2c_func,
691};
692
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300693static struct i2c_algorithm dw2104_i2c_algo = {
694 .master_xfer = dw2104_i2c_transfer,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300695 .functionality = dw210x_i2c_func,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300696};
697
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300698static struct i2c_algorithm dw3101_i2c_algo = {
699 .master_xfer = dw3101_i2c_transfer,
700 .functionality = dw210x_i2c_func,
701};
702
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300703static struct i2c_algorithm s6x0_i2c_algo = {
704 .master_xfer = s6x0_i2c_transfer,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300705 .functionality = dw210x_i2c_func,
706};
707
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300708static struct i2c_algorithm su3000_i2c_algo = {
709 .master_xfer = su3000_i2c_transfer,
710 .functionality = dw210x_i2c_func,
711};
712
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300713static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300714{
715 int i;
716 u8 ibuf[] = {0, 0};
717 u8 eeprom[256], eepromline[16];
718
719 for (i = 0; i < 256; i++) {
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300720 if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300721 err("read eeprom failed.");
722 return -1;
723 } else {
724 eepromline[i%16] = ibuf[0];
725 eeprom[i] = ibuf[0];
726 }
727 if ((i % 16) == 15) {
728 deb_xfer("%02x: ", i - 15);
729 debug_dump(eepromline, 16, deb_xfer);
730 }
731 }
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300732
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300733 memcpy(mac, eeprom + 8, 6);
734 return 0;
735};
736
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300737static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300738{
739 int i, ret;
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300740 u8 ibuf[] = { 0 }, obuf[] = { 0 };
741 u8 eeprom[256], eepromline[16];
742 struct i2c_msg msg[] = {
743 {
744 .addr = 0xa0 >> 1,
745 .flags = 0,
746 .buf = obuf,
747 .len = 1,
748 }, {
749 .addr = 0xa0 >> 1,
750 .flags = I2C_M_RD,
751 .buf = ibuf,
752 .len = 1,
753 }
754 };
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300755
756 for (i = 0; i < 256; i++) {
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300757 obuf[0] = i;
758 ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2);
759 if (ret != 2) {
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300760 err("read eeprom failed.");
761 return -1;
762 } else {
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300763 eepromline[i % 16] = ibuf[0];
764 eeprom[i] = ibuf[0];
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300765 }
766
767 if ((i % 16) == 15) {
768 deb_xfer("%02x: ", i - 15);
769 debug_dump(eepromline, 16, deb_xfer);
770 }
771 }
772
773 memcpy(mac, eeprom + 16, 6);
774 return 0;
775};
776
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300777static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
778{
779 static u8 command_start[] = {0x00};
780 static u8 command_stop[] = {0x01};
781 struct i2c_msg msg = {
782 .addr = SU3000_STREAM_CTRL,
783 .flags = 0,
784 .buf = onoff ? command_start : command_stop,
785 .len = 1
786 };
787
788 i2c_transfer(&adap->dev->i2c_adap, &msg, 1);
789
790 return 0;
791}
792
793static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
794{
795 struct su3000_state *state = (struct su3000_state *)d->priv;
796 u8 obuf[] = {0xde, 0};
797
798 info("%s: %d, initialized %d\n", __func__, i, state->initialized);
799
800 if (i && !state->initialized) {
801 state->initialized = 1;
802 /* reset board */
803 dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
804 }
805
806 return 0;
807}
808
809static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
810{
811 int i;
812 u8 obuf[] = { 0x1f, 0xf0 };
813 u8 ibuf[] = { 0 };
814 struct i2c_msg msg[] = {
815 {
816 .addr = 0x51,
817 .flags = 0,
818 .buf = obuf,
819 .len = 2,
820 }, {
821 .addr = 0x51,
822 .flags = I2C_M_RD,
823 .buf = ibuf,
824 .len = 1,
825
826 }
827 };
828
829 for (i = 0; i < 6; i++) {
830 obuf[1] = 0xf0 + i;
831 if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
832 break;
833 else
834 mac[i] = ibuf[0];
835
836 debug_dump(mac, 6, printk);
837 }
838
839 return 0;
840}
841
842static int su3000_identify_state(struct usb_device *udev,
843 struct dvb_usb_device_properties *props,
844 struct dvb_usb_device_description **desc,
845 int *cold)
846{
847 info("%s\n", __func__);
848
849 *cold = 0;
850 return 0;
851}
852
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300853static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300854{
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300855 static u8 command_13v[] = {0x00, 0x01};
856 static u8 command_18v[] = {0x01, 0x01};
857 static u8 command_off[] = {0x00, 0x00};
858 struct i2c_msg msg = {
859 .addr = DW2102_VOLTAGE_CTRL,
860 .flags = 0,
861 .buf = command_off,
862 .len = 2,
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300863 };
864
865 struct dvb_usb_adapter *udev_adap =
866 (struct dvb_usb_adapter *)(fe->dvb->priv);
867 if (voltage == SEC_VOLTAGE_18)
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300868 msg.buf = command_18v;
869 else if (voltage == SEC_VOLTAGE_13)
870 msg.buf = command_13v;
871
872 i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
873
Igor M Liplianin7fd48282008-07-20 08:05:50 -0300874 return 0;
875}
876
Igor M. Liplianin52c506e2011-02-25 18:41:23 -0300877static int s660_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
878{
879 struct dvb_usb_adapter *d =
880 (struct dvb_usb_adapter *)(fe->dvb->priv);
881 struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
882
883 dw210x_set_voltage(fe, voltage);
884 if (st->old_set_voltage)
885 st->old_set_voltage(fe, voltage);
886
887 return 0;
888}
889
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300890static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
891{
892 static u8 led_off[] = { 0 };
893 static u8 led_on[] = { 1 };
894 struct i2c_msg msg = {
895 .addr = DW2102_LED_CTRL,
896 .flags = 0,
897 .buf = led_off,
898 .len = 1
899 };
900 struct dvb_usb_adapter *udev_adap =
901 (struct dvb_usb_adapter *)(fe->dvb->priv);
902
903 if (offon)
904 msg.buf = led_on;
905 i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
906}
907
Igor M. Liplianind4305c62008-10-17 13:45:55 -0300908static struct stv0299_config sharp_z0194a_config = {
909 .demod_address = 0x68,
910 .inittab = sharp_z0194a_inittab,
911 .mclk = 88000000UL,
912 .invert = 1,
913 .skip_reinit = 0,
914 .lock_output = STV0299_LOCKOUTPUT_1,
915 .volt13_op0_op1 = STV0299_VOLT13_OP1,
916 .min_delay_ms = 100,
917 .set_symbol_rate = sharp_z0194a_set_symbol_rate,
918};
919
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300920static struct cx24116_config dw2104_config = {
921 .demod_address = 0x55,
Igor M. Liplianincc8c4f32008-09-09 13:57:47 -0300922 .mpg_clk_pos_pol = 0x01,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300923};
924
Igor M. Liplianin21b007b2008-09-17 19:19:19 -0300925static struct si21xx_config serit_sp1511lhb_config = {
926 .demod_address = 0x68,
927 .min_delay_ms = 100,
928
929};
930
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -0300931static struct tda10023_config dw3101_tda10023_config = {
932 .demod_address = 0x0c,
933 .invert = 1,
934};
935
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -0300936static struct mt312_config zl313_config = {
937 .demod_address = 0x0e,
938};
939
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300940static struct ds3000_config dw2104_ds3000_config = {
941 .demod_address = 0x68,
942};
943
944static struct stv0900_config dw2104a_stv0900_config = {
945 .demod_address = 0x6a,
946 .demod_mode = 0,
947 .xtal = 27000000,
948 .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
949 .diseqc_mode = 2,/* 2/3 PWM */
950 .tun1_maddress = 0,/* 0x60 */
951 .tun1_adc = 0,/* 2 Vpp */
952 .path1_mode = 3,
953};
954
955static struct stb6100_config dw2104a_stb6100_config = {
956 .tuner_address = 0x60,
957 .refclock = 27000000,
958};
959
960static struct stv0900_config dw2104_stv0900_config = {
961 .demod_address = 0x68,
962 .demod_mode = 0,
963 .xtal = 8000000,
964 .clkmode = 3,
965 .diseqc_mode = 2,
966 .tun1_maddress = 0,
967 .tun1_adc = 1,/* 1 Vpp */
968 .path1_mode = 3,
969};
970
971static struct stv6110_config dw2104_stv6110_config = {
972 .i2c_address = 0x60,
973 .mclk = 16000000,
974 .clk_div = 1,
975};
976
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300977static struct stv0900_config prof_7500_stv0900_config = {
978 .demod_address = 0x6a,
979 .demod_mode = 0,
980 .xtal = 27000000,
981 .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
982 .diseqc_mode = 2,/* 2/3 PWM */
983 .tun1_maddress = 0,/* 0x60 */
984 .tun1_adc = 0,/* 2 Vpp */
985 .path1_mode = 3,
986 .tun1_type = 3,
Igor M. Liplianinfa8bae12011-02-25 18:41:22 -0300987 .set_lock_led = dw210x_led_ctrl,
Igor M. Liplianincd79d332009-12-14 20:24:56 -0300988};
989
Igor M. Liplianind2ffc442011-02-25 18:41:22 -0300990static struct ds3000_config su3000_ds3000_config = {
991 .demod_address = 0x68,
992 .ci_mode = 1,
993};
994
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -0300995static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
996{
Igor M. Liplianin141cc352009-11-27 14:37:35 -0300997 struct dvb_tuner_ops *tuner_ops = NULL;
998
999 if (demod_probe & 4) {
Michael Krufky77eed212011-09-06 09:31:57 -03001000 d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001001 &d->dev->i2c_adap, 0);
Michael Krufky77eed212011-09-06 09:31:57 -03001002 if (d->fe_adap[0].fe != NULL) {
1003 if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001004 &dw2104a_stb6100_config,
1005 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001006 tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001007 tuner_ops->set_frequency = stb6100_set_freq;
1008 tuner_ops->get_frequency = stb6100_get_freq;
1009 tuner_ops->set_bandwidth = stb6100_set_bandw;
1010 tuner_ops->get_bandwidth = stb6100_get_bandw;
Michael Krufky77eed212011-09-06 09:31:57 -03001011 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001012 info("Attached STV0900+STB6100!\n");
1013 return 0;
1014 }
1015 }
1016 }
1017
1018 if (demod_probe & 2) {
Michael Krufky77eed212011-09-06 09:31:57 -03001019 d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001020 &d->dev->i2c_adap, 0);
Michael Krufky77eed212011-09-06 09:31:57 -03001021 if (d->fe_adap[0].fe != NULL) {
1022 if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001023 &dw2104_stv6110_config,
1024 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001025 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001026 info("Attached STV0900+STV6110A!\n");
1027 return 0;
1028 }
1029 }
1030 }
1031
1032 if (demod_probe & 1) {
Michael Krufky77eed212011-09-06 09:31:57 -03001033 d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001034 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001035 if (d->fe_adap[0].fe != NULL) {
1036 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001037 info("Attached cx24116!\n");
1038 return 0;
1039 }
1040 }
1041
Michael Krufky77eed212011-09-06 09:31:57 -03001042 d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001043 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001044 if (d->fe_adap[0].fe != NULL) {
1045 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001046 info("Attached DS3000!\n");
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001047 return 0;
1048 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001049
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001050 return -EIO;
1051}
1052
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001053static struct dvb_usb_device_properties dw2102_properties;
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001054static struct dvb_usb_device_properties dw2104_properties;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001055static struct dvb_usb_device_properties s6x0_properties;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001056
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001057static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
1058{
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001059 if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
1060 /*dw2102_properties.adapter->tuner_attach = NULL;*/
Michael Krufky77eed212011-09-06 09:31:57 -03001061 d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001062 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001063 if (d->fe_adap[0].fe != NULL) {
1064 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001065 info("Attached si21xx!\n");
1066 return 0;
1067 }
1068 }
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001069
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001070 if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
Michael Krufky77eed212011-09-06 09:31:57 -03001071 d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001072 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001073 if (d->fe_adap[0].fe != NULL) {
1074 if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001075 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001076 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001077 info("Attached stv0288!\n");
1078 return 0;
1079 }
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001080 }
1081 }
1082
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001083 if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
1084 /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
Michael Krufky77eed212011-09-06 09:31:57 -03001085 d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001086 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001087 if (d->fe_adap[0].fe != NULL) {
1088 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001089 info("Attached stv0299!\n");
1090 return 0;
1091 }
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001092 }
1093 return -EIO;
1094}
1095
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001096static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
1097{
Michael Krufky77eed212011-09-06 09:31:57 -03001098 d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001099 &d->dev->i2c_adap, 0x48);
Michael Krufky77eed212011-09-06 09:31:57 -03001100 if (d->fe_adap[0].fe != NULL) {
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001101 info("Attached tda10023!\n");
1102 return 0;
1103 }
1104 return -EIO;
1105}
1106
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001107static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001108{
Michael Krufky77eed212011-09-06 09:31:57 -03001109 d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001110 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001111 if (d->fe_adap[0].fe != NULL) {
1112 if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001113 &d->dev->i2c_adap)) {
Michael Krufky77eed212011-09-06 09:31:57 -03001114 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001115 info("Attached zl100313+zl10039!\n");
1116 return 0;
1117 }
1118 }
1119
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001120 return -EIO;
1121}
1122
1123static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
1124{
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001125 u8 obuf[] = {7, 1};
1126
Michael Krufky77eed212011-09-06 09:31:57 -03001127 d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001128 &d->dev->i2c_adap);
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001129
Michael Krufky77eed212011-09-06 09:31:57 -03001130 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001131 return -EIO;
1132
Michael Krufky77eed212011-09-06 09:31:57 -03001133 if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001134 return -EIO;
1135
Michael Krufky77eed212011-09-06 09:31:57 -03001136 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianinfd5466d2011-02-27 16:22:52 -03001137
1138 dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
1139
1140 info("Attached stv0288+stb6000!\n");
1141
1142 return 0;
1143
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001144}
1145
1146static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
1147{
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001148 struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -03001149 u8 obuf[] = {7, 1};
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001150
Michael Krufky77eed212011-09-06 09:31:57 -03001151 d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001152 &d->dev->i2c_adap);
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001153
Michael Krufky77eed212011-09-06 09:31:57 -03001154 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001155 return -EIO;
1156
Michael Krufky77eed212011-09-06 09:31:57 -03001157 st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
1158 d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
Igor M. Liplianin5a530cb2011-02-25 18:41:23 -03001159
1160 dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
1161
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001162 info("Attached ds3000+ds2020!\n");
1163
1164 return 0;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001165}
1166
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001167static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
1168{
Igor M. Liplianin4e59df82011-02-25 18:41:23 -03001169 u8 obuf[] = {7, 1};
1170
Michael Krufky77eed212011-09-06 09:31:57 -03001171 d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001172 &d->dev->i2c_adap, 0);
Michael Krufky77eed212011-09-06 09:31:57 -03001173 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001174 return -EIO;
Igor M. Liplianin4e59df82011-02-25 18:41:23 -03001175
Michael Krufky77eed212011-09-06 09:31:57 -03001176 d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001177
Igor M. Liplianin4e59df82011-02-25 18:41:23 -03001178 dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
1179
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001180 info("Attached STV0900+STB6100A!\n");
1181
1182 return 0;
1183}
1184
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001185static int su3000_frontend_attach(struct dvb_usb_adapter *d)
1186{
1187 u8 obuf[3] = { 0xe, 0x80, 0 };
1188 u8 ibuf[] = { 0 };
1189
1190 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1191 err("command 0x0e transfer failed.");
1192
1193 obuf[0] = 0xe;
1194 obuf[1] = 0x83;
1195 obuf[2] = 0;
1196
1197 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1198 err("command 0x0e transfer failed.");
1199
1200 obuf[0] = 0xe;
1201 obuf[1] = 0x83;
1202 obuf[2] = 1;
1203
1204 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1205 err("command 0x0e transfer failed.");
1206
1207 obuf[0] = 0x51;
1208
1209 if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
1210 err("command 0x51 transfer failed.");
1211
Michael Krufky77eed212011-09-06 09:31:57 -03001212 d->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001213 &d->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -03001214 if (d->fe_adap[0].fe == NULL)
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001215 return -EIO;
1216
1217 info("Attached DS3000!\n");
1218
1219 return 0;
1220}
1221
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001222static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
1223{
Michael Krufky77eed212011-09-06 09:31:57 -03001224 dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001225 &adap->dev->i2c_adap, DVB_PLL_OPERA1);
1226 return 0;
1227}
1228
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001229static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
1230{
Michael Krufky77eed212011-09-06 09:31:57 -03001231 dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001232 &adap->dev->i2c_adap, DVB_PLL_TUA6034);
1233
1234 return 0;
1235}
1236
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001237static struct rc_map_table rc_map_dw210x_table[] = {
Mauro Carvalho Chehab991bd3c2011-01-24 12:18:40 -03001238 { 0xf80a, KEY_POWER2 }, /*power*/
1239 { 0xf80c, KEY_MUTE }, /*mute*/
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001240 { 0xf811, KEY_1 },
1241 { 0xf812, KEY_2 },
1242 { 0xf813, KEY_3 },
1243 { 0xf814, KEY_4 },
1244 { 0xf815, KEY_5 },
1245 { 0xf816, KEY_6 },
1246 { 0xf817, KEY_7 },
1247 { 0xf818, KEY_8 },
1248 { 0xf819, KEY_9 },
1249 { 0xf810, KEY_0 },
Mauro Carvalho Chehab991bd3c2011-01-24 12:18:40 -03001250 { 0xf81c, KEY_CHANNELUP }, /*ch+*/
1251 { 0xf80f, KEY_CHANNELDOWN }, /*ch-*/
1252 { 0xf81a, KEY_VOLUMEUP }, /*vol+*/
1253 { 0xf80e, KEY_VOLUMEDOWN }, /*vol-*/
1254 { 0xf804, KEY_RECORD }, /*rec*/
1255 { 0xf809, KEY_FAVORITES }, /*fav*/
1256 { 0xf808, KEY_REWIND }, /*rewind*/
1257 { 0xf807, KEY_FASTFORWARD }, /*fast*/
1258 { 0xf80b, KEY_PAUSE }, /*pause*/
1259 { 0xf802, KEY_ESC }, /*cancel*/
1260 { 0xf803, KEY_TAB }, /*tab*/
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001261 { 0xf800, KEY_UP }, /*up*/
Mauro Carvalho Chehab991bd3c2011-01-24 12:18:40 -03001262 { 0xf81f, KEY_OK }, /*ok*/
1263 { 0xf801, KEY_DOWN }, /*down*/
1264 { 0xf805, KEY_CAMERA }, /*cap*/
1265 { 0xf806, KEY_STOP }, /*stop*/
1266 { 0xf840, KEY_ZOOM }, /*full*/
1267 { 0xf81e, KEY_TV }, /*tvmode*/
1268 { 0xf81b, KEY_LAST }, /*recall*/
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001269};
1270
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001271static struct rc_map_table rc_map_tevii_table[] = {
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001272 { 0xf80a, KEY_POWER },
1273 { 0xf80c, KEY_MUTE },
1274 { 0xf811, KEY_1 },
1275 { 0xf812, KEY_2 },
1276 { 0xf813, KEY_3 },
1277 { 0xf814, KEY_4 },
1278 { 0xf815, KEY_5 },
1279 { 0xf816, KEY_6 },
1280 { 0xf817, KEY_7 },
1281 { 0xf818, KEY_8 },
1282 { 0xf819, KEY_9 },
1283 { 0xf810, KEY_0 },
1284 { 0xf81c, KEY_MENU },
1285 { 0xf80f, KEY_VOLUMEDOWN },
1286 { 0xf81a, KEY_LAST },
1287 { 0xf80e, KEY_OPEN },
1288 { 0xf804, KEY_RECORD },
1289 { 0xf809, KEY_VOLUMEUP },
1290 { 0xf808, KEY_CHANNELUP },
1291 { 0xf807, KEY_PVR },
1292 { 0xf80b, KEY_TIME },
1293 { 0xf802, KEY_RIGHT },
1294 { 0xf803, KEY_LEFT },
1295 { 0xf800, KEY_UP },
1296 { 0xf81f, KEY_OK },
1297 { 0xf801, KEY_DOWN },
1298 { 0xf805, KEY_TUNER },
1299 { 0xf806, KEY_CHANNELDOWN },
1300 { 0xf840, KEY_PLAYPAUSE },
1301 { 0xf81e, KEY_REWIND },
1302 { 0xf81b, KEY_FAVORITES },
1303 { 0xf81d, KEY_BACK },
1304 { 0xf84d, KEY_FASTFORWARD },
1305 { 0xf844, KEY_EPG },
1306 { 0xf84c, KEY_INFO },
1307 { 0xf841, KEY_AB },
1308 { 0xf843, KEY_AUDIO },
1309 { 0xf845, KEY_SUBTITLE },
1310 { 0xf84a, KEY_LIST },
1311 { 0xf846, KEY_F1 },
1312 { 0xf847, KEY_F2 },
1313 { 0xf85e, KEY_F3 },
1314 { 0xf85c, KEY_F4 },
1315 { 0xf852, KEY_F5 },
1316 { 0xf85a, KEY_F6 },
1317 { 0xf856, KEY_MODE },
1318 { 0xf858, KEY_SWITCHVIDEOMODE },
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001319};
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001320
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001321static struct rc_map_table rc_map_tbs_table[] = {
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001322 { 0xf884, KEY_POWER },
1323 { 0xf894, KEY_MUTE },
1324 { 0xf887, KEY_1 },
1325 { 0xf886, KEY_2 },
1326 { 0xf885, KEY_3 },
1327 { 0xf88b, KEY_4 },
1328 { 0xf88a, KEY_5 },
1329 { 0xf889, KEY_6 },
1330 { 0xf88f, KEY_7 },
1331 { 0xf88e, KEY_8 },
1332 { 0xf88d, KEY_9 },
1333 { 0xf892, KEY_0 },
1334 { 0xf896, KEY_CHANNELUP },
1335 { 0xf891, KEY_CHANNELDOWN },
1336 { 0xf893, KEY_VOLUMEUP },
1337 { 0xf88c, KEY_VOLUMEDOWN },
1338 { 0xf883, KEY_RECORD },
1339 { 0xf898, KEY_PAUSE },
1340 { 0xf899, KEY_OK },
1341 { 0xf89a, KEY_SHUFFLE },
1342 { 0xf881, KEY_UP },
1343 { 0xf890, KEY_LEFT },
1344 { 0xf882, KEY_RIGHT },
1345 { 0xf888, KEY_DOWN },
1346 { 0xf895, KEY_FAVORITES },
1347 { 0xf897, KEY_SUBTITLE },
1348 { 0xf89d, KEY_ZOOM },
1349 { 0xf89f, KEY_EXIT },
1350 { 0xf89e, KEY_MENU },
1351 { 0xf89c, KEY_EPG },
1352 { 0xf880, KEY_PREVIOUS },
1353 { 0xf89b, KEY_MODE }
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001354};
1355
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001356static struct rc_map_table rc_map_su3000_table[] = {
1357 { 0x25, KEY_POWER }, /* right-bottom Red */
1358 { 0x0a, KEY_MUTE }, /* -/-- */
1359 { 0x01, KEY_1 },
1360 { 0x02, KEY_2 },
1361 { 0x03, KEY_3 },
1362 { 0x04, KEY_4 },
1363 { 0x05, KEY_5 },
1364 { 0x06, KEY_6 },
1365 { 0x07, KEY_7 },
1366 { 0x08, KEY_8 },
1367 { 0x09, KEY_9 },
1368 { 0x00, KEY_0 },
1369 { 0x20, KEY_UP }, /* CH+ */
1370 { 0x21, KEY_DOWN }, /* CH+ */
1371 { 0x12, KEY_VOLUMEUP }, /* Brightness Up */
1372 { 0x13, KEY_VOLUMEDOWN },/* Brightness Down */
1373 { 0x1f, KEY_RECORD },
1374 { 0x17, KEY_PLAY },
1375 { 0x16, KEY_PAUSE },
1376 { 0x0b, KEY_STOP },
1377 { 0x27, KEY_FASTFORWARD },/* >> */
1378 { 0x26, KEY_REWIND }, /* << */
1379 { 0x0d, KEY_OK }, /* Mute */
1380 { 0x11, KEY_LEFT }, /* VOL- */
1381 { 0x10, KEY_RIGHT }, /* VOL+ */
1382 { 0x29, KEY_BACK }, /* button under 9 */
1383 { 0x2c, KEY_MENU }, /* TTX */
1384 { 0x2b, KEY_EPG }, /* EPG */
1385 { 0x1e, KEY_RED }, /* OSD */
1386 { 0x0e, KEY_GREEN }, /* Window */
1387 { 0x2d, KEY_YELLOW }, /* button under << */
1388 { 0x0f, KEY_BLUE }, /* bottom yellow button */
1389 { 0x14, KEY_AUDIO }, /* Snapshot */
1390 { 0x38, KEY_TV }, /* TV/Radio */
Justin P. Mattock70f23fd2011-05-10 10:16:21 +02001391 { 0x0c, KEY_ESC } /* upper Red button */
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001392};
1393
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001394static struct rc_map_dvb_usb_table_table keys_tables[] = {
1395 { rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) },
1396 { rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) },
1397 { rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) },
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001398 { rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) },
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001399};
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001400
1401static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
1402{
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001403 struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
1404 int keymap_size = d->props.rc.legacy.rc_map_size;
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001405 u8 key[2];
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001406 struct i2c_msg msg = {
1407 .addr = DW2102_RC_QUERY,
1408 .flags = I2C_M_RD,
1409 .buf = key,
1410 .len = 2
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001411 };
1412 int i;
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001413 /* override keymap */
1414 if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) {
1415 keymap = keys_tables[ir_keymap - 1].rc_keys ;
1416 keymap_size = keys_tables[ir_keymap - 1].rc_keys_size;
Igor M. Liplianinfeb16e92011-02-25 18:41:22 -03001417 } else if (ir_keymap > ARRAY_SIZE(keys_tables))
1418 return 0; /* none */
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001419
1420 *state = REMOTE_NO_KEY_PRESSED;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001421 if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001422 for (i = 0; i < keymap_size ; i++) {
Mauro Carvalho Chehab2e365882009-08-29 15:19:31 -03001423 if (rc5_data(&keymap[i]) == msg.buf[0]) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001424 *state = REMOTE_KEY_PRESSED;
Mauro Carvalho Chehab34abf212010-07-31 11:24:57 -03001425 *event = keymap[i].keycode;
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001426 break;
1427 }
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001428
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001429 }
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001430
1431 if ((*state) == REMOTE_KEY_PRESSED)
1432 deb_rc("%s: found rc key: %x, %x, event: %x\n",
1433 __func__, key[0], key[1], (*event));
1434 else if (key[0] != 0xff)
1435 deb_rc("%s: unknown rc key: %x, %x\n",
1436 __func__, key[0], key[1]);
1437
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001438 }
Igor M. Liplianin8a8dad72009-06-13 08:10:24 -03001439
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001440 return 0;
1441}
1442
Jonathan Nieder27351b12011-12-23 19:00:45 -03001443enum dw2102_table_entry {
1444 CYPRESS_DW2102,
1445 CYPRESS_DW2101,
1446 CYPRESS_DW2104,
1447 TEVII_S650,
1448 TERRATEC_CINERGY_S,
1449 CYPRESS_DW3101,
1450 TEVII_S630,
1451 PROF_1100,
1452 TEVII_S660,
1453 PROF_7500,
1454 GENIATECH_SU3000,
1455 TERRATEC_CINERGY_S2,
1456 TEVII_S480_1,
1457 TEVII_S480_2,
1458 X3M_SPC1400HD,
1459};
1460
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001461static struct usb_device_id dw2102_table[] = {
Jonathan Nieder27351b12011-12-23 19:00:45 -03001462 [CYPRESS_DW2102] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
1463 [CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
1464 [CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
1465 [TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
1466 [TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
1467 [CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
1468 [TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
1469 [PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
1470 [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
1471 [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)},
1472 [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)},
1473 [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
1474 [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
1475 [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
1476 [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001477 { }
1478};
1479
1480MODULE_DEVICE_TABLE(usb, dw2102_table);
1481
1482static int dw2102_load_firmware(struct usb_device *dev,
1483 const struct firmware *frmwr)
1484{
1485 u8 *b, *p;
1486 int ret = 0, i;
1487 u8 reset;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001488 u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001489 const struct firmware *fw;
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001490
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001491 switch (dev->descriptor.idProduct) {
1492 case 0x2101:
Rémi Cardona68236272012-09-28 08:59:32 -03001493 ret = request_firmware(&fw, DW2101_FIRMWARE, &dev->dev);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001494 if (ret != 0) {
Rémi Cardona68236272012-09-28 08:59:32 -03001495 err(err_str, DW2101_FIRMWARE);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001496 return ret;
1497 }
1498 break;
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001499 default:
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001500 fw = frmwr;
1501 break;
1502 }
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001503 info("start downloading DW210X firmware");
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001504 p = kmalloc(fw->size, GFP_KERNEL);
1505 reset = 1;
1506 /*stop the CPU*/
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001507 dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);
1508 dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001509
1510 if (p != NULL) {
1511 memcpy(p, fw->data, fw->size);
1512 for (i = 0; i < fw->size; i += 0x40) {
1513 b = (u8 *) p + i;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001514 if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,
1515 DW210X_WRITE_MSG) != 0x40) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001516 err("error while transferring firmware");
1517 ret = -EINVAL;
1518 break;
1519 }
1520 }
1521 /* restart the CPU */
1522 reset = 0;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001523 if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
1524 DW210X_WRITE_MSG) != 1) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001525 err("could not restart the USB controller CPU.");
1526 ret = -EINVAL;
1527 }
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001528 if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
1529 DW210X_WRITE_MSG) != 1) {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001530 err("could not restart the USB controller CPU.");
1531 ret = -EINVAL;
1532 }
1533 /* init registers */
1534 switch (dev->descriptor.idProduct) {
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001535 case USB_PID_TEVII_S650:
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001536 dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table;
1537 dw2104_properties.rc.legacy.rc_map_size =
1538 ARRAY_SIZE(rc_map_tevii_table);
Igor M. Liplianinb42e1d72009-06-14 19:41:22 -03001539 case USB_PID_DW2104:
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001540 reset = 1;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001541 dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
1542 DW210X_WRITE_MSG);
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001543 /* break omitted intentionally */
1544 case USB_PID_DW3101:
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001545 reset = 0;
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001546 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
1547 DW210X_WRITE_MSG);
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001548 break;
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001549 case USB_PID_CINERGY_S:
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001550 case USB_PID_DW2102:
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001551 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
1552 DW210X_WRITE_MSG);
1553 dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
1554 DW210X_READ_MSG);
1555 /* check STV0299 frontend */
1556 dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,
1557 DW210X_READ_MSG);
Igor M. Liplianinea023df2008-12-04 12:49:23 -03001558 if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001559 dw2102_properties.i2c_algo = &dw2102_i2c_algo;
Michael Krufky77eed212011-09-06 09:31:57 -03001560 dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001561 break;
1562 } else {
1563 /* check STV0288 frontend */
1564 reset16[0] = 0xd0;
1565 reset16[1] = 1;
1566 reset16[2] = 0;
1567 dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,
1568 DW210X_WRITE_MSG);
1569 dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,
1570 DW210X_READ_MSG);
1571 if (reset16[2] == 0x11) {
1572 dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
Igor M. Liplianin8a4949b2008-10-05 09:11:21 -03001573 break;
1574 }
1575 }
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001576 case 0x2101:
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001577 dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,
1578 DW210X_READ_MSG);
1579 dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
1580 DW210X_READ_MSG);
1581 dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
1582 DW210X_READ_MSG);
1583 dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
1584 DW210X_READ_MSG);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001585 break;
1586 }
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001587
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001588 msleep(100);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001589 kfree(p);
1590 }
1591 return ret;
1592}
1593
1594static struct dvb_usb_device_properties dw2102_properties = {
1595 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1596 .usb_ctrl = DEVICE_SPECIFIC,
Rémi Cardona68236272012-09-28 08:59:32 -03001597 .firmware = DW2102_FIRMWARE,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001598 .no_reconnect = 1,
1599
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001600 .i2c_algo = &dw2102_serit_i2c_algo,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001601
1602 .rc.legacy = {
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001603 .rc_map_table = rc_map_dw210x_table,
1604 .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001605 .rc_interval = 150,
1606 .rc_query = dw2102_rc_query,
1607 },
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001608
1609 .generic_bulk_ctrl_endpoint = 0x81,
1610 /* parameter for the MPEG2-data transfer */
1611 .num_adapters = 1,
1612 .download_firmware = dw2102_load_firmware,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001613 .read_mac_address = dw210x_read_mac_address,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001614 .adapter = {
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001615 {
Michael Krufky77eed212011-09-06 09:31:57 -03001616 .num_frontends = 1,
1617 .fe = {{
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001618 .frontend_attach = dw2102_frontend_attach,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001619 .stream = {
1620 .type = USB_BULK,
1621 .count = 8,
1622 .endpoint = 0x82,
1623 .u = {
1624 .bulk = {
1625 .buffersize = 4096,
1626 }
1627 }
1628 },
Michael Krufky77eed212011-09-06 09:31:57 -03001629 }},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001630 }
1631 },
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001632 .num_device_descs = 3,
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001633 .devices = {
1634 {"DVBWorld DVB-S 2102 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001635 {&dw2102_table[CYPRESS_DW2102], NULL},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001636 {NULL},
1637 },
1638 {"DVBWorld DVB-S 2101 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001639 {&dw2102_table[CYPRESS_DW2101], NULL},
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001640 {NULL},
1641 },
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001642 {"TerraTec Cinergy S USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001643 {&dw2102_table[TERRATEC_CINERGY_S], NULL},
Igor M. Liplianin4cc0edf2008-11-05 22:12:56 -03001644 {NULL},
1645 },
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001646 }
1647};
1648
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001649static struct dvb_usb_device_properties dw2104_properties = {
1650 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1651 .usb_ctrl = DEVICE_SPECIFIC,
Rémi Cardona68236272012-09-28 08:59:32 -03001652 .firmware = DW2104_FIRMWARE,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001653 .no_reconnect = 1,
1654
1655 .i2c_algo = &dw2104_i2c_algo,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001656 .rc.legacy = {
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001657 .rc_map_table = rc_map_dw210x_table,
1658 .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001659 .rc_interval = 150,
1660 .rc_query = dw2102_rc_query,
1661 },
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001662
1663 .generic_bulk_ctrl_endpoint = 0x81,
1664 /* parameter for the MPEG2-data transfer */
1665 .num_adapters = 1,
1666 .download_firmware = dw2102_load_firmware,
Igor M. Liplianin21b007b2008-09-17 19:19:19 -03001667 .read_mac_address = dw210x_read_mac_address,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001668 .adapter = {
1669 {
Michael Krufky77eed212011-09-06 09:31:57 -03001670 .num_frontends = 1,
1671 .fe = {{
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001672 .frontend_attach = dw2104_frontend_attach,
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001673 .stream = {
1674 .type = USB_BULK,
1675 .count = 8,
1676 .endpoint = 0x82,
1677 .u = {
1678 .bulk = {
1679 .buffersize = 4096,
1680 }
1681 }
1682 },
Michael Krufky77eed212011-09-06 09:31:57 -03001683 }},
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001684 }
1685 },
1686 .num_device_descs = 2,
1687 .devices = {
1688 { "DVBWorld DW2104 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001689 {&dw2102_table[CYPRESS_DW2104], NULL},
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001690 {NULL},
1691 },
1692 { "TeVii S650 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001693 {&dw2102_table[TEVII_S650], NULL},
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001694 {NULL},
1695 },
1696 }
1697};
1698
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001699static struct dvb_usb_device_properties dw3101_properties = {
1700 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1701 .usb_ctrl = DEVICE_SPECIFIC,
Rémi Cardona68236272012-09-28 08:59:32 -03001702 .firmware = DW3101_FIRMWARE,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001703 .no_reconnect = 1,
1704
1705 .i2c_algo = &dw3101_i2c_algo,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001706 .rc.legacy = {
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001707 .rc_map_table = rc_map_dw210x_table,
1708 .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001709 .rc_interval = 150,
1710 .rc_query = dw2102_rc_query,
1711 },
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001712
1713 .generic_bulk_ctrl_endpoint = 0x81,
1714 /* parameter for the MPEG2-data transfer */
1715 .num_adapters = 1,
1716 .download_firmware = dw2102_load_firmware,
1717 .read_mac_address = dw210x_read_mac_address,
1718 .adapter = {
1719 {
Michael Krufky77eed212011-09-06 09:31:57 -03001720 .num_frontends = 1,
1721 .fe = {{
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001722 .frontend_attach = dw3101_frontend_attach,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001723 .tuner_attach = dw3101_tuner_attach,
1724 .stream = {
1725 .type = USB_BULK,
1726 .count = 8,
1727 .endpoint = 0x82,
1728 .u = {
1729 .bulk = {
1730 .buffersize = 4096,
1731 }
1732 }
1733 },
Michael Krufky77eed212011-09-06 09:31:57 -03001734 }},
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001735 }
1736 },
1737 .num_device_descs = 1,
1738 .devices = {
1739 { "DVBWorld DVB-C 3101 USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001740 {&dw2102_table[CYPRESS_DW3101], NULL},
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001741 {NULL},
1742 },
1743 }
1744};
1745
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001746static struct dvb_usb_device_properties s6x0_properties = {
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001747 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1748 .usb_ctrl = DEVICE_SPECIFIC,
Igor M. Liplianin52c506e2011-02-25 18:41:23 -03001749 .size_of_priv = sizeof(struct s6x0_state),
Rémi Cardona68236272012-09-28 08:59:32 -03001750 .firmware = S630_FIRMWARE,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001751 .no_reconnect = 1,
1752
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001753 .i2c_algo = &s6x0_i2c_algo,
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001754 .rc.legacy = {
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001755 .rc_map_table = rc_map_tevii_table,
1756 .rc_map_size = ARRAY_SIZE(rc_map_tevii_table),
Mauro Carvalho Chehabf72a27b2010-07-31 18:04:09 -03001757 .rc_interval = 150,
1758 .rc_query = dw2102_rc_query,
1759 },
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001760
1761 .generic_bulk_ctrl_endpoint = 0x81,
1762 .num_adapters = 1,
1763 .download_firmware = dw2102_load_firmware,
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001764 .read_mac_address = s6x0_read_mac_address,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001765 .adapter = {
1766 {
Michael Krufky77eed212011-09-06 09:31:57 -03001767 .num_frontends = 1,
1768 .fe = {{
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001769 .frontend_attach = zl100313_frontend_attach,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001770 .stream = {
1771 .type = USB_BULK,
1772 .count = 8,
1773 .endpoint = 0x82,
1774 .u = {
1775 .bulk = {
1776 .buffersize = 4096,
1777 }
1778 }
1779 },
Michael Krufky77eed212011-09-06 09:31:57 -03001780 }},
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001781 }
1782 },
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001783 .num_device_descs = 1,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001784 .devices = {
1785 {"TeVii S630 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001786 {&dw2102_table[TEVII_S630], NULL},
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001787 {NULL},
1788 },
1789 }
1790};
1791
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001792struct dvb_usb_device_properties *p1100;
1793static struct dvb_usb_device_description d1100 = {
1794 "Prof 1100 USB ",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001795 {&dw2102_table[PROF_1100], NULL},
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001796 {NULL},
1797};
1798
1799struct dvb_usb_device_properties *s660;
1800static struct dvb_usb_device_description d660 = {
1801 "TeVii S660 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001802 {&dw2102_table[TEVII_S660], NULL},
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001803 {NULL},
1804};
1805
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001806static struct dvb_usb_device_description d480_1 = {
1807 "TeVii S480.1 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001808 {&dw2102_table[TEVII_S480_1], NULL},
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001809 {NULL},
1810};
1811
1812static struct dvb_usb_device_description d480_2 = {
1813 "TeVii S480.2 USB",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001814 {&dw2102_table[TEVII_S480_2], NULL},
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001815 {NULL},
1816};
1817
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001818struct dvb_usb_device_properties *p7500;
1819static struct dvb_usb_device_description d7500 = {
1820 "Prof 7500 USB DVB-S2",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001821 {&dw2102_table[PROF_7500], NULL},
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001822 {NULL},
1823};
1824
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001825static struct dvb_usb_device_properties su3000_properties = {
1826 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1827 .usb_ctrl = DEVICE_SPECIFIC,
1828 .size_of_priv = sizeof(struct su3000_state),
1829 .power_ctrl = su3000_power_ctrl,
1830 .num_adapters = 1,
1831 .identify_state = su3000_identify_state,
1832 .i2c_algo = &su3000_i2c_algo,
1833
1834 .rc.legacy = {
1835 .rc_map_table = rc_map_su3000_table,
1836 .rc_map_size = ARRAY_SIZE(rc_map_su3000_table),
1837 .rc_interval = 150,
1838 .rc_query = dw2102_rc_query,
1839 },
1840
1841 .read_mac_address = su3000_read_mac_address,
1842
1843 .generic_bulk_ctrl_endpoint = 0x01,
1844
1845 .adapter = {
1846 {
Michael Krufky77eed212011-09-06 09:31:57 -03001847 .num_frontends = 1,
1848 .fe = {{
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001849 .streaming_ctrl = su3000_streaming_ctrl,
1850 .frontend_attach = su3000_frontend_attach,
1851 .stream = {
1852 .type = USB_BULK,
1853 .count = 8,
1854 .endpoint = 0x82,
1855 .u = {
1856 .bulk = {
1857 .buffersize = 4096,
1858 }
1859 }
1860 }
Michael Krufky77eed212011-09-06 09:31:57 -03001861 }},
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001862 }
1863 },
Mauro Carvalho Chehabb7e38632012-07-07 00:19:20 -03001864 .num_device_descs = 3,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001865 .devices = {
1866 { "SU3000HD DVB-S USB2.0",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001867 { &dw2102_table[GENIATECH_SU3000], NULL },
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001868 { NULL },
1869 },
Igor M. Liplianin2adc5912011-02-25 18:41:22 -03001870 { "Terratec Cinergy S2 USB HD",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001871 { &dw2102_table[TERRATEC_CINERGY_S2], NULL },
Igor M. Liplianin2adc5912011-02-25 18:41:22 -03001872 { NULL },
1873 },
Igor M. Liplianin5265ea52011-02-27 16:17:25 -03001874 { "X3M TV SPC1400HD PCI",
Jonathan Nieder27351b12011-12-23 19:00:45 -03001875 { &dw2102_table[X3M_SPC1400HD], NULL },
Igor M. Liplianin5265ea52011-02-27 16:17:25 -03001876 { NULL },
1877 },
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001878 }
1879};
1880
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001881static int dw2102_probe(struct usb_interface *intf,
1882 const struct usb_device_id *id)
1883{
Thomas Meyer68dd9dd2011-11-17 18:43:40 -03001884 p1100 = kmemdup(&s6x0_properties,
1885 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001886 if (!p1100)
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001887 return -ENOMEM;
1888 /* copy default structure */
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001889 /* fill only different fields */
Rémi Cardona68236272012-09-28 08:59:32 -03001890 p1100->firmware = P1100_FIRMWARE;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001891 p1100->devices[0] = d1100;
1892 p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
1893 p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
Michael Krufky77eed212011-09-06 09:31:57 -03001894 p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001895
Thomas Meyer68dd9dd2011-11-17 18:43:40 -03001896 s660 = kmemdup(&s6x0_properties,
1897 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001898 if (!s660) {
1899 kfree(p1100);
1900 return -ENOMEM;
1901 }
Rémi Cardona68236272012-09-28 08:59:32 -03001902 s660->firmware = S660_FIRMWARE;
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001903 s660->num_device_descs = 3;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001904 s660->devices[0] = d660;
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001905 s660->devices[1] = d480_1;
1906 s660->devices[2] = d480_2;
Michael Krufky77eed212011-09-06 09:31:57 -03001907 s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001908
Thomas Meyer68dd9dd2011-11-17 18:43:40 -03001909 p7500 = kmemdup(&s6x0_properties,
1910 sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001911 if (!p7500) {
1912 kfree(p1100);
1913 kfree(s660);
1914 return -ENOMEM;
1915 }
Rémi Cardona68236272012-09-28 08:59:32 -03001916 p7500->firmware = P7500_FIRMWARE;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001917 p7500->devices[0] = d7500;
Mauro Carvalho Chehab2f4f58d2010-11-17 15:46:09 -03001918 p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
1919 p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
Michael Krufky77eed212011-09-06 09:31:57 -03001920 p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001921
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001922 if (0 == dvb_usb_device_init(intf, &dw2102_properties,
1923 THIS_MODULE, NULL, adapter_nr) ||
1924 0 == dvb_usb_device_init(intf, &dw2104_properties,
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001925 THIS_MODULE, NULL, adapter_nr) ||
1926 0 == dvb_usb_device_init(intf, &dw3101_properties,
Igor M. Liplianind0a1dda2009-06-20 09:54:18 -03001927 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001928 0 == dvb_usb_device_init(intf, &s6x0_properties,
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001929 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianin195288d2011-02-25 18:41:22 -03001930 0 == dvb_usb_device_init(intf, p1100,
1931 THIS_MODULE, NULL, adapter_nr) ||
1932 0 == dvb_usb_device_init(intf, s660,
1933 THIS_MODULE, NULL, adapter_nr) ||
Igor M. Liplianincd79d332009-12-14 20:24:56 -03001934 0 == dvb_usb_device_init(intf, p7500,
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001935 THIS_MODULE, NULL, adapter_nr) ||
1936 0 == dvb_usb_device_init(intf, &su3000_properties,
1937 THIS_MODULE, NULL, adapter_nr))
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001938 return 0;
Igor M. Liplianin141cc352009-11-27 14:37:35 -03001939
Igor M. Liplianinfe03d5e2008-09-08 17:16:40 -03001940 return -ENODEV;
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001941}
1942
1943static struct usb_driver dw2102_driver = {
1944 .name = "dw2102",
1945 .probe = dw2102_probe,
1946 .disconnect = dvb_usb_device_exit,
1947 .id_table = dw2102_table,
1948};
1949
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001950module_usb_driver(dw2102_driver);
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001951
1952MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
Igor M. Liplianin1dac77c2009-06-14 20:51:45 -03001953MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
1954 " DVB-C 3101 USB2.0,"
Igor M. Liplianine8f50552011-02-25 18:41:23 -03001955 " TeVii S600, S630, S650, S660, S480,"
Igor M. Liplianind2ffc442011-02-25 18:41:22 -03001956 " Prof 1100, 7500 USB2.0,"
1957 " Geniatech SU3000 devices");
Igor M Liplianin7fd48282008-07-20 08:05:50 -03001958MODULE_VERSION("0.1");
1959MODULE_LICENSE("GPL");
Rémi Cardona68236272012-09-28 08:59:32 -03001960MODULE_FIRMWARE(DW2101_FIRMWARE);
1961MODULE_FIRMWARE(DW2102_FIRMWARE);
1962MODULE_FIRMWARE(DW2104_FIRMWARE);
1963MODULE_FIRMWARE(DW3101_FIRMWARE);
1964MODULE_FIRMWARE(S630_FIRMWARE);
1965MODULE_FIRMWARE(S660_FIRMWARE);
1966MODULE_FIRMWARE(P1100_FIRMWARE);
1967MODULE_FIRMWARE(P7500_FIRMWARE);