dw2102.c 17 KB

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