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