]>
Commit | Line | Data |
---|---|---|
fe03d5ee | 1 | /* DVB USB framework compliant Linux driver for the |
2f30fb49 | 2 | * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, |
6ede20f9 | 3 | * TeVii S421, S480, S482, S600, S630, S632, S650, S660, S662, |
2f30fb49 | 4 | * Prof 1100, 7500, |
27254c36 | 5 | * Geniatech SU3000, T220, |
6ede20f9 OS |
6 | * TechnoTrend S2-4600, |
7 | * Terratec Cinergy S2 cards | |
955d00ac | 8 | * Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by) |
2f30fb49 IL |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | |
11 | * under the terms of the GNU General Public License as published by the | |
12 | * Free Software Foundation, version 2. | |
13 | * | |
14 | * see Documentation/dvb/README.dvb-usb for more information | |
15 | */ | |
e8364275 | 16 | #include "dvb-usb-ids.h" |
7fd4828f | 17 | #include "dw2102.h" |
21b007b9 | 18 | #include "si21xx.h" |
7fd4828f IL |
19 | #include "stv0299.h" |
20 | #include "z0194a.h" | |
8a4949b7 IL |
21 | #include "stv0288.h" |
22 | #include "stb6000.h" | |
23 | #include "eds1547.h" | |
fe03d5ee | 24 | #include "cx24116.h" |
1dac77c9 | 25 | #include "tda1002x.h" |
d0a1ddad IL |
26 | #include "mt312.h" |
27 | #include "zl10039.h" | |
73f0af44 | 28 | #include "ts2020.h" |
141cc35e IL |
29 | #include "ds3000.h" |
30 | #include "stv0900.h" | |
31 | #include "stv6110.h" | |
32 | #include "stb6100.h" | |
33 | #include "stb6100_proc.h" | |
955d00ac | 34 | #include "m88rs2000.h" |
51d882ed EP |
35 | #include "tda18271.h" |
36 | #include "cxd2820r.h" | |
27254c36 | 37 | #include "m88ds3103.h" |
7fd4828f | 38 | |
0065a79a MCC |
39 | /* Max transfer size done by I2C transfer functions */ |
40 | #define MAX_XFER_SIZE 64 | |
41 | ||
f08e9f0d | 42 | |
21b007b9 IL |
43 | #define DW210X_READ_MSG 0 |
44 | #define DW210X_WRITE_MSG 1 | |
7fd4828f IL |
45 | |
46 | #define REG_1F_SYMBOLRATE_BYTE0 0x1f | |
47 | #define REG_20_SYMBOLRATE_BYTE1 0x20 | |
48 | #define REG_21_SYMBOLRATE_BYTE2 0x21 | |
fe03d5ee | 49 | /* on my own*/ |
7fd4828f | 50 | #define DW2102_VOLTAGE_CTRL (0x1800) |
d2ffc447 | 51 | #define SU3000_STREAM_CTRL (0x1900) |
7fd4828f | 52 | #define DW2102_RC_QUERY (0x1a00) |
fa8bae10 | 53 | #define DW2102_LED_CTRL (0x1b00) |
7fd4828f | 54 | |
6823627b RC |
55 | #define DW2101_FIRMWARE "dvb-usb-dw2101.fw" |
56 | #define DW2102_FIRMWARE "dvb-usb-dw2102.fw" | |
57 | #define DW2104_FIRMWARE "dvb-usb-dw2104.fw" | |
58 | #define DW3101_FIRMWARE "dvb-usb-dw3101.fw" | |
59 | #define S630_FIRMWARE "dvb-usb-s630.fw" | |
60 | #define S660_FIRMWARE "dvb-usb-s660.fw" | |
61 | #define P1100_FIRMWARE "dvb-usb-p1100.fw" | |
62 | #define P7500_FIRMWARE "dvb-usb-p7500.fw" | |
63 | ||
141cc35e IL |
64 | #define err_str "did not find the firmware file. (%s) " \ |
65 | "Please see linux/Documentation/dvb/ for more details " \ | |
66 | "on firmware-problems." | |
67 | ||
2c4ffe27 | 68 | struct dw2102_state { |
d2ffc447 | 69 | u8 initialized; |
356484ca | 70 | u8 last_lock; |
606142af | 71 | u8 data[MAX_XFER_SIZE + 4]; |
f3c6abca | 72 | struct i2c_client *i2c_client_demod; |
70769b24 | 73 | struct i2c_client *i2c_client_tuner; |
356484ca OS |
74 | |
75 | /* fe hook functions*/ | |
0df289a2 | 76 | int (*old_set_voltage)(struct dvb_frontend *f, enum fe_sec_voltage v); |
356484ca | 77 | int (*fe_read_status)(struct dvb_frontend *fe, |
0df289a2 | 78 | enum fe_status *status); |
52c506e0 IL |
79 | }; |
80 | ||
fe03d5ee IL |
81 | /* debug */ |
82 | static int dvb_usb_dw2102_debug; | |
83 | module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); | |
8a8dad71 IL |
84 | MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))." |
85 | DVB_USB_DEBUG_STATUS); | |
86 | ||
141cc35e IL |
87 | /* demod probe */ |
88 | static int demod_probe = 1; | |
89 | module_param_named(demod, demod_probe, int, 0644); | |
f319ed91 | 90 | MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 4=stv0903+stb6100(or-able))."); |
141cc35e | 91 | |
7fd4828f IL |
92 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
93 | ||
21b007b9 | 94 | static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, |
fe03d5ee | 95 | u16 index, u8 * data, u16 len, int flags) |
7fd4828f IL |
96 | { |
97 | int ret; | |
b47b8501 | 98 | u8 *u8buf; |
21b007b9 | 99 | unsigned int pipe = (flags == DW210X_READ_MSG) ? |
fe03d5ee | 100 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); |
21b007b9 | 101 | u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; |
7fd4828f | 102 | |
b47b8501 FM |
103 | u8buf = kmalloc(len, GFP_KERNEL); |
104 | if (!u8buf) | |
105 | return -ENOMEM; | |
106 | ||
107 | ||
21b007b9 | 108 | if (flags == DW210X_WRITE_MSG) |
7fd4828f | 109 | memcpy(u8buf, data, len); |
fe03d5ee IL |
110 | ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, |
111 | value, index , u8buf, len, 2000); | |
7fd4828f | 112 | |
21b007b9 | 113 | if (flags == DW210X_READ_MSG) |
7fd4828f | 114 | memcpy(data, u8buf, len); |
b47b8501 FM |
115 | |
116 | kfree(u8buf); | |
7fd4828f IL |
117 | return ret; |
118 | } | |
119 | ||
120 | /* I2C */ | |
7fd4828f IL |
121 | static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
122 | int num) | |
123 | { | |
1dac77c9 | 124 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
d51dbecc | 125 | int i = 0; |
7fd4828f | 126 | u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; |
7fd4828f IL |
127 | u16 value; |
128 | ||
129 | if (!d) | |
130 | return -ENODEV; | |
131 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
132 | return -EAGAIN; | |
133 | ||
134 | switch (num) { | |
135 | case 2: | |
136 | /* read stv0299 register */ | |
7fd4828f IL |
137 | value = msg[0].buf[0];/* register */ |
138 | for (i = 0; i < msg[1].len; i++) { | |
d51dbecc | 139 | dw210x_op_rw(d->udev, 0xb5, value + i, 0, |
21b007b9 | 140 | buf6, 2, DW210X_READ_MSG); |
7fd4828f | 141 | msg[1].buf[i] = buf6[0]; |
7fd4828f IL |
142 | } |
143 | break; | |
144 | case 1: | |
145 | switch (msg[0].addr) { | |
146 | case 0x68: | |
147 | /* write to stv0299 register */ | |
148 | buf6[0] = 0x2a; | |
149 | buf6[1] = msg[0].buf[0]; | |
150 | buf6[2] = msg[0].buf[1]; | |
d51dbecc | 151 | dw210x_op_rw(d->udev, 0xb2, 0, 0, |
21b007b9 | 152 | buf6, 3, DW210X_WRITE_MSG); |
7fd4828f IL |
153 | break; |
154 | case 0x60: | |
155 | if (msg[0].flags == 0) { | |
156 | /* write to tuner pll */ | |
157 | buf6[0] = 0x2c; | |
158 | buf6[1] = 5; | |
159 | buf6[2] = 0xc0; | |
160 | buf6[3] = msg[0].buf[0]; | |
161 | buf6[4] = msg[0].buf[1]; | |
162 | buf6[5] = msg[0].buf[2]; | |
163 | buf6[6] = msg[0].buf[3]; | |
d51dbecc | 164 | dw210x_op_rw(d->udev, 0xb2, 0, 0, |
21b007b9 | 165 | buf6, 7, DW210X_WRITE_MSG); |
7fd4828f | 166 | } else { |
fe03d5ee | 167 | /* read from tuner */ |
d51dbecc | 168 | dw210x_op_rw(d->udev, 0xb5, 0, 0, |
21b007b9 | 169 | buf6, 1, DW210X_READ_MSG); |
7fd4828f IL |
170 | msg[0].buf[0] = buf6[0]; |
171 | } | |
172 | break; | |
173 | case (DW2102_RC_QUERY): | |
d51dbecc | 174 | dw210x_op_rw(d->udev, 0xb8, 0, 0, |
21b007b9 | 175 | buf6, 2, DW210X_READ_MSG); |
7fd4828f IL |
176 | msg[0].buf[0] = buf6[0]; |
177 | msg[0].buf[1] = buf6[1]; | |
178 | break; | |
179 | case (DW2102_VOLTAGE_CTRL): | |
180 | buf6[0] = 0x30; | |
181 | buf6[1] = msg[0].buf[0]; | |
d51dbecc | 182 | dw210x_op_rw(d->udev, 0xb2, 0, 0, |
21b007b9 | 183 | buf6, 2, DW210X_WRITE_MSG); |
7fd4828f IL |
184 | break; |
185 | } | |
186 | ||
187 | break; | |
188 | } | |
189 | ||
190 | mutex_unlock(&d->i2c_mutex); | |
191 | return num; | |
192 | } | |
193 | ||
21b007b9 IL |
194 | static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, |
195 | struct i2c_msg msg[], int num) | |
196 | { | |
197 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
21b007b9 IL |
198 | u8 buf6[] = {0, 0, 0, 0, 0, 0, 0}; |
199 | ||
200 | if (!d) | |
201 | return -ENODEV; | |
202 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
203 | return -EAGAIN; | |
204 | ||
205 | switch (num) { | |
206 | case 2: | |
207 | /* read si2109 register by number */ | |
141cc35e | 208 | buf6[0] = msg[0].addr << 1; |
21b007b9 IL |
209 | buf6[1] = msg[0].len; |
210 | buf6[2] = msg[0].buf[0]; | |
d51dbecc | 211 | dw210x_op_rw(d->udev, 0xc2, 0, 0, |
21b007b9 IL |
212 | buf6, msg[0].len + 2, DW210X_WRITE_MSG); |
213 | /* read si2109 register */ | |
d51dbecc | 214 | dw210x_op_rw(d->udev, 0xc3, 0xd0, 0, |
21b007b9 IL |
215 | buf6, msg[1].len + 2, DW210X_READ_MSG); |
216 | memcpy(msg[1].buf, buf6 + 2, msg[1].len); | |
217 | ||
218 | break; | |
219 | case 1: | |
220 | switch (msg[0].addr) { | |
221 | case 0x68: | |
222 | /* write to si2109 register */ | |
141cc35e | 223 | buf6[0] = msg[0].addr << 1; |
21b007b9 IL |
224 | buf6[1] = msg[0].len; |
225 | memcpy(buf6 + 2, msg[0].buf, msg[0].len); | |
d51dbecc | 226 | dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6, |
21b007b9 IL |
227 | msg[0].len + 2, DW210X_WRITE_MSG); |
228 | break; | |
229 | case(DW2102_RC_QUERY): | |
d51dbecc | 230 | dw210x_op_rw(d->udev, 0xb8, 0, 0, |
21b007b9 IL |
231 | buf6, 2, DW210X_READ_MSG); |
232 | msg[0].buf[0] = buf6[0]; | |
233 | msg[0].buf[1] = buf6[1]; | |
234 | break; | |
235 | case(DW2102_VOLTAGE_CTRL): | |
236 | buf6[0] = 0x30; | |
237 | buf6[1] = msg[0].buf[0]; | |
d51dbecc | 238 | dw210x_op_rw(d->udev, 0xb2, 0, 0, |
21b007b9 IL |
239 | buf6, 2, DW210X_WRITE_MSG); |
240 | break; | |
241 | } | |
242 | break; | |
243 | } | |
244 | ||
245 | mutex_unlock(&d->i2c_mutex); | |
246 | return num; | |
247 | } | |
1dac77c9 | 248 | |
8a4949b7 IL |
249 | static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) |
250 | { | |
251 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
324ed533 | 252 | int ret; |
8a4949b7 IL |
253 | |
254 | if (!d) | |
255 | return -ENODEV; | |
256 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
257 | return -EAGAIN; | |
258 | ||
259 | switch (num) { | |
260 | case 2: { | |
261 | /* read */ | |
262 | /* first write first register number */ | |
0065a79a MCC |
263 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; |
264 | ||
265 | if (2 + msg[1].len > sizeof(ibuf)) { | |
266 | warn("i2c rd: len=%d is too big!\n", | |
267 | msg[1].len); | |
324ed533 DC |
268 | ret = -EOPNOTSUPP; |
269 | goto unlock; | |
0065a79a MCC |
270 | } |
271 | ||
141cc35e | 272 | obuf[0] = msg[0].addr << 1; |
8a4949b7 IL |
273 | obuf[1] = msg[0].len; |
274 | obuf[2] = msg[0].buf[0]; | |
d51dbecc | 275 | dw210x_op_rw(d->udev, 0xc2, 0, 0, |
8a4949b7 IL |
276 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); |
277 | /* second read registers */ | |
d51dbecc | 278 | dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0, |
8a4949b7 IL |
279 | ibuf, msg[1].len + 2, DW210X_READ_MSG); |
280 | memcpy(msg[1].buf, ibuf + 2, msg[1].len); | |
281 | ||
282 | break; | |
283 | } | |
284 | case 1: | |
285 | switch (msg[0].addr) { | |
286 | case 0x68: { | |
287 | /* write to register */ | |
0065a79a MCC |
288 | u8 obuf[MAX_XFER_SIZE]; |
289 | ||
290 | if (2 + msg[0].len > sizeof(obuf)) { | |
291 | warn("i2c wr: len=%d is too big!\n", | |
292 | msg[1].len); | |
324ed533 DC |
293 | ret = -EOPNOTSUPP; |
294 | goto unlock; | |
0065a79a MCC |
295 | } |
296 | ||
141cc35e | 297 | obuf[0] = msg[0].addr << 1; |
8a4949b7 IL |
298 | obuf[1] = msg[0].len; |
299 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | |
d51dbecc | 300 | dw210x_op_rw(d->udev, 0xc2, 0, 0, |
8a4949b7 IL |
301 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); |
302 | break; | |
303 | } | |
304 | case 0x61: { | |
305 | /* write to tuner */ | |
0065a79a MCC |
306 | u8 obuf[MAX_XFER_SIZE]; |
307 | ||
308 | if (2 + msg[0].len > sizeof(obuf)) { | |
309 | warn("i2c wr: len=%d is too big!\n", | |
310 | msg[1].len); | |
324ed533 DC |
311 | ret = -EOPNOTSUPP; |
312 | goto unlock; | |
0065a79a MCC |
313 | } |
314 | ||
141cc35e | 315 | obuf[0] = msg[0].addr << 1; |
8a4949b7 IL |
316 | obuf[1] = msg[0].len; |
317 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | |
d51dbecc | 318 | dw210x_op_rw(d->udev, 0xc2, 0, 0, |
8a4949b7 IL |
319 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); |
320 | break; | |
321 | } | |
322 | case(DW2102_RC_QUERY): { | |
323 | u8 ibuf[2]; | |
d51dbecc | 324 | dw210x_op_rw(d->udev, 0xb8, 0, 0, |
8a4949b7 IL |
325 | ibuf, 2, DW210X_READ_MSG); |
326 | memcpy(msg[0].buf, ibuf , 2); | |
327 | break; | |
328 | } | |
329 | case(DW2102_VOLTAGE_CTRL): { | |
330 | u8 obuf[2]; | |
331 | obuf[0] = 0x30; | |
332 | obuf[1] = msg[0].buf[0]; | |
d51dbecc | 333 | dw210x_op_rw(d->udev, 0xb2, 0, 0, |
8a4949b7 IL |
334 | obuf, 2, DW210X_WRITE_MSG); |
335 | break; | |
336 | } | |
337 | } | |
338 | ||
339 | break; | |
340 | } | |
324ed533 | 341 | ret = num; |
8a4949b7 | 342 | |
324ed533 | 343 | unlock: |
8a4949b7 | 344 | mutex_unlock(&d->i2c_mutex); |
324ed533 | 345 | return ret; |
8a4949b7 | 346 | } |
21b007b9 | 347 | |
fe03d5ee IL |
348 | static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) |
349 | { | |
350 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
324ed533 | 351 | int len, i, j, ret; |
fe03d5ee IL |
352 | |
353 | if (!d) | |
354 | return -ENODEV; | |
355 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
356 | return -EAGAIN; | |
357 | ||
141cc35e IL |
358 | for (j = 0; j < num; j++) { |
359 | switch (msg[j].addr) { | |
fe03d5ee IL |
360 | case(DW2102_RC_QUERY): { |
361 | u8 ibuf[2]; | |
d51dbecc | 362 | dw210x_op_rw(d->udev, 0xb8, 0, 0, |
21b007b9 | 363 | ibuf, 2, DW210X_READ_MSG); |
141cc35e | 364 | memcpy(msg[j].buf, ibuf , 2); |
fe03d5ee IL |
365 | break; |
366 | } | |
367 | case(DW2102_VOLTAGE_CTRL): { | |
368 | u8 obuf[2]; | |
369 | obuf[0] = 0x30; | |
141cc35e | 370 | obuf[1] = msg[j].buf[0]; |
d51dbecc | 371 | dw210x_op_rw(d->udev, 0xb2, 0, 0, |
21b007b9 | 372 | obuf, 2, DW210X_WRITE_MSG); |
fe03d5ee IL |
373 | break; |
374 | } | |
141cc35e IL |
375 | /*case 0x55: cx24116 |
376 | case 0x6a: stv0903 | |
377 | case 0x68: ds3000, stv0903 | |
378 | case 0x60: ts2020, stv6110, stb6100 */ | |
379 | default: { | |
380 | if (msg[j].flags == I2C_M_RD) { | |
381 | /* read registers */ | |
0065a79a MCC |
382 | u8 ibuf[MAX_XFER_SIZE]; |
383 | ||
384 | if (2 + msg[j].len > sizeof(ibuf)) { | |
385 | warn("i2c rd: len=%d is too big!\n", | |
386 | msg[j].len); | |
324ed533 DC |
387 | ret = -EOPNOTSUPP; |
388 | goto unlock; | |
0065a79a MCC |
389 | } |
390 | ||
d51dbecc | 391 | dw210x_op_rw(d->udev, 0xc3, |
141cc35e IL |
392 | (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); | |
48902bc7 | 396 | mdelay(10); |
141cc35e IL |
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)); | |
d51dbecc | 411 | dw210x_op_rw(d->udev, 0xc2, 0, 0, |
141cc35e IL |
412 | 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 */ | |
0065a79a MCC |
419 | u8 obuf[MAX_XFER_SIZE]; |
420 | ||
421 | if (2 + msg[j].len > sizeof(obuf)) { | |
422 | warn("i2c wr: len=%d is too big!\n", | |
423 | msg[j].len); | |
324ed533 DC |
424 | ret = -EOPNOTSUPP; |
425 | goto unlock; | |
0065a79a MCC |
426 | } |
427 | ||
141cc35e IL |
428 | obuf[0] = msg[j].addr << 1; |
429 | obuf[1] = msg[j].len; | |
430 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | |
d51dbecc | 431 | dw210x_op_rw(d->udev, 0xc2, 0, 0, |
141cc35e IL |
432 | obuf, msg[j].len + 2, |
433 | DW210X_WRITE_MSG); | |
434 | } | |
435 | break; | |
436 | } | |
fe03d5ee IL |
437 | } |
438 | ||
fe03d5ee | 439 | } |
324ed533 | 440 | ret = num; |
fe03d5ee | 441 | |
324ed533 | 442 | unlock: |
fe03d5ee | 443 | mutex_unlock(&d->i2c_mutex); |
324ed533 | 444 | return ret; |
fe03d5ee IL |
445 | } |
446 | ||
1dac77c9 IL |
447 | static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
448 | int num) | |
449 | { | |
450 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
324ed533 | 451 | int ret; |
d51dbecc | 452 | int i; |
1dac77c9 IL |
453 | |
454 | if (!d) | |
455 | return -ENODEV; | |
456 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
457 | return -EAGAIN; | |
458 | ||
459 | switch (num) { | |
460 | case 2: { | |
461 | /* read */ | |
462 | /* first write first register number */ | |
0065a79a MCC |
463 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; |
464 | ||
465 | if (2 + msg[1].len > sizeof(ibuf)) { | |
466 | warn("i2c rd: len=%d is too big!\n", | |
467 | msg[1].len); | |
324ed533 DC |
468 | ret = -EOPNOTSUPP; |
469 | goto unlock; | |
0065a79a | 470 | } |
1dac77c9 IL |
471 | obuf[0] = msg[0].addr << 1; |
472 | obuf[1] = msg[0].len; | |
473 | obuf[2] = msg[0].buf[0]; | |
d51dbecc | 474 | dw210x_op_rw(d->udev, 0xc2, 0, 0, |
1dac77c9 IL |
475 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); |
476 | /* second read registers */ | |
d51dbecc | 477 | dw210x_op_rw(d->udev, 0xc3, 0x19 , 0, |
1dac77c9 IL |
478 | ibuf, msg[1].len + 2, DW210X_READ_MSG); |
479 | memcpy(msg[1].buf, ibuf + 2, msg[1].len); | |
480 | ||
481 | break; | |
482 | } | |
483 | case 1: | |
484 | switch (msg[0].addr) { | |
485 | case 0x60: | |
486 | case 0x0c: { | |
487 | /* write to register */ | |
0065a79a MCC |
488 | u8 obuf[MAX_XFER_SIZE]; |
489 | ||
490 | if (2 + msg[0].len > sizeof(obuf)) { | |
491 | warn("i2c wr: len=%d is too big!\n", | |
492 | msg[0].len); | |
324ed533 DC |
493 | ret = -EOPNOTSUPP; |
494 | goto unlock; | |
0065a79a | 495 | } |
1dac77c9 IL |
496 | obuf[0] = msg[0].addr << 1; |
497 | obuf[1] = msg[0].len; | |
498 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | |
d51dbecc | 499 | dw210x_op_rw(d->udev, 0xc2, 0, 0, |
1dac77c9 IL |
500 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); |
501 | break; | |
502 | } | |
503 | case(DW2102_RC_QUERY): { | |
504 | u8 ibuf[2]; | |
d51dbecc | 505 | dw210x_op_rw(d->udev, 0xb8, 0, 0, |
1dac77c9 IL |
506 | ibuf, 2, DW210X_READ_MSG); |
507 | memcpy(msg[0].buf, ibuf , 2); | |
508 | break; | |
509 | } | |
510 | } | |
511 | ||
512 | break; | |
513 | } | |
514 | ||
515 | for (i = 0; i < num; i++) { | |
516 | deb_xfer("%02x:%02x: %s ", i, msg[i].addr, | |
517 | msg[i].flags == 0 ? ">>>" : "<<<"); | |
518 | debug_dump(msg[i].buf, msg[i].len, deb_xfer); | |
519 | } | |
324ed533 | 520 | ret = num; |
1dac77c9 | 521 | |
324ed533 | 522 | unlock: |
1dac77c9 | 523 | mutex_unlock(&d->i2c_mutex); |
324ed533 | 524 | return ret; |
1dac77c9 IL |
525 | } |
526 | ||
141cc35e | 527 | static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
d0a1ddad IL |
528 | int num) |
529 | { | |
530 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
21ead03b | 531 | struct usb_device *udev; |
324ed533 | 532 | int len, i, j, ret; |
d0a1ddad IL |
533 | |
534 | if (!d) | |
535 | return -ENODEV; | |
21ead03b | 536 | udev = d->udev; |
d0a1ddad IL |
537 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
538 | return -EAGAIN; | |
539 | ||
141cc35e IL |
540 | for (j = 0; j < num; j++) { |
541 | switch (msg[j].addr) { | |
d0a1ddad | 542 | case (DW2102_RC_QUERY): { |
5a530cbe | 543 | u8 ibuf[5]; |
d51dbecc | 544 | dw210x_op_rw(d->udev, 0xb8, 0, 0, |
5a530cbe IL |
545 | ibuf, 5, DW210X_READ_MSG); |
546 | memcpy(msg[j].buf, ibuf + 3, 2); | |
d0a1ddad IL |
547 | break; |
548 | } | |
549 | case (DW2102_VOLTAGE_CTRL): { | |
550 | u8 obuf[2]; | |
cd79d33e IL |
551 | |
552 | obuf[0] = 1; | |
553 | obuf[1] = msg[j].buf[1];/* off-on */ | |
d51dbecc | 554 | dw210x_op_rw(d->udev, 0x8a, 0, 0, |
cd79d33e | 555 | obuf, 2, DW210X_WRITE_MSG); |
141cc35e | 556 | obuf[0] = 3; |
cd79d33e | 557 | obuf[1] = msg[j].buf[0];/* 13v-18v */ |
d51dbecc | 558 | dw210x_op_rw(d->udev, 0x8a, 0, 0, |
d0a1ddad IL |
559 | obuf, 2, DW210X_WRITE_MSG); |
560 | break; | |
561 | } | |
fa8bae10 IL |
562 | case (DW2102_LED_CTRL): { |
563 | u8 obuf[2]; | |
564 | ||
565 | obuf[0] = 5; | |
566 | obuf[1] = msg[j].buf[0]; | |
d51dbecc | 567 | dw210x_op_rw(d->udev, 0x8a, 0, 0, |
fa8bae10 IL |
568 | obuf, 2, DW210X_WRITE_MSG); |
569 | break; | |
570 | } | |
141cc35e IL |
571 | /*case 0x55: cx24116 |
572 | case 0x6a: stv0903 | |
955d00ac | 573 | case 0x68: ds3000, stv0903, rs2000 |
141cc35e IL |
574 | case 0x60: ts2020, stv6110, stb6100 |
575 | case 0xa0: eeprom */ | |
576 | default: { | |
577 | if (msg[j].flags == I2C_M_RD) { | |
578 | /* read registers */ | |
0065a79a MCC |
579 | u8 ibuf[MAX_XFER_SIZE]; |
580 | ||
581 | if (msg[j].len > sizeof(ibuf)) { | |
582 | warn("i2c rd: len=%d is too big!\n", | |
583 | msg[j].len); | |
324ed533 DC |
584 | ret = -EOPNOTSUPP; |
585 | goto unlock; | |
0065a79a MCC |
586 | } |
587 | ||
d51dbecc | 588 | dw210x_op_rw(d->udev, 0x91, 0, 0, |
141cc35e IL |
589 | ibuf, msg[j].len, |
590 | DW210X_READ_MSG); | |
591 | memcpy(msg[j].buf, ibuf, msg[j].len); | |
592 | break; | |
593 | } else if ((msg[j].buf[0] == 0xb0) && | |
594 | (msg[j].addr == 0x68)) { | |
595 | /* write firmware */ | |
596 | u8 obuf[19]; | |
597 | obuf[0] = (msg[j].len > 16 ? | |
598 | 18 : msg[j].len + 1); | |
599 | obuf[1] = msg[j].addr << 1; | |
600 | obuf[2] = msg[j].buf[0]; | |
601 | len = msg[j].len - 1; | |
602 | i = 1; | |
603 | do { | |
604 | memcpy(obuf + 3, msg[j].buf + i, | |
605 | (len > 16 ? 16 : len)); | |
d51dbecc | 606 | dw210x_op_rw(d->udev, 0x80, 0, 0, |
141cc35e IL |
607 | obuf, (len > 16 ? 16 : len) + 3, |
608 | DW210X_WRITE_MSG); | |
609 | i += 16; | |
610 | len -= 16; | |
611 | } while (len > 0); | |
a84adf40 | 612 | } else if (j < (num - 1)) { |
cd79d33e | 613 | /* write register addr before read */ |
0065a79a MCC |
614 | u8 obuf[MAX_XFER_SIZE]; |
615 | ||
616 | if (2 + msg[j].len > sizeof(obuf)) { | |
617 | warn("i2c wr: len=%d is too big!\n", | |
618 | msg[j].len); | |
324ed533 DC |
619 | ret = -EOPNOTSUPP; |
620 | goto unlock; | |
0065a79a MCC |
621 | } |
622 | ||
cd79d33e IL |
623 | obuf[0] = msg[j + 1].len; |
624 | obuf[1] = (msg[j].addr << 1); | |
625 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | |
d51dbecc | 626 | dw210x_op_rw(d->udev, |
1ad5d064 | 627 | le16_to_cpu(udev->descriptor.idProduct) == |
a84adf40 | 628 | 0x7500 ? 0x92 : 0x90, 0, 0, |
cd79d33e IL |
629 | obuf, msg[j].len + 2, |
630 | DW210X_WRITE_MSG); | |
631 | break; | |
141cc35e IL |
632 | } else { |
633 | /* write registers */ | |
0065a79a MCC |
634 | u8 obuf[MAX_XFER_SIZE]; |
635 | ||
636 | if (2 + msg[j].len > sizeof(obuf)) { | |
637 | warn("i2c wr: len=%d is too big!\n", | |
638 | msg[j].len); | |
324ed533 DC |
639 | ret = -EOPNOTSUPP; |
640 | goto unlock; | |
0065a79a | 641 | } |
141cc35e IL |
642 | obuf[0] = msg[j].len + 1; |
643 | obuf[1] = (msg[j].addr << 1); | |
644 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | |
d51dbecc | 645 | dw210x_op_rw(d->udev, 0x80, 0, 0, |
141cc35e IL |
646 | obuf, msg[j].len + 2, |
647 | DW210X_WRITE_MSG); | |
648 | break; | |
649 | } | |
650 | break; | |
651 | } | |
d0a1ddad | 652 | } |
d0a1ddad | 653 | } |
324ed533 | 654 | ret = num; |
d0a1ddad | 655 | |
324ed533 | 656 | unlock: |
d0a1ddad | 657 | mutex_unlock(&d->i2c_mutex); |
324ed533 | 658 | return ret; |
d0a1ddad IL |
659 | } |
660 | ||
d2ffc447 IL |
661 | static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
662 | int num) | |
663 | { | |
664 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
606142af | 665 | struct dw2102_state *state; |
d2ffc447 IL |
666 | |
667 | if (!d) | |
668 | return -ENODEV; | |
606142af JM |
669 | |
670 | state = d->priv; | |
671 | ||
d2ffc447 IL |
672 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
673 | return -EAGAIN; | |
606142af JM |
674 | if (mutex_lock_interruptible(&d->data_mutex) < 0) { |
675 | mutex_unlock(&d->i2c_mutex); | |
676 | return -EAGAIN; | |
677 | } | |
d2ffc447 IL |
678 | |
679 | switch (num) { | |
680 | case 1: | |
681 | switch (msg[0].addr) { | |
682 | case SU3000_STREAM_CTRL: | |
606142af JM |
683 | state->data[0] = msg[0].buf[0] + 0x36; |
684 | state->data[1] = 3; | |
685 | state->data[2] = 0; | |
686 | if (dvb_usb_generic_rw(d, state->data, 3, | |
687 | state->data, 0, 0) < 0) | |
d2ffc447 IL |
688 | err("i2c transfer failed."); |
689 | break; | |
690 | case DW2102_RC_QUERY: | |
606142af JM |
691 | state->data[0] = 0x10; |
692 | if (dvb_usb_generic_rw(d, state->data, 1, | |
693 | state->data, 2, 0) < 0) | |
d2ffc447 | 694 | err("i2c transfer failed."); |
606142af JM |
695 | msg[0].buf[1] = state->data[0]; |
696 | msg[0].buf[0] = state->data[1]; | |
d2ffc447 IL |
697 | break; |
698 | default: | |
699 | /* always i2c write*/ | |
606142af JM |
700 | state->data[0] = 0x08; |
701 | state->data[1] = msg[0].addr; | |
702 | state->data[2] = msg[0].len; | |
d2ffc447 | 703 | |
606142af | 704 | memcpy(&state->data[3], msg[0].buf, msg[0].len); |
d2ffc447 | 705 | |
606142af JM |
706 | if (dvb_usb_generic_rw(d, state->data, msg[0].len + 3, |
707 | state->data, 1, 0) < 0) | |
d2ffc447 IL |
708 | err("i2c transfer failed."); |
709 | ||
710 | } | |
711 | break; | |
712 | case 2: | |
713 | /* always i2c read */ | |
606142af JM |
714 | state->data[0] = 0x09; |
715 | state->data[1] = msg[0].len; | |
716 | state->data[2] = msg[1].len; | |
717 | state->data[3] = msg[0].addr; | |
718 | memcpy(&state->data[4], msg[0].buf, msg[0].len); | |
719 | ||
720 | if (dvb_usb_generic_rw(d, state->data, msg[0].len + 4, | |
721 | state->data, msg[1].len + 1, 0) < 0) | |
d2ffc447 IL |
722 | err("i2c transfer failed."); |
723 | ||
606142af | 724 | memcpy(msg[1].buf, &state->data[1], msg[1].len); |
d2ffc447 IL |
725 | break; |
726 | default: | |
727 | warn("more than 2 i2c messages at a time is not handled yet."); | |
728 | break; | |
729 | } | |
606142af | 730 | mutex_unlock(&d->data_mutex); |
d2ffc447 IL |
731 | mutex_unlock(&d->i2c_mutex); |
732 | return num; | |
733 | } | |
734 | ||
21b007b9 | 735 | static u32 dw210x_i2c_func(struct i2c_adapter *adapter) |
7fd4828f IL |
736 | { |
737 | return I2C_FUNC_I2C; | |
738 | } | |
739 | ||
740 | static struct i2c_algorithm dw2102_i2c_algo = { | |
741 | .master_xfer = dw2102_i2c_transfer, | |
21b007b9 IL |
742 | .functionality = dw210x_i2c_func, |
743 | }; | |
744 | ||
745 | static struct i2c_algorithm dw2102_serit_i2c_algo = { | |
746 | .master_xfer = dw2102_serit_i2c_transfer, | |
747 | .functionality = dw210x_i2c_func, | |
7fd4828f IL |
748 | }; |
749 | ||
8a4949b7 IL |
750 | static struct i2c_algorithm dw2102_earda_i2c_algo = { |
751 | .master_xfer = dw2102_earda_i2c_transfer, | |
752 | .functionality = dw210x_i2c_func, | |
753 | }; | |
754 | ||
fe03d5ee IL |
755 | static struct i2c_algorithm dw2104_i2c_algo = { |
756 | .master_xfer = dw2104_i2c_transfer, | |
21b007b9 | 757 | .functionality = dw210x_i2c_func, |
fe03d5ee IL |
758 | }; |
759 | ||
1dac77c9 IL |
760 | static struct i2c_algorithm dw3101_i2c_algo = { |
761 | .master_xfer = dw3101_i2c_transfer, | |
762 | .functionality = dw210x_i2c_func, | |
763 | }; | |
764 | ||
141cc35e IL |
765 | static struct i2c_algorithm s6x0_i2c_algo = { |
766 | .master_xfer = s6x0_i2c_transfer, | |
d0a1ddad IL |
767 | .functionality = dw210x_i2c_func, |
768 | }; | |
769 | ||
d2ffc447 IL |
770 | static struct i2c_algorithm su3000_i2c_algo = { |
771 | .master_xfer = su3000_i2c_transfer, | |
772 | .functionality = dw210x_i2c_func, | |
773 | }; | |
774 | ||
21b007b9 | 775 | static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) |
fe03d5ee IL |
776 | { |
777 | int i; | |
778 | u8 ibuf[] = {0, 0}; | |
779 | u8 eeprom[256], eepromline[16]; | |
780 | ||
781 | for (i = 0; i < 256; i++) { | |
21b007b9 | 782 | if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) { |
fe03d5ee IL |
783 | err("read eeprom failed."); |
784 | return -1; | |
785 | } else { | |
786 | eepromline[i%16] = ibuf[0]; | |
787 | eeprom[i] = ibuf[0]; | |
788 | } | |
789 | if ((i % 16) == 15) { | |
790 | deb_xfer("%02x: ", i - 15); | |
791 | debug_dump(eepromline, 16, deb_xfer); | |
792 | } | |
793 | } | |
1dac77c9 | 794 | |
fe03d5ee IL |
795 | memcpy(mac, eeprom + 8, 6); |
796 | return 0; | |
797 | }; | |
798 | ||
141cc35e | 799 | static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) |
d0a1ddad IL |
800 | { |
801 | int i, ret; | |
141cc35e IL |
802 | u8 ibuf[] = { 0 }, obuf[] = { 0 }; |
803 | u8 eeprom[256], eepromline[16]; | |
804 | struct i2c_msg msg[] = { | |
805 | { | |
806 | .addr = 0xa0 >> 1, | |
807 | .flags = 0, | |
808 | .buf = obuf, | |
809 | .len = 1, | |
810 | }, { | |
811 | .addr = 0xa0 >> 1, | |
812 | .flags = I2C_M_RD, | |
813 | .buf = ibuf, | |
814 | .len = 1, | |
815 | } | |
816 | }; | |
d0a1ddad IL |
817 | |
818 | for (i = 0; i < 256; i++) { | |
141cc35e IL |
819 | obuf[0] = i; |
820 | ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2); | |
821 | if (ret != 2) { | |
d0a1ddad IL |
822 | err("read eeprom failed."); |
823 | return -1; | |
824 | } else { | |
141cc35e IL |
825 | eepromline[i % 16] = ibuf[0]; |
826 | eeprom[i] = ibuf[0]; | |
d0a1ddad IL |
827 | } |
828 | ||
829 | if ((i % 16) == 15) { | |
830 | deb_xfer("%02x: ", i - 15); | |
831 | debug_dump(eepromline, 16, deb_xfer); | |
832 | } | |
833 | } | |
834 | ||
835 | memcpy(mac, eeprom + 16, 6); | |
836 | return 0; | |
837 | }; | |
838 | ||
d2ffc447 IL |
839 | static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
840 | { | |
841 | static u8 command_start[] = {0x00}; | |
842 | static u8 command_stop[] = {0x01}; | |
843 | struct i2c_msg msg = { | |
844 | .addr = SU3000_STREAM_CTRL, | |
845 | .flags = 0, | |
846 | .buf = onoff ? command_start : command_stop, | |
847 | .len = 1 | |
848 | }; | |
849 | ||
850 | i2c_transfer(&adap->dev->i2c_adap, &msg, 1); | |
851 | ||
852 | return 0; | |
853 | } | |
854 | ||
855 | static int su3000_power_ctrl(struct dvb_usb_device *d, int i) | |
856 | { | |
2c4ffe27 | 857 | struct dw2102_state *state = (struct dw2102_state *)d->priv; |
606142af | 858 | int ret = 0; |
d2ffc447 | 859 | |
0385443f | 860 | info("%s: %d, initialized %d", __func__, i, state->initialized); |
d2ffc447 IL |
861 | |
862 | if (i && !state->initialized) { | |
606142af JM |
863 | mutex_lock(&d->data_mutex); |
864 | ||
865 | state->data[0] = 0xde; | |
866 | state->data[1] = 0; | |
867 | ||
d2ffc447 IL |
868 | state->initialized = 1; |
869 | /* reset board */ | |
606142af JM |
870 | ret = dvb_usb_generic_rw(d, state->data, 2, NULL, 0, 0); |
871 | mutex_unlock(&d->data_mutex); | |
d2ffc447 IL |
872 | } |
873 | ||
606142af | 874 | return ret; |
d2ffc447 IL |
875 | } |
876 | ||
877 | static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | |
878 | { | |
879 | int i; | |
880 | u8 obuf[] = { 0x1f, 0xf0 }; | |
881 | u8 ibuf[] = { 0 }; | |
882 | struct i2c_msg msg[] = { | |
883 | { | |
884 | .addr = 0x51, | |
885 | .flags = 0, | |
886 | .buf = obuf, | |
887 | .len = 2, | |
888 | }, { | |
889 | .addr = 0x51, | |
890 | .flags = I2C_M_RD, | |
891 | .buf = ibuf, | |
892 | .len = 1, | |
893 | ||
894 | } | |
895 | }; | |
896 | ||
897 | for (i = 0; i < 6; i++) { | |
898 | obuf[1] = 0xf0 + i; | |
899 | if (i2c_transfer(&d->i2c_adap, msg, 2) != 2) | |
900 | break; | |
901 | else | |
902 | mac[i] = ibuf[0]; | |
d2ffc447 IL |
903 | } |
904 | ||
905 | return 0; | |
906 | } | |
907 | ||
908 | static int su3000_identify_state(struct usb_device *udev, | |
909 | struct dvb_usb_device_properties *props, | |
910 | struct dvb_usb_device_description **desc, | |
911 | int *cold) | |
912 | { | |
0385443f | 913 | info("%s", __func__); |
d2ffc447 IL |
914 | |
915 | *cold = 0; | |
916 | return 0; | |
917 | } | |
918 | ||
0df289a2 MCC |
919 | static int dw210x_set_voltage(struct dvb_frontend *fe, |
920 | enum fe_sec_voltage voltage) | |
7fd4828f | 921 | { |
cd79d33e IL |
922 | static u8 command_13v[] = {0x00, 0x01}; |
923 | static u8 command_18v[] = {0x01, 0x01}; | |
924 | static u8 command_off[] = {0x00, 0x00}; | |
925 | struct i2c_msg msg = { | |
926 | .addr = DW2102_VOLTAGE_CTRL, | |
927 | .flags = 0, | |
928 | .buf = command_off, | |
929 | .len = 2, | |
7fd4828f IL |
930 | }; |
931 | ||
932 | struct dvb_usb_adapter *udev_adap = | |
933 | (struct dvb_usb_adapter *)(fe->dvb->priv); | |
934 | if (voltage == SEC_VOLTAGE_18) | |
cd79d33e IL |
935 | msg.buf = command_18v; |
936 | else if (voltage == SEC_VOLTAGE_13) | |
937 | msg.buf = command_13v; | |
938 | ||
939 | i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); | |
940 | ||
7fd4828f IL |
941 | return 0; |
942 | } | |
943 | ||
0df289a2 MCC |
944 | static int s660_set_voltage(struct dvb_frontend *fe, |
945 | enum fe_sec_voltage voltage) | |
52c506e0 IL |
946 | { |
947 | struct dvb_usb_adapter *d = | |
948 | (struct dvb_usb_adapter *)(fe->dvb->priv); | |
2c4ffe27 | 949 | struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; |
52c506e0 IL |
950 | |
951 | dw210x_set_voltage(fe, voltage); | |
952 | if (st->old_set_voltage) | |
953 | st->old_set_voltage(fe, voltage); | |
954 | ||
955 | return 0; | |
956 | } | |
957 | ||
fa8bae10 IL |
958 | static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon) |
959 | { | |
960 | static u8 led_off[] = { 0 }; | |
961 | static u8 led_on[] = { 1 }; | |
962 | struct i2c_msg msg = { | |
963 | .addr = DW2102_LED_CTRL, | |
964 | .flags = 0, | |
965 | .buf = led_off, | |
966 | .len = 1 | |
967 | }; | |
968 | struct dvb_usb_adapter *udev_adap = | |
969 | (struct dvb_usb_adapter *)(fe->dvb->priv); | |
970 | ||
971 | if (offon) | |
972 | msg.buf = led_on; | |
973 | i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); | |
974 | } | |
975 | ||
0df289a2 MCC |
976 | static int tt_s2_4600_read_status(struct dvb_frontend *fe, |
977 | enum fe_status *status) | |
356484ca OS |
978 | { |
979 | struct dvb_usb_adapter *d = | |
980 | (struct dvb_usb_adapter *)(fe->dvb->priv); | |
981 | struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; | |
982 | int ret; | |
983 | ||
984 | ret = st->fe_read_status(fe, status); | |
985 | ||
986 | /* resync slave fifo when signal change from unlock to lock */ | |
987 | if ((*status & FE_HAS_LOCK) && (!st->last_lock)) | |
988 | su3000_streaming_ctrl(d, 1); | |
989 | ||
990 | st->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0; | |
991 | return ret; | |
992 | } | |
993 | ||
d4305c68 IL |
994 | static struct stv0299_config sharp_z0194a_config = { |
995 | .demod_address = 0x68, | |
996 | .inittab = sharp_z0194a_inittab, | |
997 | .mclk = 88000000UL, | |
998 | .invert = 1, | |
999 | .skip_reinit = 0, | |
1000 | .lock_output = STV0299_LOCKOUTPUT_1, | |
1001 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | |
1002 | .min_delay_ms = 100, | |
1003 | .set_symbol_rate = sharp_z0194a_set_symbol_rate, | |
1004 | }; | |
1005 | ||
fe03d5ee IL |
1006 | static struct cx24116_config dw2104_config = { |
1007 | .demod_address = 0x55, | |
cc8c4f3a | 1008 | .mpg_clk_pos_pol = 0x01, |
fe03d5ee IL |
1009 | }; |
1010 | ||
21b007b9 IL |
1011 | static struct si21xx_config serit_sp1511lhb_config = { |
1012 | .demod_address = 0x68, | |
1013 | .min_delay_ms = 100, | |
1014 | ||
1015 | }; | |
1016 | ||
1dac77c9 IL |
1017 | static struct tda10023_config dw3101_tda10023_config = { |
1018 | .demod_address = 0x0c, | |
1019 | .invert = 1, | |
1020 | }; | |
1021 | ||
d0a1ddad IL |
1022 | static struct mt312_config zl313_config = { |
1023 | .demod_address = 0x0e, | |
1024 | }; | |
1025 | ||
141cc35e IL |
1026 | static struct ds3000_config dw2104_ds3000_config = { |
1027 | .demod_address = 0x68, | |
1028 | }; | |
1029 | ||
03a67279 | 1030 | static struct ts2020_config dw2104_ts2020_config = { |
73f0af44 | 1031 | .tuner_address = 0x60, |
b858c331 | 1032 | .clk_out_div = 1, |
03a67279 | 1033 | .frequency_div = 1060000, |
73f0af44 KD |
1034 | }; |
1035 | ||
43385c8a IL |
1036 | static struct ds3000_config s660_ds3000_config = { |
1037 | .demod_address = 0x68, | |
b858c331 | 1038 | .ci_mode = 1, |
43385c8a IL |
1039 | .set_lock_led = dw210x_led_ctrl, |
1040 | }; | |
1041 | ||
03a67279 JH |
1042 | static struct ts2020_config s660_ts2020_config = { |
1043 | .tuner_address = 0x60, | |
1044 | .clk_out_div = 1, | |
1045 | .frequency_div = 1146000, | |
1046 | }; | |
1047 | ||
141cc35e IL |
1048 | static struct stv0900_config dw2104a_stv0900_config = { |
1049 | .demod_address = 0x6a, | |
1050 | .demod_mode = 0, | |
1051 | .xtal = 27000000, | |
1052 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | |
1053 | .diseqc_mode = 2,/* 2/3 PWM */ | |
1054 | .tun1_maddress = 0,/* 0x60 */ | |
1055 | .tun1_adc = 0,/* 2 Vpp */ | |
1056 | .path1_mode = 3, | |
1057 | }; | |
1058 | ||
1059 | static struct stb6100_config dw2104a_stb6100_config = { | |
1060 | .tuner_address = 0x60, | |
1061 | .refclock = 27000000, | |
1062 | }; | |
1063 | ||
1064 | static struct stv0900_config dw2104_stv0900_config = { | |
1065 | .demod_address = 0x68, | |
1066 | .demod_mode = 0, | |
1067 | .xtal = 8000000, | |
1068 | .clkmode = 3, | |
1069 | .diseqc_mode = 2, | |
1070 | .tun1_maddress = 0, | |
1071 | .tun1_adc = 1,/* 1 Vpp */ | |
1072 | .path1_mode = 3, | |
1073 | }; | |
1074 | ||
1075 | static struct stv6110_config dw2104_stv6110_config = { | |
1076 | .i2c_address = 0x60, | |
1077 | .mclk = 16000000, | |
1078 | .clk_div = 1, | |
1079 | }; | |
1080 | ||
cd79d33e IL |
1081 | static struct stv0900_config prof_7500_stv0900_config = { |
1082 | .demod_address = 0x6a, | |
1083 | .demod_mode = 0, | |
1084 | .xtal = 27000000, | |
1085 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | |
1086 | .diseqc_mode = 2,/* 2/3 PWM */ | |
1087 | .tun1_maddress = 0,/* 0x60 */ | |
1088 | .tun1_adc = 0,/* 2 Vpp */ | |
1089 | .path1_mode = 3, | |
1090 | .tun1_type = 3, | |
fa8bae10 | 1091 | .set_lock_led = dw210x_led_ctrl, |
cd79d33e IL |
1092 | }; |
1093 | ||
d2ffc447 IL |
1094 | static struct ds3000_config su3000_ds3000_config = { |
1095 | .demod_address = 0x68, | |
1096 | .ci_mode = 1, | |
b858c331 | 1097 | .set_lock_led = dw210x_led_ctrl, |
73f0af44 KD |
1098 | }; |
1099 | ||
51d882ed EP |
1100 | static struct cxd2820r_config cxd2820r_config = { |
1101 | .i2c_address = 0x6c, /* (0xd8 >> 1) */ | |
1102 | .ts_mode = 0x38, | |
7b71ef7e | 1103 | .ts_clock_inv = 1, |
51d882ed EP |
1104 | }; |
1105 | ||
1106 | static struct tda18271_config tda18271_config = { | |
1107 | .output_opt = TDA18271_OUTPUT_LT_OFF, | |
1108 | .gate = TDA18271_GATE_DIGITAL, | |
1109 | }; | |
1110 | ||
955d00ac IL |
1111 | static u8 m88rs2000_inittab[] = { |
1112 | DEMOD_WRITE, 0x9a, 0x30, | |
1113 | DEMOD_WRITE, 0x00, 0x01, | |
1114 | WRITE_DELAY, 0x19, 0x00, | |
1115 | DEMOD_WRITE, 0x00, 0x00, | |
1116 | DEMOD_WRITE, 0x9a, 0xb0, | |
1117 | DEMOD_WRITE, 0x81, 0xc1, | |
955d00ac IL |
1118 | DEMOD_WRITE, 0x81, 0x81, |
1119 | DEMOD_WRITE, 0x86, 0xc6, | |
1120 | DEMOD_WRITE, 0x9a, 0x30, | |
1121 | DEMOD_WRITE, 0xf0, 0x80, | |
1122 | DEMOD_WRITE, 0xf1, 0xbf, | |
1123 | DEMOD_WRITE, 0xb0, 0x45, | |
1124 | DEMOD_WRITE, 0xb2, 0x01, | |
1125 | DEMOD_WRITE, 0x9a, 0xb0, | |
1126 | 0xff, 0xaa, 0xff | |
1127 | }; | |
1128 | ||
1129 | static struct m88rs2000_config s421_m88rs2000_config = { | |
1130 | .demod_addr = 0x68, | |
955d00ac IL |
1131 | .inittab = m88rs2000_inittab, |
1132 | }; | |
1133 | ||
fe03d5ee IL |
1134 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) |
1135 | { | |
141cc35e IL |
1136 | struct dvb_tuner_ops *tuner_ops = NULL; |
1137 | ||
1138 | if (demod_probe & 4) { | |
77eed219 | 1139 | d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config, |
141cc35e | 1140 | &d->dev->i2c_adap, 0); |
77eed219 MK |
1141 | if (d->fe_adap[0].fe != NULL) { |
1142 | if (dvb_attach(stb6100_attach, d->fe_adap[0].fe, | |
141cc35e IL |
1143 | &dw2104a_stb6100_config, |
1144 | &d->dev->i2c_adap)) { | |
77eed219 | 1145 | tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops; |
141cc35e IL |
1146 | tuner_ops->set_frequency = stb6100_set_freq; |
1147 | tuner_ops->get_frequency = stb6100_get_freq; | |
1148 | tuner_ops->set_bandwidth = stb6100_set_bandw; | |
1149 | tuner_ops->get_bandwidth = stb6100_get_bandw; | |
77eed219 | 1150 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; |
0385443f | 1151 | info("Attached STV0900+STB6100!"); |
141cc35e IL |
1152 | return 0; |
1153 | } | |
1154 | } | |
1155 | } | |
1156 | ||
1157 | if (demod_probe & 2) { | |
77eed219 | 1158 | d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config, |
141cc35e | 1159 | &d->dev->i2c_adap, 0); |
77eed219 MK |
1160 | if (d->fe_adap[0].fe != NULL) { |
1161 | if (dvb_attach(stv6110_attach, d->fe_adap[0].fe, | |
141cc35e IL |
1162 | &dw2104_stv6110_config, |
1163 | &d->dev->i2c_adap)) { | |
77eed219 | 1164 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; |
0385443f | 1165 | info("Attached STV0900+STV6110A!"); |
141cc35e IL |
1166 | return 0; |
1167 | } | |
1168 | } | |
1169 | } | |
1170 | ||
1171 | if (demod_probe & 1) { | |
77eed219 | 1172 | d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config, |
141cc35e | 1173 | &d->dev->i2c_adap); |
77eed219 MK |
1174 | if (d->fe_adap[0].fe != NULL) { |
1175 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; | |
0385443f | 1176 | info("Attached cx24116!"); |
141cc35e IL |
1177 | return 0; |
1178 | } | |
1179 | } | |
1180 | ||
77eed219 | 1181 | d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config, |
141cc35e | 1182 | &d->dev->i2c_adap); |
77eed219 | 1183 | if (d->fe_adap[0].fe != NULL) { |
73f0af44 KD |
1184 | dvb_attach(ts2020_attach, d->fe_adap[0].fe, |
1185 | &dw2104_ts2020_config, &d->dev->i2c_adap); | |
77eed219 | 1186 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; |
0385443f | 1187 | info("Attached DS3000!"); |
fe03d5ee IL |
1188 | return 0; |
1189 | } | |
141cc35e | 1190 | |
fe03d5ee IL |
1191 | return -EIO; |
1192 | } | |
1193 | ||
21b007b9 | 1194 | static struct dvb_usb_device_properties dw2102_properties; |
b42e1d71 | 1195 | static struct dvb_usb_device_properties dw2104_properties; |
141cc35e | 1196 | static struct dvb_usb_device_properties s6x0_properties; |
21b007b9 | 1197 | |
7fd4828f IL |
1198 | static int dw2102_frontend_attach(struct dvb_usb_adapter *d) |
1199 | { | |
21b007b9 IL |
1200 | if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) { |
1201 | /*dw2102_properties.adapter->tuner_attach = NULL;*/ | |
77eed219 | 1202 | d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config, |
21b007b9 | 1203 | &d->dev->i2c_adap); |
77eed219 MK |
1204 | if (d->fe_adap[0].fe != NULL) { |
1205 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; | |
0385443f | 1206 | info("Attached si21xx!"); |
21b007b9 IL |
1207 | return 0; |
1208 | } | |
1209 | } | |
141cc35e | 1210 | |
8a4949b7 | 1211 | if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) { |
77eed219 | 1212 | d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config, |
8a4949b7 | 1213 | &d->dev->i2c_adap); |
77eed219 MK |
1214 | if (d->fe_adap[0].fe != NULL) { |
1215 | if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, | |
141cc35e | 1216 | &d->dev->i2c_adap)) { |
77eed219 | 1217 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; |
0385443f | 1218 | info("Attached stv0288!"); |
141cc35e IL |
1219 | return 0; |
1220 | } | |
8a4949b7 IL |
1221 | } |
1222 | } | |
1223 | ||
21b007b9 IL |
1224 | if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) { |
1225 | /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ | |
77eed219 | 1226 | d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, |
21b007b9 | 1227 | &d->dev->i2c_adap); |
77eed219 MK |
1228 | if (d->fe_adap[0].fe != NULL) { |
1229 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; | |
0385443f | 1230 | info("Attached stv0299!"); |
21b007b9 IL |
1231 | return 0; |
1232 | } | |
7fd4828f IL |
1233 | } |
1234 | return -EIO; | |
1235 | } | |
1236 | ||
1dac77c9 IL |
1237 | static int dw3101_frontend_attach(struct dvb_usb_adapter *d) |
1238 | { | |
77eed219 | 1239 | d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config, |
1dac77c9 | 1240 | &d->dev->i2c_adap, 0x48); |
77eed219 | 1241 | if (d->fe_adap[0].fe != NULL) { |
0385443f | 1242 | info("Attached tda10023!"); |
1dac77c9 IL |
1243 | return 0; |
1244 | } | |
1245 | return -EIO; | |
1246 | } | |
1247 | ||
195288da | 1248 | static int zl100313_frontend_attach(struct dvb_usb_adapter *d) |
d0a1ddad | 1249 | { |
77eed219 | 1250 | d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config, |
141cc35e | 1251 | &d->dev->i2c_adap); |
77eed219 MK |
1252 | if (d->fe_adap[0].fe != NULL) { |
1253 | if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60, | |
141cc35e | 1254 | &d->dev->i2c_adap)) { |
77eed219 | 1255 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; |
0385443f | 1256 | info("Attached zl100313+zl10039!"); |
141cc35e IL |
1257 | return 0; |
1258 | } | |
1259 | } | |
1260 | ||
195288da IL |
1261 | return -EIO; |
1262 | } | |
1263 | ||
1264 | static int stv0288_frontend_attach(struct dvb_usb_adapter *d) | |
1265 | { | |
fd5466d1 IL |
1266 | u8 obuf[] = {7, 1}; |
1267 | ||
77eed219 | 1268 | d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config, |
141cc35e | 1269 | &d->dev->i2c_adap); |
141cc35e | 1270 | |
77eed219 | 1271 | if (d->fe_adap[0].fe == NULL) |
fd5466d1 IL |
1272 | return -EIO; |
1273 | ||
77eed219 | 1274 | if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap)) |
fd5466d1 IL |
1275 | return -EIO; |
1276 | ||
77eed219 | 1277 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; |
fd5466d1 IL |
1278 | |
1279 | dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); | |
1280 | ||
0385443f | 1281 | info("Attached stv0288+stb6000!"); |
fd5466d1 IL |
1282 | |
1283 | return 0; | |
1284 | ||
195288da IL |
1285 | } |
1286 | ||
1287 | static int ds3000_frontend_attach(struct dvb_usb_adapter *d) | |
1288 | { | |
2c4ffe27 | 1289 | struct dw2102_state *st = d->dev->priv; |
5a530cbe | 1290 | u8 obuf[] = {7, 1}; |
52c506e0 | 1291 | |
43385c8a | 1292 | d->fe_adap[0].fe = dvb_attach(ds3000_attach, &s660_ds3000_config, |
141cc35e | 1293 | &d->dev->i2c_adap); |
141cc35e | 1294 | |
77eed219 | 1295 | if (d->fe_adap[0].fe == NULL) |
52c506e0 IL |
1296 | return -EIO; |
1297 | ||
03a67279 | 1298 | dvb_attach(ts2020_attach, d->fe_adap[0].fe, &s660_ts2020_config, |
73f0af44 KD |
1299 | &d->dev->i2c_adap); |
1300 | ||
77eed219 MK |
1301 | st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage; |
1302 | d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage; | |
5a530cbe IL |
1303 | |
1304 | dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); | |
1305 | ||
0385443f | 1306 | info("Attached ds3000+ts2020!"); |
52c506e0 IL |
1307 | |
1308 | return 0; | |
d0a1ddad IL |
1309 | } |
1310 | ||
cd79d33e IL |
1311 | static int prof_7500_frontend_attach(struct dvb_usb_adapter *d) |
1312 | { | |
4e59df8f IL |
1313 | u8 obuf[] = {7, 1}; |
1314 | ||
77eed219 | 1315 | d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config, |
cd79d33e | 1316 | &d->dev->i2c_adap, 0); |
77eed219 | 1317 | if (d->fe_adap[0].fe == NULL) |
cd79d33e | 1318 | return -EIO; |
4e59df8f | 1319 | |
77eed219 | 1320 | d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; |
cd79d33e | 1321 | |
4e59df8f IL |
1322 | dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); |
1323 | ||
0385443f | 1324 | info("Attached STV0900+STB6100A!"); |
cd79d33e IL |
1325 | |
1326 | return 0; | |
1327 | } | |
1328 | ||
606142af | 1329 | static int su3000_frontend_attach(struct dvb_usb_adapter *adap) |
d2ffc447 | 1330 | { |
606142af JM |
1331 | struct dvb_usb_device *d = adap->dev; |
1332 | struct dw2102_state *state = d->priv; | |
1333 | ||
1334 | mutex_lock(&d->data_mutex); | |
1335 | ||
1336 | state->data[0] = 0xe; | |
1337 | state->data[1] = 0x80; | |
1338 | state->data[2] = 0; | |
d2ffc447 | 1339 | |
606142af | 1340 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
d2ffc447 IL |
1341 | err("command 0x0e transfer failed."); |
1342 | ||
606142af JM |
1343 | state->data[0] = 0xe; |
1344 | state->data[1] = 0x02; | |
1345 | state->data[2] = 1; | |
b858c331 | 1346 | |
606142af | 1347 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
b858c331 IL |
1348 | err("command 0x0e transfer failed."); |
1349 | msleep(300); | |
1350 | ||
606142af JM |
1351 | state->data[0] = 0xe; |
1352 | state->data[1] = 0x83; | |
1353 | state->data[2] = 0; | |
d2ffc447 | 1354 | |
606142af | 1355 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
d2ffc447 IL |
1356 | err("command 0x0e transfer failed."); |
1357 | ||
606142af JM |
1358 | state->data[0] = 0xe; |
1359 | state->data[1] = 0x83; | |
1360 | state->data[2] = 1; | |
d2ffc447 | 1361 | |
606142af | 1362 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
d2ffc447 IL |
1363 | err("command 0x0e transfer failed."); |
1364 | ||
606142af | 1365 | state->data[0] = 0x51; |
d2ffc447 | 1366 | |
606142af | 1367 | if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0) |
d2ffc447 IL |
1368 | err("command 0x51 transfer failed."); |
1369 | ||
606142af JM |
1370 | mutex_unlock(&d->data_mutex); |
1371 | ||
1372 | adap->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config, | |
1373 | &d->i2c_adap); | |
1374 | if (adap->fe_adap[0].fe == NULL) | |
d2ffc447 IL |
1375 | return -EIO; |
1376 | ||
606142af | 1377 | if (dvb_attach(ts2020_attach, adap->fe_adap[0].fe, |
b858c331 | 1378 | &dw2104_ts2020_config, |
606142af | 1379 | &d->i2c_adap)) { |
0385443f | 1380 | info("Attached DS3000/TS2020!"); |
b858c331 IL |
1381 | return 0; |
1382 | } | |
d2ffc447 | 1383 | |
0385443f | 1384 | info("Failed to attach DS3000/TS2020!"); |
b858c331 | 1385 | return -EIO; |
d2ffc447 IL |
1386 | } |
1387 | ||
606142af | 1388 | static int t220_frontend_attach(struct dvb_usb_adapter *adap) |
51d882ed | 1389 | { |
606142af JM |
1390 | struct dvb_usb_device *d = adap->dev; |
1391 | struct dw2102_state *state = d->priv; | |
1392 | ||
1393 | mutex_lock(&d->data_mutex); | |
51d882ed | 1394 | |
606142af JM |
1395 | state->data[0] = 0xe; |
1396 | state->data[1] = 0x87; | |
1397 | state->data[2] = 0x0; | |
1398 | ||
1399 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) | |
51d882ed EP |
1400 | err("command 0x0e transfer failed."); |
1401 | ||
606142af JM |
1402 | state->data[0] = 0xe; |
1403 | state->data[1] = 0x86; | |
1404 | state->data[2] = 1; | |
7b71ef7e | 1405 | |
606142af | 1406 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
7b71ef7e C |
1407 | err("command 0x0e transfer failed."); |
1408 | ||
606142af JM |
1409 | state->data[0] = 0xe; |
1410 | state->data[1] = 0x80; | |
1411 | state->data[2] = 0; | |
51d882ed | 1412 | |
606142af | 1413 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
51d882ed EP |
1414 | err("command 0x0e transfer failed."); |
1415 | ||
7b71ef7e | 1416 | msleep(50); |
51d882ed | 1417 | |
606142af JM |
1418 | state->data[0] = 0xe; |
1419 | state->data[1] = 0x80; | |
1420 | state->data[2] = 1; | |
51d882ed | 1421 | |
606142af | 1422 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
51d882ed EP |
1423 | err("command 0x0e transfer failed."); |
1424 | ||
606142af | 1425 | state->data[0] = 0x51; |
51d882ed | 1426 | |
606142af | 1427 | if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0) |
51d882ed EP |
1428 | err("command 0x51 transfer failed."); |
1429 | ||
606142af JM |
1430 | mutex_unlock(&d->data_mutex); |
1431 | ||
1432 | adap->fe_adap[0].fe = dvb_attach(cxd2820r_attach, &cxd2820r_config, | |
1433 | &d->i2c_adap, NULL); | |
1434 | if (adap->fe_adap[0].fe != NULL) { | |
1435 | if (dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0x60, | |
1436 | &d->i2c_adap, &tda18271_config)) { | |
0385443f | 1437 | info("Attached TDA18271HD/CXD2820R!"); |
51d882ed EP |
1438 | return 0; |
1439 | } | |
1440 | } | |
1441 | ||
0385443f | 1442 | info("Failed to attach TDA18271HD/CXD2820R!"); |
51d882ed EP |
1443 | return -EIO; |
1444 | } | |
1445 | ||
606142af | 1446 | static int m88rs2000_frontend_attach(struct dvb_usb_adapter *adap) |
955d00ac | 1447 | { |
606142af JM |
1448 | struct dvb_usb_device *d = adap->dev; |
1449 | struct dw2102_state *state = d->priv; | |
1450 | ||
1451 | mutex_lock(&d->data_mutex); | |
955d00ac | 1452 | |
606142af JM |
1453 | state->data[0] = 0x51; |
1454 | ||
1455 | if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0) | |
955d00ac IL |
1456 | err("command 0x51 transfer failed."); |
1457 | ||
606142af | 1458 | mutex_unlock(&d->data_mutex); |
b858c331 | 1459 | |
606142af JM |
1460 | adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach, |
1461 | &s421_m88rs2000_config, | |
1462 | &d->i2c_adap); | |
1463 | ||
1464 | if (adap->fe_adap[0].fe == NULL) | |
955d00ac IL |
1465 | return -EIO; |
1466 | ||
606142af | 1467 | if (dvb_attach(ts2020_attach, adap->fe_adap[0].fe, |
b858c331 | 1468 | &dw2104_ts2020_config, |
606142af | 1469 | &d->i2c_adap)) { |
0385443f | 1470 | info("Attached RS2000/TS2020!"); |
b858c331 IL |
1471 | return 0; |
1472 | } | |
955d00ac | 1473 | |
0385443f | 1474 | info("Failed to attach RS2000/TS2020!"); |
b858c331 | 1475 | return -EIO; |
955d00ac IL |
1476 | } |
1477 | ||
27254c36 OS |
1478 | static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap) |
1479 | { | |
1480 | struct dvb_usb_device *d = adap->dev; | |
1481 | struct dw2102_state *state = d->priv; | |
27254c36 OS |
1482 | struct i2c_adapter *i2c_adapter; |
1483 | struct i2c_client *client; | |
f3c6abca OS |
1484 | struct i2c_board_info board_info; |
1485 | struct m88ds3103_platform_data m88ds3103_pdata = {}; | |
0fecb6c0 | 1486 | struct ts2020_config ts2020_config = {}; |
27254c36 | 1487 | |
606142af JM |
1488 | mutex_lock(&d->data_mutex); |
1489 | ||
1490 | state->data[0] = 0xe; | |
1491 | state->data[1] = 0x80; | |
1492 | state->data[2] = 0x0; | |
1493 | ||
1494 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) | |
27254c36 OS |
1495 | err("command 0x0e transfer failed."); |
1496 | ||
606142af JM |
1497 | state->data[0] = 0xe; |
1498 | state->data[1] = 0x02; | |
1499 | state->data[2] = 1; | |
27254c36 | 1500 | |
606142af | 1501 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
27254c36 OS |
1502 | err("command 0x0e transfer failed."); |
1503 | msleep(300); | |
1504 | ||
606142af JM |
1505 | state->data[0] = 0xe; |
1506 | state->data[1] = 0x83; | |
1507 | state->data[2] = 0; | |
27254c36 | 1508 | |
606142af | 1509 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
27254c36 OS |
1510 | err("command 0x0e transfer failed."); |
1511 | ||
606142af JM |
1512 | state->data[0] = 0xe; |
1513 | state->data[1] = 0x83; | |
1514 | state->data[2] = 1; | |
27254c36 | 1515 | |
606142af | 1516 | if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0) |
27254c36 OS |
1517 | err("command 0x0e transfer failed."); |
1518 | ||
606142af | 1519 | state->data[0] = 0x51; |
27254c36 | 1520 | |
606142af | 1521 | if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0) |
27254c36 OS |
1522 | err("command 0x51 transfer failed."); |
1523 | ||
606142af JM |
1524 | mutex_unlock(&d->data_mutex); |
1525 | ||
f3c6abca OS |
1526 | /* attach demod */ |
1527 | m88ds3103_pdata.clk = 27000000; | |
1528 | m88ds3103_pdata.i2c_wr_max = 33; | |
1529 | m88ds3103_pdata.ts_mode = M88DS3103_TS_CI; | |
1530 | m88ds3103_pdata.ts_clk = 16000; | |
1531 | m88ds3103_pdata.ts_clk_pol = 0; | |
1532 | m88ds3103_pdata.spec_inv = 0; | |
1533 | m88ds3103_pdata.agc = 0x99; | |
1534 | m88ds3103_pdata.agc_inv = 0; | |
1535 | m88ds3103_pdata.clk_out = M88DS3103_CLOCK_OUT_ENABLED; | |
1536 | m88ds3103_pdata.envelope_mode = 0; | |
1537 | m88ds3103_pdata.lnb_hv_pol = 1; | |
1538 | m88ds3103_pdata.lnb_en_pol = 0; | |
1539 | memset(&board_info, 0, sizeof(board_info)); | |
1540 | strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); | |
1541 | board_info.addr = 0x68; | |
1542 | board_info.platform_data = &m88ds3103_pdata; | |
1543 | request_module("m88ds3103"); | |
1544 | client = i2c_new_device(&d->i2c_adap, &board_info); | |
1545 | if (client == NULL || client->dev.driver == NULL) | |
27254c36 | 1546 | return -ENODEV; |
f3c6abca OS |
1547 | if (!try_module_get(client->dev.driver->owner)) { |
1548 | i2c_unregister_device(client); | |
1549 | return -ENODEV; | |
1550 | } | |
1551 | adap->fe_adap[0].fe = m88ds3103_pdata.get_dvb_frontend(client); | |
1552 | i2c_adapter = m88ds3103_pdata.get_i2c_adapter(client); | |
1553 | ||
1554 | state->i2c_client_demod = client; | |
27254c36 OS |
1555 | |
1556 | /* attach tuner */ | |
0fecb6c0 | 1557 | ts2020_config.fe = adap->fe_adap[0].fe; |
f3c6abca OS |
1558 | memset(&board_info, 0, sizeof(board_info)); |
1559 | strlcpy(board_info.type, "ts2022", I2C_NAME_SIZE); | |
1560 | board_info.addr = 0x60; | |
1561 | board_info.platform_data = &ts2020_config; | |
0fecb6c0 | 1562 | request_module("ts2020"); |
f3c6abca | 1563 | client = i2c_new_device(i2c_adapter, &board_info); |
27254c36 OS |
1564 | |
1565 | if (client == NULL || client->dev.driver == NULL) { | |
1566 | dvb_frontend_detach(adap->fe_adap[0].fe); | |
1567 | return -ENODEV; | |
1568 | } | |
1569 | ||
1570 | if (!try_module_get(client->dev.driver->owner)) { | |
1571 | i2c_unregister_device(client); | |
1572 | dvb_frontend_detach(adap->fe_adap[0].fe); | |
1573 | return -ENODEV; | |
1574 | } | |
1575 | ||
1576 | /* delegate signal strength measurement to tuner */ | |
1577 | adap->fe_adap[0].fe->ops.read_signal_strength = | |
1578 | adap->fe_adap[0].fe->ops.tuner_ops.get_rf_strength; | |
1579 | ||
1580 | state->i2c_client_tuner = client; | |
1581 | ||
356484ca OS |
1582 | /* hook fe: need to resync the slave fifo when signal locks */ |
1583 | state->fe_read_status = adap->fe_adap[0].fe->ops.read_status; | |
1584 | adap->fe_adap[0].fe->ops.read_status = tt_s2_4600_read_status; | |
1585 | ||
1586 | state->last_lock = 0; | |
1587 | ||
27254c36 OS |
1588 | return 0; |
1589 | } | |
1590 | ||
7fd4828f IL |
1591 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) |
1592 | { | |
77eed219 | 1593 | dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, |
7fd4828f IL |
1594 | &adap->dev->i2c_adap, DVB_PLL_OPERA1); |
1595 | return 0; | |
1596 | } | |
1597 | ||
1dac77c9 IL |
1598 | static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) |
1599 | { | |
77eed219 | 1600 | dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, |
1dac77c9 IL |
1601 | &adap->dev->i2c_adap, DVB_PLL_TUA6034); |
1602 | ||
1603 | return 0; | |
1604 | } | |
1605 | ||
a49de26a EP |
1606 | static int dw2102_rc_query(struct dvb_usb_device *d) |
1607 | { | |
1608 | u8 key[2]; | |
1609 | struct i2c_msg msg = { | |
1610 | .addr = DW2102_RC_QUERY, | |
1611 | .flags = I2C_M_RD, | |
1612 | .buf = key, | |
1613 | .len = 2 | |
1614 | }; | |
7fd4828f | 1615 | |
a49de26a EP |
1616 | if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { |
1617 | if (msg.buf[0] != 0xff) { | |
1618 | deb_rc("%s: rc code: %x, %x\n", | |
1619 | __func__, key[0], key[1]); | |
120703f9 | 1620 | rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0], 0); |
a49de26a EP |
1621 | } |
1622 | } | |
d2ffc447 | 1623 | |
a49de26a EP |
1624 | return 0; |
1625 | } | |
7fd4828f | 1626 | |
a49de26a | 1627 | static int prof_rc_query(struct dvb_usb_device *d) |
7fd4828f | 1628 | { |
7fd4828f | 1629 | u8 key[2]; |
8a8dad71 IL |
1630 | struct i2c_msg msg = { |
1631 | .addr = DW2102_RC_QUERY, | |
1632 | .flags = I2C_M_RD, | |
1633 | .buf = key, | |
1634 | .len = 2 | |
7fd4828f | 1635 | }; |
8a8dad71 | 1636 | |
a49de26a EP |
1637 | if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { |
1638 | if (msg.buf[0] != 0xff) { | |
1639 | deb_rc("%s: rc code: %x, %x\n", | |
1640 | __func__, key[0], key[1]); | |
120703f9 | 1641 | rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0]^0xff, 0); |
7fd4828f | 1642 | } |
a49de26a | 1643 | } |
8a8dad71 | 1644 | |
a49de26a EP |
1645 | return 0; |
1646 | } | |
1647 | ||
1648 | static int su3000_rc_query(struct dvb_usb_device *d) | |
1649 | { | |
1650 | u8 key[2]; | |
1651 | struct i2c_msg msg = { | |
1652 | .addr = DW2102_RC_QUERY, | |
1653 | .flags = I2C_M_RD, | |
1654 | .buf = key, | |
1655 | .len = 2 | |
1656 | }; | |
8a8dad71 | 1657 | |
a49de26a EP |
1658 | if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { |
1659 | if (msg.buf[0] != 0xff) { | |
1660 | deb_rc("%s: rc code: %x, %x\n", | |
1661 | __func__, key[0], key[1]); | |
120703f9 DH |
1662 | rc_keydown(d->rc_dev, RC_TYPE_RC5, |
1663 | RC_SCANCODE_RC5(key[1], key[0]), 0); | |
a49de26a | 1664 | } |
7fd4828f | 1665 | } |
8a8dad71 | 1666 | |
7fd4828f IL |
1667 | return 0; |
1668 | } | |
1669 | ||
27351b13 JN |
1670 | enum dw2102_table_entry { |
1671 | CYPRESS_DW2102, | |
1672 | CYPRESS_DW2101, | |
1673 | CYPRESS_DW2104, | |
1674 | TEVII_S650, | |
1675 | TERRATEC_CINERGY_S, | |
1676 | CYPRESS_DW3101, | |
1677 | TEVII_S630, | |
1678 | PROF_1100, | |
1679 | TEVII_S660, | |
1680 | PROF_7500, | |
1681 | GENIATECH_SU3000, | |
1682 | TERRATEC_CINERGY_S2, | |
1683 | TEVII_S480_1, | |
1684 | TEVII_S480_2, | |
1685 | X3M_SPC1400HD, | |
955d00ac IL |
1686 | TEVII_S421, |
1687 | TEVII_S632, | |
44122dd6 | 1688 | TERRATEC_CINERGY_S2_R2, |
49438d97 | 1689 | TERRATEC_CINERGY_S2_R3, |
69fd825c | 1690 | TERRATEC_CINERGY_S2_R4, |
f08e9f0d | 1691 | GOTVIEW_SAT_HD, |
51d882ed | 1692 | GENIATECH_T220, |
27254c36 | 1693 | TECHNOTREND_S2_4600, |
44767fc4 OS |
1694 | TEVII_S482_1, |
1695 | TEVII_S482_2, | |
93b66420 | 1696 | TERRATEC_CINERGY_S2_BOX, |
6ede20f9 | 1697 | TEVII_S662 |
27351b13 JN |
1698 | }; |
1699 | ||
7fd4828f | 1700 | static struct usb_device_id dw2102_table[] = { |
27351b13 JN |
1701 | [CYPRESS_DW2102] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, |
1702 | [CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, | |
1703 | [CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)}, | |
1704 | [TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)}, | |
e8364275 | 1705 | [TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S)}, |
27351b13 JN |
1706 | [CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, |
1707 | [TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, | |
1708 | [PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, | |
1709 | [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, | |
1710 | [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)}, | |
1711 | [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)}, | |
a561d768 | 1712 | [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R1)}, |
27351b13 JN |
1713 | [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)}, |
1714 | [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)}, | |
1715 | [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)}, | |
955d00ac IL |
1716 | [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)}, |
1717 | [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, | |
a561d768 | 1718 | [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R2)}, |
49438d97 | 1719 | [TERRATEC_CINERGY_S2_R3] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R3)}, |
69fd825c | 1720 | [TERRATEC_CINERGY_S2_R4] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4)}, |
f08e9f0d | 1721 | [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, |
51d882ed | 1722 | [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, |
27254c36 OS |
1723 | [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND, |
1724 | USB_PID_TECHNOTREND_CONNECT_S2_4600)}, | |
44767fc4 OS |
1725 | [TEVII_S482_1] = {USB_DEVICE(0x9022, 0xd483)}, |
1726 | [TEVII_S482_2] = {USB_DEVICE(0x9022, 0xd484)}, | |
93b66420 | 1727 | [TERRATEC_CINERGY_S2_BOX] = {USB_DEVICE(USB_VID_TERRATEC, 0x0105)}, |
6ede20f9 | 1728 | [TEVII_S662] = {USB_DEVICE(0x9022, USB_PID_TEVII_S662)}, |
7fd4828f IL |
1729 | { } |
1730 | }; | |
1731 | ||
1732 | MODULE_DEVICE_TABLE(usb, dw2102_table); | |
1733 | ||
1734 | static int dw2102_load_firmware(struct usb_device *dev, | |
1735 | const struct firmware *frmwr) | |
1736 | { | |
1737 | u8 *b, *p; | |
1738 | int ret = 0, i; | |
1739 | u8 reset; | |
8a4949b7 | 1740 | u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; |
7fd4828f | 1741 | const struct firmware *fw; |
d0a1ddad | 1742 | |
1ad5d064 | 1743 | switch (le16_to_cpu(dev->descriptor.idProduct)) { |
7fd4828f | 1744 | case 0x2101: |
6823627b | 1745 | ret = request_firmware(&fw, DW2101_FIRMWARE, &dev->dev); |
7fd4828f | 1746 | if (ret != 0) { |
6823627b | 1747 | err(err_str, DW2101_FIRMWARE); |
7fd4828f IL |
1748 | return ret; |
1749 | } | |
1750 | break; | |
fe03d5ee | 1751 | default: |
7fd4828f IL |
1752 | fw = frmwr; |
1753 | break; | |
1754 | } | |
fe03d5ee | 1755 | info("start downloading DW210X firmware"); |
7fd4828f IL |
1756 | p = kmalloc(fw->size, GFP_KERNEL); |
1757 | reset = 1; | |
1758 | /*stop the CPU*/ | |
21b007b9 IL |
1759 | dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG); |
1760 | dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG); | |
7fd4828f IL |
1761 | |
1762 | if (p != NULL) { | |
1763 | memcpy(p, fw->data, fw->size); | |
1764 | for (i = 0; i < fw->size; i += 0x40) { | |
1765 | b = (u8 *) p + i; | |
21b007b9 IL |
1766 | if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40, |
1767 | DW210X_WRITE_MSG) != 0x40) { | |
7fd4828f IL |
1768 | err("error while transferring firmware"); |
1769 | ret = -EINVAL; | |
1770 | break; | |
1771 | } | |
1772 | } | |
1773 | /* restart the CPU */ | |
1774 | reset = 0; | |
21b007b9 IL |
1775 | if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, |
1776 | DW210X_WRITE_MSG) != 1) { | |
7fd4828f IL |
1777 | err("could not restart the USB controller CPU."); |
1778 | ret = -EINVAL; | |
1779 | } | |
21b007b9 IL |
1780 | if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, |
1781 | DW210X_WRITE_MSG) != 1) { | |
7fd4828f IL |
1782 | err("could not restart the USB controller CPU."); |
1783 | ret = -EINVAL; | |
1784 | } | |
1785 | /* init registers */ | |
1ad5d064 | 1786 | switch (le16_to_cpu(dev->descriptor.idProduct)) { |
1dac77c9 | 1787 | case USB_PID_TEVII_S650: |
a49de26a | 1788 | dw2104_properties.rc.core.rc_codes = RC_MAP_TEVII_NEC; |
b42e1d71 | 1789 | case USB_PID_DW2104: |
fe03d5ee | 1790 | reset = 1; |
21b007b9 IL |
1791 | dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, |
1792 | DW210X_WRITE_MSG); | |
1dac77c9 IL |
1793 | /* break omitted intentionally */ |
1794 | case USB_PID_DW3101: | |
fe03d5ee | 1795 | reset = 0; |
21b007b9 IL |
1796 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, |
1797 | DW210X_WRITE_MSG); | |
fe03d5ee | 1798 | break; |
e8364275 | 1799 | case USB_PID_TERRATEC_CINERGY_S: |
7fd4828f | 1800 | case USB_PID_DW2102: |
21b007b9 IL |
1801 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, |
1802 | DW210X_WRITE_MSG); | |
1803 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, | |
1804 | DW210X_READ_MSG); | |
1805 | /* check STV0299 frontend */ | |
1806 | dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2, | |
1807 | DW210X_READ_MSG); | |
ea023df5 | 1808 | if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) { |
21b007b9 | 1809 | dw2102_properties.i2c_algo = &dw2102_i2c_algo; |
77eed219 | 1810 | dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach; |
8a4949b7 IL |
1811 | break; |
1812 | } else { | |
1813 | /* check STV0288 frontend */ | |
1814 | reset16[0] = 0xd0; | |
1815 | reset16[1] = 1; | |
1816 | reset16[2] = 0; | |
1817 | dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3, | |
1818 | DW210X_WRITE_MSG); | |
1819 | dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3, | |
1820 | DW210X_READ_MSG); | |
1821 | if (reset16[2] == 0x11) { | |
1822 | dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo; | |
8a4949b7 IL |
1823 | break; |
1824 | } | |
1825 | } | |
7fd4828f | 1826 | case 0x2101: |
21b007b9 IL |
1827 | dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, |
1828 | DW210X_READ_MSG); | |
1829 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, | |
1830 | DW210X_READ_MSG); | |
1831 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, | |
1832 | DW210X_READ_MSG); | |
1833 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, | |
1834 | DW210X_READ_MSG); | |
7fd4828f IL |
1835 | break; |
1836 | } | |
1dac77c9 | 1837 | |
fe03d5ee | 1838 | msleep(100); |
7fd4828f IL |
1839 | kfree(p); |
1840 | } | |
2a518f8e SM |
1841 | |
1842 | if (le16_to_cpu(dev->descriptor.idProduct) == 0x2101) | |
1843 | release_firmware(fw); | |
7fd4828f IL |
1844 | return ret; |
1845 | } | |
1846 | ||
1847 | static struct dvb_usb_device_properties dw2102_properties = { | |
1848 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | |
1849 | .usb_ctrl = DEVICE_SPECIFIC, | |
6823627b | 1850 | .firmware = DW2102_FIRMWARE, |
7fd4828f IL |
1851 | .no_reconnect = 1, |
1852 | ||
21b007b9 | 1853 | .i2c_algo = &dw2102_serit_i2c_algo, |
f72a27b8 | 1854 | |
a49de26a | 1855 | .rc.core = { |
f72a27b8 | 1856 | .rc_interval = 150, |
a49de26a EP |
1857 | .rc_codes = RC_MAP_DM1105_NEC, |
1858 | .module_name = "dw2102", | |
1859 | .allowed_protos = RC_BIT_NEC, | |
f72a27b8 MCC |
1860 | .rc_query = dw2102_rc_query, |
1861 | }, | |
7fd4828f IL |
1862 | |
1863 | .generic_bulk_ctrl_endpoint = 0x81, | |
1864 | /* parameter for the MPEG2-data transfer */ | |
1865 | .num_adapters = 1, | |
1866 | .download_firmware = dw2102_load_firmware, | |
21b007b9 | 1867 | .read_mac_address = dw210x_read_mac_address, |
1dac77c9 | 1868 | .adapter = { |
7fd4828f | 1869 | { |
77eed219 MK |
1870 | .num_frontends = 1, |
1871 | .fe = {{ | |
7fd4828f | 1872 | .frontend_attach = dw2102_frontend_attach, |
7fd4828f IL |
1873 | .stream = { |
1874 | .type = USB_BULK, | |
1875 | .count = 8, | |
1876 | .endpoint = 0x82, | |
1877 | .u = { | |
1878 | .bulk = { | |
1879 | .buffersize = 4096, | |
1880 | } | |
1881 | } | |
1882 | }, | |
77eed219 | 1883 | }}, |
7fd4828f IL |
1884 | } |
1885 | }, | |
4cc0edff | 1886 | .num_device_descs = 3, |
7fd4828f IL |
1887 | .devices = { |
1888 | {"DVBWorld DVB-S 2102 USB2.0", | |
27351b13 | 1889 | {&dw2102_table[CYPRESS_DW2102], NULL}, |
7fd4828f IL |
1890 | {NULL}, |
1891 | }, | |
1892 | {"DVBWorld DVB-S 2101 USB2.0", | |
27351b13 | 1893 | {&dw2102_table[CYPRESS_DW2101], NULL}, |
7fd4828f | 1894 | {NULL}, |
4cc0edff IL |
1895 | }, |
1896 | {"TerraTec Cinergy S USB", | |
27351b13 | 1897 | {&dw2102_table[TERRATEC_CINERGY_S], NULL}, |
4cc0edff | 1898 | {NULL}, |
7fd4828f IL |
1899 | }, |
1900 | } | |
1901 | }; | |
1902 | ||
fe03d5ee IL |
1903 | static struct dvb_usb_device_properties dw2104_properties = { |
1904 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | |
1905 | .usb_ctrl = DEVICE_SPECIFIC, | |
6823627b | 1906 | .firmware = DW2104_FIRMWARE, |
fe03d5ee IL |
1907 | .no_reconnect = 1, |
1908 | ||
1909 | .i2c_algo = &dw2104_i2c_algo, | |
a49de26a | 1910 | .rc.core = { |
f72a27b8 | 1911 | .rc_interval = 150, |
a49de26a EP |
1912 | .rc_codes = RC_MAP_DM1105_NEC, |
1913 | .module_name = "dw2102", | |
1914 | .allowed_protos = RC_BIT_NEC, | |
f72a27b8 MCC |
1915 | .rc_query = dw2102_rc_query, |
1916 | }, | |
fe03d5ee IL |
1917 | |
1918 | .generic_bulk_ctrl_endpoint = 0x81, | |
1919 | /* parameter for the MPEG2-data transfer */ | |
1920 | .num_adapters = 1, | |
1921 | .download_firmware = dw2102_load_firmware, | |
21b007b9 | 1922 | .read_mac_address = dw210x_read_mac_address, |
fe03d5ee IL |
1923 | .adapter = { |
1924 | { | |
77eed219 MK |
1925 | .num_frontends = 1, |
1926 | .fe = {{ | |
fe03d5ee | 1927 | .frontend_attach = dw2104_frontend_attach, |
fe03d5ee IL |
1928 | .stream = { |
1929 | .type = USB_BULK, | |
1930 | .count = 8, | |
1931 | .endpoint = 0x82, | |
1932 | .u = { | |
1933 | .bulk = { | |
1934 | .buffersize = 4096, | |
1935 | } | |
1936 | } | |
1937 | }, | |
77eed219 | 1938 | }}, |
fe03d5ee IL |
1939 | } |
1940 | }, | |
1941 | .num_device_descs = 2, | |
1942 | .devices = { | |
1943 | { "DVBWorld DW2104 USB2.0", | |
27351b13 | 1944 | {&dw2102_table[CYPRESS_DW2104], NULL}, |
fe03d5ee IL |
1945 | {NULL}, |
1946 | }, | |
1947 | { "TeVii S650 USB2.0", | |
27351b13 | 1948 | {&dw2102_table[TEVII_S650], NULL}, |
fe03d5ee IL |
1949 | {NULL}, |
1950 | }, | |
1951 | } | |
1952 | }; | |
1953 | ||
1dac77c9 IL |
1954 | static struct dvb_usb_device_properties dw3101_properties = { |
1955 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | |
1956 | .usb_ctrl = DEVICE_SPECIFIC, | |
6823627b | 1957 | .firmware = DW3101_FIRMWARE, |
1dac77c9 IL |
1958 | .no_reconnect = 1, |
1959 | ||
1960 | .i2c_algo = &dw3101_i2c_algo, | |
a49de26a | 1961 | .rc.core = { |
f72a27b8 | 1962 | .rc_interval = 150, |
a49de26a EP |
1963 | .rc_codes = RC_MAP_DM1105_NEC, |
1964 | .module_name = "dw2102", | |
1965 | .allowed_protos = RC_BIT_NEC, | |
f72a27b8 MCC |
1966 | .rc_query = dw2102_rc_query, |
1967 | }, | |
1dac77c9 IL |
1968 | |
1969 | .generic_bulk_ctrl_endpoint = 0x81, | |
1970 | /* parameter for the MPEG2-data transfer */ | |
1971 | .num_adapters = 1, | |
1972 | .download_firmware = dw2102_load_firmware, | |
1973 | .read_mac_address = dw210x_read_mac_address, | |
1974 | .adapter = { | |
1975 | { | |
77eed219 MK |
1976 | .num_frontends = 1, |
1977 | .fe = {{ | |
1dac77c9 | 1978 | .frontend_attach = dw3101_frontend_attach, |
1dac77c9 IL |
1979 | .tuner_attach = dw3101_tuner_attach, |
1980 | .stream = { | |
1981 | .type = USB_BULK, | |
1982 | .count = 8, | |
1983 | .endpoint = 0x82, | |
1984 | .u = { | |
1985 | .bulk = { | |
1986 | .buffersize = 4096, | |
1987 | } | |
1988 | } | |
1989 | }, | |
77eed219 | 1990 | }}, |
1dac77c9 IL |
1991 | } |
1992 | }, | |
1993 | .num_device_descs = 1, | |
1994 | .devices = { | |
1995 | { "DVBWorld DVB-C 3101 USB2.0", | |
27351b13 | 1996 | {&dw2102_table[CYPRESS_DW3101], NULL}, |
1dac77c9 IL |
1997 | {NULL}, |
1998 | }, | |
1999 | } | |
2000 | }; | |
2001 | ||
141cc35e | 2002 | static struct dvb_usb_device_properties s6x0_properties = { |
d0a1ddad IL |
2003 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
2004 | .usb_ctrl = DEVICE_SPECIFIC, | |
2c4ffe27 | 2005 | .size_of_priv = sizeof(struct dw2102_state), |
6823627b | 2006 | .firmware = S630_FIRMWARE, |
d0a1ddad IL |
2007 | .no_reconnect = 1, |
2008 | ||
141cc35e | 2009 | .i2c_algo = &s6x0_i2c_algo, |
a49de26a | 2010 | .rc.core = { |
f72a27b8 | 2011 | .rc_interval = 150, |
a49de26a EP |
2012 | .rc_codes = RC_MAP_TEVII_NEC, |
2013 | .module_name = "dw2102", | |
2014 | .allowed_protos = RC_BIT_NEC, | |
f72a27b8 MCC |
2015 | .rc_query = dw2102_rc_query, |
2016 | }, | |
d0a1ddad IL |
2017 | |
2018 | .generic_bulk_ctrl_endpoint = 0x81, | |
2019 | .num_adapters = 1, | |
2020 | .download_firmware = dw2102_load_firmware, | |
141cc35e | 2021 | .read_mac_address = s6x0_read_mac_address, |
d0a1ddad IL |
2022 | .adapter = { |
2023 | { | |
77eed219 MK |
2024 | .num_frontends = 1, |
2025 | .fe = {{ | |
195288da | 2026 | .frontend_attach = zl100313_frontend_attach, |
d0a1ddad IL |
2027 | .stream = { |
2028 | .type = USB_BULK, | |
2029 | .count = 8, | |
2030 | .endpoint = 0x82, | |
2031 | .u = { | |
2032 | .bulk = { | |
2033 | .buffersize = 4096, | |
2034 | } | |
2035 | } | |
2036 | }, | |
77eed219 | 2037 | }}, |
d0a1ddad IL |
2038 | } |
2039 | }, | |
195288da | 2040 | .num_device_descs = 1, |
d0a1ddad IL |
2041 | .devices = { |
2042 | {"TeVii S630 USB", | |
27351b13 | 2043 | {&dw2102_table[TEVII_S630], NULL}, |
d0a1ddad IL |
2044 | {NULL}, |
2045 | }, | |
2046 | } | |
2047 | }; | |
2048 | ||
1ad5d064 | 2049 | static struct dvb_usb_device_properties *p1100; |
195288da IL |
2050 | static struct dvb_usb_device_description d1100 = { |
2051 | "Prof 1100 USB ", | |
27351b13 | 2052 | {&dw2102_table[PROF_1100], NULL}, |
195288da IL |
2053 | {NULL}, |
2054 | }; | |
2055 | ||
1ad5d064 | 2056 | static struct dvb_usb_device_properties *s660; |
195288da IL |
2057 | static struct dvb_usb_device_description d660 = { |
2058 | "TeVii S660 USB", | |
27351b13 | 2059 | {&dw2102_table[TEVII_S660], NULL}, |
195288da IL |
2060 | {NULL}, |
2061 | }; | |
2062 | ||
e8f5055a IL |
2063 | static struct dvb_usb_device_description d480_1 = { |
2064 | "TeVii S480.1 USB", | |
27351b13 | 2065 | {&dw2102_table[TEVII_S480_1], NULL}, |
e8f5055a IL |
2066 | {NULL}, |
2067 | }; | |
2068 | ||
2069 | static struct dvb_usb_device_description d480_2 = { | |
2070 | "TeVii S480.2 USB", | |
27351b13 | 2071 | {&dw2102_table[TEVII_S480_2], NULL}, |
e8f5055a IL |
2072 | {NULL}, |
2073 | }; | |
2074 | ||
1ad5d064 | 2075 | static struct dvb_usb_device_properties *p7500; |
cd79d33e IL |
2076 | static struct dvb_usb_device_description d7500 = { |
2077 | "Prof 7500 USB DVB-S2", | |
27351b13 | 2078 | {&dw2102_table[PROF_7500], NULL}, |
cd79d33e IL |
2079 | {NULL}, |
2080 | }; | |
2081 | ||
1ad5d064 | 2082 | static struct dvb_usb_device_properties *s421; |
955d00ac IL |
2083 | static struct dvb_usb_device_description d421 = { |
2084 | "TeVii S421 PCI", | |
2085 | {&dw2102_table[TEVII_S421], NULL}, | |
2086 | {NULL}, | |
2087 | }; | |
2088 | ||
2089 | static struct dvb_usb_device_description d632 = { | |
2090 | "TeVii S632 USB", | |
2091 | {&dw2102_table[TEVII_S632], NULL}, | |
2092 | {NULL}, | |
2093 | }; | |
2094 | ||
d2ffc447 IL |
2095 | static struct dvb_usb_device_properties su3000_properties = { |
2096 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | |
2097 | .usb_ctrl = DEVICE_SPECIFIC, | |
2c4ffe27 | 2098 | .size_of_priv = sizeof(struct dw2102_state), |
d2ffc447 IL |
2099 | .power_ctrl = su3000_power_ctrl, |
2100 | .num_adapters = 1, | |
2101 | .identify_state = su3000_identify_state, | |
2102 | .i2c_algo = &su3000_i2c_algo, | |
2103 | ||
a49de26a | 2104 | .rc.core = { |
d2ffc447 | 2105 | .rc_interval = 150, |
a49de26a EP |
2106 | .rc_codes = RC_MAP_SU3000, |
2107 | .module_name = "dw2102", | |
2108 | .allowed_protos = RC_BIT_RC5, | |
2109 | .rc_query = su3000_rc_query, | |
d2ffc447 IL |
2110 | }, |
2111 | ||
2112 | .read_mac_address = su3000_read_mac_address, | |
2113 | ||
2114 | .generic_bulk_ctrl_endpoint = 0x01, | |
2115 | ||
2116 | .adapter = { | |
2117 | { | |
77eed219 MK |
2118 | .num_frontends = 1, |
2119 | .fe = {{ | |
d2ffc447 IL |
2120 | .streaming_ctrl = su3000_streaming_ctrl, |
2121 | .frontend_attach = su3000_frontend_attach, | |
2122 | .stream = { | |
2123 | .type = USB_BULK, | |
2124 | .count = 8, | |
2125 | .endpoint = 0x82, | |
2126 | .u = { | |
2127 | .bulk = { | |
2128 | .buffersize = 4096, | |
2129 | } | |
2130 | } | |
2131 | } | |
77eed219 | 2132 | }}, |
d2ffc447 IL |
2133 | } |
2134 | }, | |
49438d97 | 2135 | .num_device_descs = 6, |
d2ffc447 IL |
2136 | .devices = { |
2137 | { "SU3000HD DVB-S USB2.0", | |
27351b13 | 2138 | { &dw2102_table[GENIATECH_SU3000], NULL }, |
d2ffc447 IL |
2139 | { NULL }, |
2140 | }, | |
2adc591f | 2141 | { "Terratec Cinergy S2 USB HD", |
27351b13 | 2142 | { &dw2102_table[TERRATEC_CINERGY_S2], NULL }, |
2adc591f IL |
2143 | { NULL }, |
2144 | }, | |
5265ea54 | 2145 | { "X3M TV SPC1400HD PCI", |
27351b13 | 2146 | { &dw2102_table[X3M_SPC1400HD], NULL }, |
5265ea54 IL |
2147 | { NULL }, |
2148 | }, | |
44122dd6 IL |
2149 | { "Terratec Cinergy S2 USB HD Rev.2", |
2150 | { &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL }, | |
2151 | { NULL }, | |
2152 | }, | |
49438d97 OS |
2153 | { "Terratec Cinergy S2 USB HD Rev.3", |
2154 | { &dw2102_table[TERRATEC_CINERGY_S2_R3], NULL }, | |
2155 | { NULL }, | |
2156 | }, | |
f08e9f0d AP |
2157 | { "GOTVIEW Satellite HD", |
2158 | { &dw2102_table[GOTVIEW_SAT_HD], NULL }, | |
2159 | { NULL }, | |
2160 | }, | |
d2ffc447 IL |
2161 | } |
2162 | }; | |
2163 | ||
51d882ed EP |
2164 | static struct dvb_usb_device_properties t220_properties = { |
2165 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | |
2166 | .usb_ctrl = DEVICE_SPECIFIC, | |
2c4ffe27 | 2167 | .size_of_priv = sizeof(struct dw2102_state), |
51d882ed EP |
2168 | .power_ctrl = su3000_power_ctrl, |
2169 | .num_adapters = 1, | |
2170 | .identify_state = su3000_identify_state, | |
2171 | .i2c_algo = &su3000_i2c_algo, | |
2172 | ||
a49de26a | 2173 | .rc.core = { |
51d882ed | 2174 | .rc_interval = 150, |
a49de26a EP |
2175 | .rc_codes = RC_MAP_SU3000, |
2176 | .module_name = "dw2102", | |
2177 | .allowed_protos = RC_BIT_RC5, | |
2178 | .rc_query = su3000_rc_query, | |
51d882ed EP |
2179 | }, |
2180 | ||
2181 | .read_mac_address = su3000_read_mac_address, | |
2182 | ||
2183 | .generic_bulk_ctrl_endpoint = 0x01, | |
2184 | ||
2185 | .adapter = { | |
2186 | { | |
2187 | .num_frontends = 1, | |
2188 | .fe = { { | |
2189 | .streaming_ctrl = su3000_streaming_ctrl, | |
2190 | .frontend_attach = t220_frontend_attach, | |
2191 | .stream = { | |
2192 | .type = USB_BULK, | |
2193 | .count = 8, | |
2194 | .endpoint = 0x82, | |
2195 | .u = { | |
2196 | .bulk = { | |
2197 | .buffersize = 4096, | |
2198 | } | |
2199 | } | |
2200 | } | |
2201 | } }, | |
2202 | } | |
2203 | }, | |
2204 | .num_device_descs = 1, | |
2205 | .devices = { | |
2206 | { "Geniatech T220 DVB-T/T2 USB2.0", | |
2207 | { &dw2102_table[GENIATECH_T220], NULL }, | |
2208 | { NULL }, | |
2209 | }, | |
2210 | } | |
2211 | }; | |
2212 | ||
27254c36 OS |
2213 | static struct dvb_usb_device_properties tt_s2_4600_properties = { |
2214 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | |
2215 | .usb_ctrl = DEVICE_SPECIFIC, | |
2216 | .size_of_priv = sizeof(struct dw2102_state), | |
2217 | .power_ctrl = su3000_power_ctrl, | |
2218 | .num_adapters = 1, | |
2219 | .identify_state = su3000_identify_state, | |
2220 | .i2c_algo = &su3000_i2c_algo, | |
2221 | ||
2222 | .rc.core = { | |
2223 | .rc_interval = 250, | |
2224 | .rc_codes = RC_MAP_TT_1500, | |
2225 | .module_name = "dw2102", | |
2226 | .allowed_protos = RC_BIT_RC5, | |
2227 | .rc_query = su3000_rc_query, | |
2228 | }, | |
2229 | ||
2230 | .read_mac_address = su3000_read_mac_address, | |
2231 | ||
2232 | .generic_bulk_ctrl_endpoint = 0x01, | |
2233 | ||
2234 | .adapter = { | |
2235 | { | |
2236 | .num_frontends = 1, | |
2237 | .fe = {{ | |
2238 | .streaming_ctrl = su3000_streaming_ctrl, | |
2239 | .frontend_attach = tt_s2_4600_frontend_attach, | |
2240 | .stream = { | |
2241 | .type = USB_BULK, | |
2242 | .count = 8, | |
2243 | .endpoint = 0x82, | |
2244 | .u = { | |
2245 | .bulk = { | |
2246 | .buffersize = 4096, | |
2247 | } | |
2248 | } | |
2249 | } | |
2250 | } }, | |
2251 | } | |
2252 | }, | |
6ede20f9 | 2253 | .num_device_descs = 5, |
27254c36 OS |
2254 | .devices = { |
2255 | { "TechnoTrend TT-connect S2-4600", | |
2256 | { &dw2102_table[TECHNOTREND_S2_4600], NULL }, | |
2257 | { NULL }, | |
2258 | }, | |
44767fc4 OS |
2259 | { "TeVii S482 (tuner 1)", |
2260 | { &dw2102_table[TEVII_S482_1], NULL }, | |
2261 | { NULL }, | |
2262 | }, | |
2263 | { "TeVii S482 (tuner 2)", | |
2264 | { &dw2102_table[TEVII_S482_2], NULL }, | |
2265 | { NULL }, | |
2266 | }, | |
93b66420 PZ |
2267 | { "Terratec Cinergy S2 USB BOX", |
2268 | { &dw2102_table[TERRATEC_CINERGY_S2_BOX], NULL }, | |
2269 | { NULL }, | |
2270 | }, | |
6ede20f9 OS |
2271 | { "TeVii S662", |
2272 | { &dw2102_table[TEVII_S662], NULL }, | |
2273 | { NULL }, | |
2274 | }, | |
27254c36 OS |
2275 | } |
2276 | }; | |
2277 | ||
7fd4828f IL |
2278 | static int dw2102_probe(struct usb_interface *intf, |
2279 | const struct usb_device_id *id) | |
2280 | { | |
68dd9dd4 TM |
2281 | p1100 = kmemdup(&s6x0_properties, |
2282 | sizeof(struct dvb_usb_device_properties), GFP_KERNEL); | |
195288da IL |
2283 | if (!p1100) |
2284 | return -ENOMEM; | |
2285 | /* copy default structure */ | |
195288da | 2286 | /* fill only different fields */ |
6823627b | 2287 | p1100->firmware = P1100_FIRMWARE; |
195288da | 2288 | p1100->devices[0] = d1100; |
a49de26a EP |
2289 | p1100->rc.core.rc_query = prof_rc_query; |
2290 | p1100->rc.core.rc_codes = RC_MAP_TBS_NEC; | |
77eed219 | 2291 | p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach; |
195288da | 2292 | |
68dd9dd4 TM |
2293 | s660 = kmemdup(&s6x0_properties, |
2294 | sizeof(struct dvb_usb_device_properties), GFP_KERNEL); | |
195288da IL |
2295 | if (!s660) { |
2296 | kfree(p1100); | |
2297 | return -ENOMEM; | |
2298 | } | |
6823627b | 2299 | s660->firmware = S660_FIRMWARE; |
e8f5055a | 2300 | s660->num_device_descs = 3; |
195288da | 2301 | s660->devices[0] = d660; |
e8f5055a IL |
2302 | s660->devices[1] = d480_1; |
2303 | s660->devices[2] = d480_2; | |
77eed219 | 2304 | s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach; |
cd79d33e | 2305 | |
68dd9dd4 TM |
2306 | p7500 = kmemdup(&s6x0_properties, |
2307 | sizeof(struct dvb_usb_device_properties), GFP_KERNEL); | |
195288da IL |
2308 | if (!p7500) { |
2309 | kfree(p1100); | |
2310 | kfree(s660); | |
cd79d33e | 2311 | return -ENOMEM; |
195288da | 2312 | } |
6823627b | 2313 | p7500->firmware = P7500_FIRMWARE; |
cd79d33e | 2314 | p7500->devices[0] = d7500; |
a49de26a EP |
2315 | p7500->rc.core.rc_query = prof_rc_query; |
2316 | p7500->rc.core.rc_codes = RC_MAP_TBS_NEC; | |
77eed219 | 2317 | p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach; |
cd79d33e | 2318 | |
955d00ac IL |
2319 | |
2320 | s421 = kmemdup(&su3000_properties, | |
2321 | sizeof(struct dvb_usb_device_properties), GFP_KERNEL); | |
2322 | if (!s421) { | |
2323 | kfree(p1100); | |
2324 | kfree(s660); | |
2325 | kfree(p7500); | |
2326 | return -ENOMEM; | |
2327 | } | |
2328 | s421->num_device_descs = 2; | |
2329 | s421->devices[0] = d421; | |
2330 | s421->devices[1] = d632; | |
2331 | s421->adapter->fe[0].frontend_attach = m88rs2000_frontend_attach; | |
2332 | ||
fe03d5ee IL |
2333 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, |
2334 | THIS_MODULE, NULL, adapter_nr) || | |
2335 | 0 == dvb_usb_device_init(intf, &dw2104_properties, | |
1dac77c9 IL |
2336 | THIS_MODULE, NULL, adapter_nr) || |
2337 | 0 == dvb_usb_device_init(intf, &dw3101_properties, | |
d0a1ddad | 2338 | THIS_MODULE, NULL, adapter_nr) || |
141cc35e | 2339 | 0 == dvb_usb_device_init(intf, &s6x0_properties, |
cd79d33e | 2340 | THIS_MODULE, NULL, adapter_nr) || |
195288da IL |
2341 | 0 == dvb_usb_device_init(intf, p1100, |
2342 | THIS_MODULE, NULL, adapter_nr) || | |
2343 | 0 == dvb_usb_device_init(intf, s660, | |
2344 | THIS_MODULE, NULL, adapter_nr) || | |
cd79d33e | 2345 | 0 == dvb_usb_device_init(intf, p7500, |
d2ffc447 | 2346 | THIS_MODULE, NULL, adapter_nr) || |
955d00ac IL |
2347 | 0 == dvb_usb_device_init(intf, s421, |
2348 | THIS_MODULE, NULL, adapter_nr) || | |
d2ffc447 | 2349 | 0 == dvb_usb_device_init(intf, &su3000_properties, |
51d882ed EP |
2350 | THIS_MODULE, NULL, adapter_nr) || |
2351 | 0 == dvb_usb_device_init(intf, &t220_properties, | |
27254c36 OS |
2352 | THIS_MODULE, NULL, adapter_nr) || |
2353 | 0 == dvb_usb_device_init(intf, &tt_s2_4600_properties, | |
51d882ed | 2354 | THIS_MODULE, NULL, adapter_nr)) |
fe03d5ee | 2355 | return 0; |
141cc35e | 2356 | |
fe03d5ee | 2357 | return -ENODEV; |
7fd4828f IL |
2358 | } |
2359 | ||
70769b24 OS |
2360 | static void dw2102_disconnect(struct usb_interface *intf) |
2361 | { | |
2362 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
2363 | struct dw2102_state *st = (struct dw2102_state *)d->priv; | |
2364 | struct i2c_client *client; | |
2365 | ||
2366 | /* remove I2C client for tuner */ | |
2367 | client = st->i2c_client_tuner; | |
2368 | if (client) { | |
2369 | module_put(client->dev.driver->owner); | |
2370 | i2c_unregister_device(client); | |
2371 | } | |
2372 | ||
f3c6abca OS |
2373 | /* remove I2C client for demodulator */ |
2374 | client = st->i2c_client_demod; | |
2375 | if (client) { | |
2376 | module_put(client->dev.driver->owner); | |
2377 | i2c_unregister_device(client); | |
2378 | } | |
2379 | ||
70769b24 OS |
2380 | dvb_usb_device_exit(intf); |
2381 | } | |
2382 | ||
7fd4828f IL |
2383 | static struct usb_driver dw2102_driver = { |
2384 | .name = "dw2102", | |
2385 | .probe = dw2102_probe, | |
70769b24 | 2386 | .disconnect = dw2102_disconnect, |
7fd4828f IL |
2387 | .id_table = dw2102_table, |
2388 | }; | |
2389 | ||
ecb3b2b3 | 2390 | module_usb_driver(dw2102_driver); |
7fd4828f IL |
2391 | |
2392 | MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); | |
f319ed91 | 2393 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101 USB2.0, TeVii S421, S480, S482, S600, S630, S632, S650, TeVii S660, S662, Prof 1100, 7500 USB2.0, Geniatech SU3000, T220, TechnoTrend S2-4600, Terratec Cinergy S2 devices"); |
7fd4828f IL |
2394 | MODULE_VERSION("0.1"); |
2395 | MODULE_LICENSE("GPL"); | |
6823627b RC |
2396 | MODULE_FIRMWARE(DW2101_FIRMWARE); |
2397 | MODULE_FIRMWARE(DW2102_FIRMWARE); | |
2398 | MODULE_FIRMWARE(DW2104_FIRMWARE); | |
2399 | MODULE_FIRMWARE(DW3101_FIRMWARE); | |
2400 | MODULE_FIRMWARE(S630_FIRMWARE); | |
2401 | MODULE_FIRMWARE(S660_FIRMWARE); | |
2402 | MODULE_FIRMWARE(P1100_FIRMWARE); | |
2403 | MODULE_FIRMWARE(P7500_FIRMWARE); |