c9431713df6010f29a0659c5a0c371ed6e0cb8f8
[safe/jmp/linux-2.6] / drivers / media / dvb / dvb-usb / dw2102.c
1 /* DVB USB framework compliant Linux driver for the
2 *       DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card
3 *
4 * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
5 *
6 *       This program is free software; you can redistribute it and/or modify it
7 *       under the terms of the GNU General Public License as published by the
8 *       Free Software Foundation, version 2.
9 *
10 * see Documentation/dvb/README.dvb-usb for more information
11 */
12 #include "dw2102.h"
13 #include "si21xx.h"
14 #include "stv0299.h"
15 #include "z0194a.h"
16 #include "stv0288.h"
17 #include "stb6000.h"
18 #include "eds1547.h"
19 #include "cx24116.h"
20
21 #ifndef USB_PID_DW2102
22 #define USB_PID_DW2102 0x2102
23 #endif
24
25 #ifndef USB_PID_DW2104
26 #define USB_PID_DW2104 0x2104
27 #endif
28
29 #define DW210X_READ_MSG 0
30 #define DW210X_WRITE_MSG 1
31
32 #define REG_1F_SYMBOLRATE_BYTE0 0x1f
33 #define REG_20_SYMBOLRATE_BYTE1 0x20
34 #define REG_21_SYMBOLRATE_BYTE2 0x21
35 /* on my own*/
36 #define DW2102_VOLTAGE_CTRL (0x1800)
37 #define DW2102_RC_QUERY (0x1a00)
38
39 struct dw210x_state {
40         u32 last_key_pressed;
41 };
42 struct dw210x_rc_keys {
43         u32 keycode;
44         u32 event;
45 };
46
47 /* debug */
48 static int dvb_usb_dw2102_debug;
49 module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
50 MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS);
51
52 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
53
54 static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
55                         u16 index, u8 * data, u16 len, int flags)
56 {
57         int ret;
58         u8 u8buf[len];
59
60         unsigned int pipe = (flags == DW210X_READ_MSG) ?
61                                 usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
62         u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
63
64         if (flags == DW210X_WRITE_MSG)
65                 memcpy(u8buf, data, len);
66         ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
67                                 value, index , u8buf, len, 2000);
68
69         if (flags == DW210X_READ_MSG)
70                 memcpy(data, u8buf, len);
71         return ret;
72 }
73
74 /* I2C */
75 static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
76                 int num)
77 {
78 struct dvb_usb_device *d = i2c_get_adapdata(adap);
79         int i = 0, ret = 0;
80         u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
81         u16 value;
82
83         if (!d)
84                 return -ENODEV;
85         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
86                 return -EAGAIN;
87
88         switch (num) {
89         case 2:
90                 /* read stv0299 register */
91                 value = msg[0].buf[0];/* register */
92                 for (i = 0; i < msg[1].len; i++) {
93                         value = value + i;
94                         ret = dw210x_op_rw(d->udev, 0xb5, value, 0,
95                                         buf6, 2, DW210X_READ_MSG);
96                         msg[1].buf[i] = buf6[0];
97                 }
98                 break;
99         case 1:
100                 switch (msg[0].addr) {
101                 case 0x68:
102                         /* write to stv0299 register */
103                         buf6[0] = 0x2a;
104                         buf6[1] = msg[0].buf[0];
105                         buf6[2] = msg[0].buf[1];
106                         ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
107                                         buf6, 3, DW210X_WRITE_MSG);
108                         break;
109                 case 0x60:
110                         if (msg[0].flags == 0) {
111                         /* write to tuner pll */
112                                 buf6[0] = 0x2c;
113                                 buf6[1] = 5;
114                                 buf6[2] = 0xc0;
115                                 buf6[3] = msg[0].buf[0];
116                                 buf6[4] = msg[0].buf[1];
117                                 buf6[5] = msg[0].buf[2];
118                                 buf6[6] = msg[0].buf[3];
119                                 ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
120                                                 buf6, 7, DW210X_WRITE_MSG);
121                         } else {
122                         /* read from tuner */
123                                 ret = dw210x_op_rw(d->udev, 0xb5, 0, 0,
124                                                 buf6, 1, DW210X_READ_MSG);
125                                 msg[0].buf[0] = buf6[0];
126                         }
127                         break;
128                 case (DW2102_RC_QUERY):
129                         ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
130                                         buf6, 2, DW210X_READ_MSG);
131                         msg[0].buf[0] = buf6[0];
132                         msg[0].buf[1] = buf6[1];
133                         break;
134                 case (DW2102_VOLTAGE_CTRL):
135                         buf6[0] = 0x30;
136                         buf6[1] = msg[0].buf[0];
137                         ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
138                                         buf6, 2, DW210X_WRITE_MSG);
139                         break;
140                 }
141
142                 break;
143         }
144
145         mutex_unlock(&d->i2c_mutex);
146         return num;
147 }
148
149 static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
150                                                 struct i2c_msg msg[], int num)
151 {
152         struct dvb_usb_device *d = i2c_get_adapdata(adap);
153         int ret = 0;
154         u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};
155
156         if (!d)
157                 return -ENODEV;
158         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
159                 return -EAGAIN;
160
161         switch (num) {
162         case 2:
163                 /* read si2109 register by number */
164                 buf6[0] = 0xd0;
165                 buf6[1] = msg[0].len;
166                 buf6[2] = msg[0].buf[0];
167                 ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
168                                 buf6, msg[0].len + 2, DW210X_WRITE_MSG);
169                 /* read si2109 register */
170                 ret = dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
171                                 buf6, msg[1].len + 2, DW210X_READ_MSG);
172                 memcpy(msg[1].buf, buf6 + 2, msg[1].len);
173
174                 break;
175         case 1:
176                 switch (msg[0].addr) {
177                 case 0x68:
178                         /* write to si2109 register */
179                         buf6[0] = 0xd0;
180                         buf6[1] = msg[0].len;
181                         memcpy(buf6 + 2, msg[0].buf, msg[0].len);
182                         ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
183                                         msg[0].len + 2, DW210X_WRITE_MSG);
184                         break;
185                 case(DW2102_RC_QUERY):
186                         ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
187                                         buf6, 2, DW210X_READ_MSG);
188                         msg[0].buf[0] = buf6[0];
189                         msg[0].buf[1] = buf6[1];
190                         break;
191                 case(DW2102_VOLTAGE_CTRL):
192                         buf6[0] = 0x30;
193                         buf6[1] = msg[0].buf[0];
194                         ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
195                                         buf6, 2, DW210X_WRITE_MSG);
196                         break;
197                 }
198                 break;
199         }
200
201         mutex_unlock(&d->i2c_mutex);
202         return num;
203 }
204 static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
205 {
206         struct dvb_usb_device *d = i2c_get_adapdata(adap);
207         int ret = 0;
208
209         if (!d)
210                 return -ENODEV;
211         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
212                 return -EAGAIN;
213
214         switch (num) {
215         case 2: {
216                 /* read */
217                 /* first write first register number */
218                 u8 ibuf [msg[1].len + 2], obuf[3];
219                 obuf[0] = 0xd0;
220                 obuf[1] = msg[0].len;
221                 obuf[2] = msg[0].buf[0];
222                 ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
223                                 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
224                 /* second read registers */
225                 ret = dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,
226                                 ibuf, msg[1].len + 2, DW210X_READ_MSG);
227                 memcpy(msg[1].buf, ibuf + 2, msg[1].len);
228
229                 break;
230         }
231         case 1:
232                 switch (msg[0].addr) {
233                 case 0x68: {
234                         /* write to register */
235                         u8 obuf[msg[0].len + 2];
236                         obuf[0] = 0xd0;
237                         obuf[1] = msg[0].len;
238                         memcpy(obuf + 2, msg[0].buf, msg[0].len);
239                         ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
240                                         obuf, msg[0].len + 2, DW210X_WRITE_MSG);
241                         break;
242                 }
243                 case 0x61: {
244                         /* write to tuner */
245                         u8 obuf[msg[0].len + 2];
246                         obuf[0] = 0xc2;
247                         obuf[1] = msg[0].len;
248                         memcpy(obuf + 2, msg[0].buf, msg[0].len);
249                         ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
250                                         obuf, msg[0].len + 2, DW210X_WRITE_MSG);
251                         break;
252                 }
253                 case(DW2102_RC_QUERY): {
254                         u8 ibuf[2];
255                         ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
256                                         ibuf, 2, DW210X_READ_MSG);
257                         memcpy(msg[0].buf, ibuf , 2);
258                         break;
259                 }
260                 case(DW2102_VOLTAGE_CTRL): {
261                         u8 obuf[2];
262                         obuf[0] = 0x30;
263                         obuf[1] = msg[0].buf[0];
264                         ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
265                                         obuf, 2, DW210X_WRITE_MSG);
266                         break;
267                 }
268                 }
269
270                 break;
271         }
272
273         mutex_unlock(&d->i2c_mutex);
274         return num;
275 }
276
277 static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
278 {
279         struct dvb_usb_device *d = i2c_get_adapdata(adap);
280         int ret = 0;
281         int len, i;
282
283         if (!d)
284                 return -ENODEV;
285         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
286                 return -EAGAIN;
287
288         switch (num) {
289         case 2: {
290                 /* read */
291                 /* first write first register number */
292                 u8 ibuf [msg[1].len + 2], obuf[3];
293                 obuf[0] = 0xaa;
294                 obuf[1] = msg[0].len;
295                 obuf[2] = msg[0].buf[0];
296                 ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
297                                 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
298                 /* second read registers */
299                 ret = dw210x_op_rw(d->udev, 0xc3, 0xab , 0,
300                                 ibuf, msg[1].len + 2, DW210X_READ_MSG);
301                 memcpy(msg[1].buf, ibuf + 2, msg[1].len);
302
303                 break;
304         }
305         case 1:
306                 switch (msg[0].addr) {
307                 case 0x55: {
308                         if (msg[0].buf[0] == 0xf7) {
309                                 /* firmware */
310                                 /* Write in small blocks */
311                                 u8 obuf[19];
312                                 obuf[0] = 0xaa;
313                                 obuf[1] = 0x11;
314                                 obuf[2] = 0xf7;
315                                 len = msg[0].len - 1;
316                                 i = 1;
317                                 do {
318                                         memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len));
319                                         ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
320                                                 obuf, (len > 16 ? 16 : len) + 3, DW210X_WRITE_MSG);
321                                         i += 16;
322                                         len -= 16;
323                                 } while (len > 0);
324                         } else {
325                                 /* write to register */
326                                 u8 obuf[msg[0].len + 2];
327                                 obuf[0] = 0xaa;
328                                 obuf[1] = msg[0].len;
329                                 memcpy(obuf + 2, msg[0].buf, msg[0].len);
330                                 ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
331                                                 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
332                         }
333                         break;
334                 }
335                 case(DW2102_RC_QUERY): {
336                         u8 ibuf[2];
337                         ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
338                                         ibuf, 2, DW210X_READ_MSG);
339                         memcpy(msg[0].buf, ibuf , 2);
340                         break;
341                 }
342                 case(DW2102_VOLTAGE_CTRL): {
343                         u8 obuf[2];
344                         obuf[0] = 0x30;
345                         obuf[1] = msg[0].buf[0];
346                         ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
347                                         obuf, 2, DW210X_WRITE_MSG);
348                         break;
349                 }
350                 }
351
352                 break;
353         }
354
355         mutex_unlock(&d->i2c_mutex);
356         return num;
357 }
358
359 static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
360 {
361         return I2C_FUNC_I2C;
362 }
363
364 static struct i2c_algorithm dw2102_i2c_algo = {
365         .master_xfer = dw2102_i2c_transfer,
366         .functionality = dw210x_i2c_func,
367 };
368
369 static struct i2c_algorithm dw2102_serit_i2c_algo = {
370         .master_xfer = dw2102_serit_i2c_transfer,
371         .functionality = dw210x_i2c_func,
372 };
373
374 static struct i2c_algorithm dw2102_earda_i2c_algo = {
375         .master_xfer = dw2102_earda_i2c_transfer,
376         .functionality = dw210x_i2c_func,
377 };
378
379 static struct i2c_algorithm dw2104_i2c_algo = {
380         .master_xfer = dw2104_i2c_transfer,
381         .functionality = dw210x_i2c_func,
382 };
383
384 static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
385 {
386         int i;
387         u8 ibuf[] = {0, 0};
388         u8 eeprom[256], eepromline[16];
389
390         for (i = 0; i < 256; i++) {
391                 if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {
392                         err("read eeprom failed.");
393                         return -1;
394                 } else {
395                         eepromline[i%16] = ibuf[0];
396                         eeprom[i] = ibuf[0];
397                 }
398                 if ((i % 16) == 15) {
399                         deb_xfer("%02x: ", i - 15);
400                         debug_dump(eepromline, 16, deb_xfer);
401                 }
402         }
403         memcpy(mac, eeprom + 8, 6);
404         return 0;
405 };
406
407 static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
408 {
409         static u8 command_13v[1] = {0x00};
410         static u8 command_18v[1] = {0x01};
411         struct i2c_msg msg[] = {
412                 {.addr = DW2102_VOLTAGE_CTRL, .flags = 0,
413                         .buf = command_13v, .len = 1},
414         };
415
416         struct dvb_usb_adapter *udev_adap =
417                 (struct dvb_usb_adapter *)(fe->dvb->priv);
418         if (voltage == SEC_VOLTAGE_18)
419                 msg[0].buf = command_18v;
420         i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
421         return 0;
422 }
423
424 static struct stv0299_config sharp_z0194a_config = {
425         .demod_address = 0x68,
426         .inittab = sharp_z0194a_inittab,
427         .mclk = 88000000UL,
428         .invert = 1,
429         .skip_reinit = 0,
430         .lock_output = STV0299_LOCKOUTPUT_1,
431         .volt13_op0_op1 = STV0299_VOLT13_OP1,
432         .min_delay_ms = 100,
433         .set_symbol_rate = sharp_z0194a_set_symbol_rate,
434 };
435
436 static struct cx24116_config dw2104_config = {
437         .demod_address = 0x55,
438         .mpg_clk_pos_pol = 0x01,
439 };
440
441 static struct si21xx_config serit_sp1511lhb_config = {
442         .demod_address = 0x68,
443         .min_delay_ms = 100,
444
445 };
446
447 static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
448 {
449         if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
450                         &d->dev->i2c_adap)) != NULL) {
451                 d->fe->ops.set_voltage = dw210x_set_voltage;
452                 info("Attached cx24116!\n");
453                 return 0;
454         }
455         return -EIO;
456 }
457
458 static struct dvb_usb_device_properties dw2102_properties;
459
460 static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
461 {
462         if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
463                 /*dw2102_properties.adapter->tuner_attach = NULL;*/
464                 d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
465                                         &d->dev->i2c_adap);
466                 if (d->fe != NULL) {
467                         d->fe->ops.set_voltage = dw210x_set_voltage;
468                         info("Attached si21xx!\n");
469                         return 0;
470                 }
471         }
472         if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
473                 /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
474                 d->fe = dvb_attach(stv0288_attach, &earda_config,
475                                         &d->dev->i2c_adap);
476                 if (d->fe != NULL) {
477                         d->fe->ops.set_voltage = dw210x_set_voltage;
478                         info("Attached stv0288!\n");
479                         return 0;
480                 }
481         }
482
483         if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
484                 /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
485                 d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
486                                         &d->dev->i2c_adap);
487                 if (d->fe != NULL) {
488                         d->fe->ops.set_voltage = dw210x_set_voltage;
489                         info("Attached stv0299!\n");
490                         return 0;
491                 }
492         }
493         return -EIO;
494 }
495
496 static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
497 {
498         dvb_attach(dvb_pll_attach, adap->fe, 0x60,
499                 &adap->dev->i2c_adap, DVB_PLL_OPERA1);
500         return 0;
501 }
502
503 static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap)
504 {
505         dvb_attach(stb6000_attach, adap->fe, 0x61,
506                 &adap->dev->i2c_adap);
507
508         return 0;
509 }
510
511 static struct dvb_usb_rc_key dw210x_rc_keys[] = {
512         { 0xf8, 0x0a, KEY_Q },          /*power*/
513         { 0xf8, 0x0c, KEY_M },          /*mute*/
514         { 0xf8, 0x11, KEY_1 },
515         { 0xf8, 0x12, KEY_2 },
516         { 0xf8, 0x13, KEY_3 },
517         { 0xf8, 0x14, KEY_4 },
518         { 0xf8, 0x15, KEY_5 },
519         { 0xf8, 0x16, KEY_6 },
520         { 0xf8, 0x17, KEY_7 },
521         { 0xf8, 0x18, KEY_8 },
522         { 0xf8, 0x19, KEY_9 },
523         { 0xf8, 0x10, KEY_0 },
524         { 0xf8, 0x1c, KEY_PAGEUP },     /*ch+*/
525         { 0xf8, 0x0f, KEY_PAGEDOWN },   /*ch-*/
526         { 0xf8, 0x1a, KEY_O },          /*vol+*/
527         { 0xf8, 0x0e, KEY_Z },          /*vol-*/
528         { 0xf8, 0x04, KEY_R },          /*rec*/
529         { 0xf8, 0x09, KEY_D },          /*fav*/
530         { 0xf8, 0x08, KEY_BACKSPACE },  /*rewind*/
531         { 0xf8, 0x07, KEY_A },          /*fast*/
532         { 0xf8, 0x0b, KEY_P },          /*pause*/
533         { 0xf8, 0x02, KEY_ESC },        /*cancel*/
534         { 0xf8, 0x03, KEY_G },          /*tab*/
535         { 0xf8, 0x00, KEY_UP },         /*up*/
536         { 0xf8, 0x1f, KEY_ENTER },      /*ok*/
537         { 0xf8, 0x01, KEY_DOWN },       /*down*/
538         { 0xf8, 0x05, KEY_C },          /*cap*/
539         { 0xf8, 0x06, KEY_S },          /*stop*/
540         { 0xf8, 0x40, KEY_F },          /*full*/
541         { 0xf8, 0x1e, KEY_W },          /*tvmode*/
542         { 0xf8, 0x1b, KEY_B },          /*recall*/
543
544 };
545
546
547
548 static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
549 {
550         struct dw210x_state *st = d->priv;
551         u8 key[2];
552         struct i2c_msg msg[] = {
553                 {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,
554                 .len = 2},
555         };
556         int i;
557
558         *state = REMOTE_NO_KEY_PRESSED;
559         if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
560                 for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) {
561                         if (dw210x_rc_keys[i].data == msg[0].buf[0]) {
562                                 *state = REMOTE_KEY_PRESSED;
563                                 *event = dw210x_rc_keys[i].event;
564                                 st->last_key_pressed =
565                                         dw210x_rc_keys[i].event;
566                                 break;
567                         }
568                 st->last_key_pressed = 0;
569                 }
570         }
571         /* info("key: %x %x\n",key[0],key[1]); */
572         return 0;
573 }
574
575 static struct usb_device_id dw2102_table[] = {
576         {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
577         {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
578         {USB_DEVICE(USB_VID_CYPRESS, 0x2104)},
579         {USB_DEVICE(0x9022, 0xd650)},
580         { }
581 };
582
583 MODULE_DEVICE_TABLE(usb, dw2102_table);
584
585 static int dw2102_load_firmware(struct usb_device *dev,
586                         const struct firmware *frmwr)
587 {
588         u8 *b, *p;
589         int ret = 0, i;
590         u8 reset;
591         u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
592         const struct firmware *fw;
593         const char *filename = "dvb-usb-dw2101.fw";
594         switch (dev->descriptor.idProduct) {
595         case 0x2101:
596                 ret = request_firmware(&fw, filename, &dev->dev);
597                 if (ret != 0) {
598                         err("did not find the firmware file. (%s) "
599                         "Please see linux/Documentation/dvb/ for more details "
600                         "on firmware-problems.", filename);
601                         return ret;
602                 }
603                 break;
604         default:
605                 fw = frmwr;
606                 break;
607         }
608         info("start downloading DW210X firmware");
609         p = kmalloc(fw->size, GFP_KERNEL);
610         reset = 1;
611         /*stop the CPU*/
612         dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);
613         dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);
614
615         if (p != NULL) {
616                 memcpy(p, fw->data, fw->size);
617                 for (i = 0; i < fw->size; i += 0x40) {
618                         b = (u8 *) p + i;
619                         if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,
620                                         DW210X_WRITE_MSG) != 0x40) {
621                                 err("error while transferring firmware");
622                                 ret = -EINVAL;
623                                 break;
624                         }
625                 }
626                 /* restart the CPU */
627                 reset = 0;
628                 if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
629                                         DW210X_WRITE_MSG) != 1) {
630                         err("could not restart the USB controller CPU.");
631                         ret = -EINVAL;
632                 }
633                 if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
634                                         DW210X_WRITE_MSG) != 1) {
635                         err("could not restart the USB controller CPU.");
636                         ret = -EINVAL;
637                 }
638                 /* init registers */
639                 switch (dev->descriptor.idProduct) {
640                 case USB_PID_DW2104:
641                 case 0xd650:
642                         reset = 1;
643                         dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
644                                         DW210X_WRITE_MSG);
645                         reset = 0;
646                         dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
647                                         DW210X_WRITE_MSG);
648                         break;
649                 case USB_PID_DW2102:
650                         dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
651                                         DW210X_WRITE_MSG);
652                         dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
653                                         DW210X_READ_MSG);
654                         /* check STV0299 frontend  */
655                         dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,
656                                         DW210X_READ_MSG);
657                         if (reset16[0] == 0xa1) {
658                                 dw2102_properties.i2c_algo = &dw2102_i2c_algo;
659                                 dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;
660                                 break;
661                         } else {
662                                 /* check STV0288 frontend  */
663                                 reset16[0] = 0xd0;
664                                 reset16[1] = 1;
665                                 reset16[2] = 0;
666                                 dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,
667                                                 DW210X_WRITE_MSG);
668                                 dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,
669                                                 DW210X_READ_MSG);
670                                 if (reset16[2] == 0x11) {
671                                         dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
672                                         dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach;
673                                         break;
674                                 }
675                         }
676                 case 0x2101:
677                         dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,
678                                         DW210X_READ_MSG);
679                         dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
680                                         DW210X_READ_MSG);
681                         dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
682                                         DW210X_READ_MSG);
683                         dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
684                                         DW210X_READ_MSG);
685                         break;
686                 }
687                 msleep(100);
688                 kfree(p);
689         }
690         return ret;
691 }
692
693 static struct dvb_usb_device_properties dw2102_properties = {
694         .caps = DVB_USB_IS_AN_I2C_ADAPTER,
695         .usb_ctrl = DEVICE_SPECIFIC,
696         .firmware = "dvb-usb-dw2102.fw",
697         .size_of_priv = sizeof(struct dw210x_state),
698         .no_reconnect = 1,
699
700         .i2c_algo = &dw2102_serit_i2c_algo,
701         .rc_key_map = dw210x_rc_keys,
702         .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
703         .rc_interval = 150,
704         .rc_query = dw2102_rc_query,
705
706         .generic_bulk_ctrl_endpoint = 0x81,
707         /* parameter for the MPEG2-data transfer */
708         .num_adapters = 1,
709         .download_firmware = dw2102_load_firmware,
710         .read_mac_address = dw210x_read_mac_address,
711                 .adapter = {
712                 {
713                         .frontend_attach = dw2102_frontend_attach,
714                         .streaming_ctrl = NULL,
715                         .tuner_attach = NULL,
716                         .stream = {
717                                 .type = USB_BULK,
718                                 .count = 8,
719                                 .endpoint = 0x82,
720                                 .u = {
721                                         .bulk = {
722                                                 .buffersize = 4096,
723                                         }
724                                 }
725                         },
726                 }
727         },
728         .num_device_descs = 2,
729         .devices = {
730                 {"DVBWorld DVB-S 2102 USB2.0",
731                         {&dw2102_table[0], NULL},
732                         {NULL},
733                 },
734                 {"DVBWorld DVB-S 2101 USB2.0",
735                         {&dw2102_table[1], NULL},
736                         {NULL},
737                 },
738         }
739 };
740
741 static struct dvb_usb_device_properties dw2104_properties = {
742         .caps = DVB_USB_IS_AN_I2C_ADAPTER,
743         .usb_ctrl = DEVICE_SPECIFIC,
744         .firmware = "dvb-usb-dw2104.fw",
745         .size_of_priv = sizeof(struct dw210x_state),
746         .no_reconnect = 1,
747
748         .i2c_algo = &dw2104_i2c_algo,
749         .rc_key_map = dw210x_rc_keys,
750         .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
751         .rc_interval = 150,
752         .rc_query = dw2102_rc_query,
753
754         .generic_bulk_ctrl_endpoint = 0x81,
755         /* parameter for the MPEG2-data transfer */
756         .num_adapters = 1,
757         .download_firmware = dw2102_load_firmware,
758         .read_mac_address = dw210x_read_mac_address,
759         .adapter = {
760                 {
761                         .frontend_attach = dw2104_frontend_attach,
762                         .streaming_ctrl = NULL,
763                         /*.tuner_attach = dw2104_tuner_attach,*/
764                         .stream = {
765                                 .type = USB_BULK,
766                                 .count = 8,
767                                 .endpoint = 0x82,
768                                 .u = {
769                                         .bulk = {
770                                                 .buffersize = 4096,
771                                         }
772                                 }
773                         },
774                 }
775         },
776         .num_device_descs = 2,
777         .devices = {
778                 { "DVBWorld DW2104 USB2.0",
779                         {&dw2102_table[2], NULL},
780                         {NULL},
781                 },
782                 { "TeVii S650 USB2.0",
783                         {&dw2102_table[3], NULL},
784                         {NULL},
785                 },
786         }
787 };
788
789 static int dw2102_probe(struct usb_interface *intf,
790                 const struct usb_device_id *id)
791 {
792         if (0 == dvb_usb_device_init(intf, &dw2102_properties,
793                         THIS_MODULE, NULL, adapter_nr) ||
794             0 == dvb_usb_device_init(intf, &dw2104_properties,
795                         THIS_MODULE, NULL, adapter_nr)) {
796                 return 0;
797         }
798         return -ENODEV;
799 }
800
801 static struct usb_driver dw2102_driver = {
802         .name = "dw2102",
803         .probe = dw2102_probe,
804         .disconnect = dvb_usb_device_exit,
805         .id_table = dw2102_table,
806 };
807
808 static int __init dw2102_module_init(void)
809 {
810         int ret =  usb_register(&dw2102_driver);
811         if (ret)
812                 err("usb_register failed. Error number %d", ret);
813
814         return ret;
815 }
816
817 static void __exit dw2102_module_exit(void)
818 {
819         usb_deregister(&dw2102_driver);
820 }
821
822 module_init(dw2102_module_init);
823 module_exit(dw2102_module_exit);
824
825 MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
826 MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device");
827 MODULE_VERSION("0.1");
828 MODULE_LICENSE("GPL");