hdic.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * DVB USB Linux driver for the HDIC receiver
  3. *
  4. * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
  5. *
  6. * Author: Antti Palosaari <crope@iki.fi>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22. #include "hdic.h"
  23. #include "hd29l2.h"
  24. #include "mxl5007t.h"
  25. /* debug */
  26. static int dvb_usb_hdic_debug;
  27. module_param_named(debug, dvb_usb_hdic_debug, int, 0644);
  28. MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
  29. DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  30. /*
  31. * I2C addresses (7bit) found by probing I2C bus:
  32. * 0x48 ??
  33. * 0x51 eeprom
  34. * 0x60 MaxLinear MXL5007T tuner
  35. * 0x73 HDIC HD29L2 demod
  36. *
  37. * Xtals:
  38. * 24.000 MHz Cypress CY7C68013A-56 (FX2)
  39. * 30.400 MHz HDIC HD29L2
  40. * 24.000 MHz MaxLinear MXL5007T
  41. *
  42. * I/Os:
  43. * RDY1 / SLWR == TS_CLK (USB_SLWR = !TS_CLK&TS_VALID)
  44. * PA1 / INT1 == 29L1_RESET RST_N
  45. */
  46. /*
  47. * See Qanu DVB-T USB2.0 communication protocol specification for more
  48. * information used USB API.
  49. */
  50. /* I2C */
  51. static int hdic_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
  52. int num)
  53. {
  54. int ret;
  55. struct dvb_usb_device *d = i2c_get_adapdata(adap);
  56. u8 buf[64];
  57. /*
  58. * increase sleep when there is a lot of errors:
  59. * dvb-usb: recv bulk message failed: -110
  60. */
  61. #define HDIC_I2C_SLEEP 1
  62. if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
  63. return -EAGAIN;
  64. if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
  65. (msg[1].flags & I2C_M_RD)) {
  66. /* I2C write + read combination (typical register read) */
  67. buf[0] = HDIC_CMD_I2C;
  68. buf[1] = (msg[0].addr << 1); /* I2C write */
  69. buf[2] = msg[0].len;
  70. buf[3] = 1; /* no I2C stop => repeated start */
  71. memcpy(&buf[4], msg[0].buf, msg[0].len);
  72. ret = dvb_usb_generic_rw(d, buf, 4+msg[0].len, buf, 1,
  73. HDIC_I2C_SLEEP);
  74. if (ret)
  75. goto err;
  76. buf[0] = HDIC_CMD_I2C;
  77. buf[1] = (msg[1].addr << 1) | 0x01; /* I2C read */
  78. buf[2] = msg[1].len;
  79. buf[3] = 0; /* I2C stop */
  80. ret = dvb_usb_generic_rw(d, buf, 4, buf, 1+msg[1].len,
  81. HDIC_I2C_SLEEP);
  82. if (ret)
  83. goto err;
  84. memcpy(msg[1].buf, &buf[1], msg[1].len);
  85. } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
  86. /* I2C write (typical register write) */
  87. buf[0] = HDIC_CMD_I2C;
  88. buf[1] = (msg[0].addr << 1); /* I2C write */
  89. buf[2] = msg[0].len;
  90. buf[3] = 0; /* I2C stop */
  91. memcpy(&buf[4], msg[0].buf, msg[0].len);
  92. ret = dvb_usb_generic_rw(d, buf, 4+msg[0].len, buf, 1,
  93. HDIC_I2C_SLEEP);
  94. if (ret)
  95. goto err;
  96. } else {
  97. ret = -EOPNOTSUPP;
  98. goto err;
  99. }
  100. usleep_range(100, 1000);
  101. mutex_unlock(&d->i2c_mutex);
  102. return num;
  103. err:
  104. deb_info("%s: failed=%d\n", __func__, ret);
  105. mutex_unlock(&d->i2c_mutex);
  106. return ret;
  107. }
  108. static u32 hdic_i2c_func(struct i2c_adapter *adapter)
  109. {
  110. return I2C_FUNC_I2C;
  111. }
  112. static struct i2c_algorithm hdic_i2c_algo = {
  113. .master_xfer = hdic_i2c_xfer,
  114. .functionality = hdic_i2c_func,
  115. };
  116. /* Callbacks for DVB USB */
  117. static int hdic_power_ctrl(struct dvb_usb_device *d, int enable)
  118. {
  119. u8 sbuf[] = { HDIC_CMD_SLEEP_MODE, enable ? 0 : 1 };
  120. u8 rbuf[1];
  121. deb_info("%s: enable=%d\n", __func__, enable);
  122. return dvb_usb_generic_rw(d, sbuf, sizeof(sbuf), rbuf, sizeof(rbuf), 0);
  123. }
  124. static int hdic_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
  125. {
  126. u8 sbuf[] = { HDIC_CMD_CONTROL_STREAM_TRANSFER, enable };
  127. u8 rbuf[1];
  128. deb_info("%s: enable=%d\n", __func__, enable);
  129. return dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf), rbuf,
  130. sizeof(rbuf), 0);
  131. }
  132. /* general callback */
  133. static int hdic_frontend_callback(void *priv, int component, int cmd, int arg)
  134. {
  135. int ret;
  136. struct dvb_frontend *fe = priv;
  137. struct dvb_usb_adapter *adap = fe->dvb->priv;
  138. u8 sbuf[2] = { HDIC_CMD_DEMOD_RESET };
  139. u8 rbuf[1];
  140. deb_info("%s:\n", __func__);
  141. /* enable demod reset */
  142. sbuf[1] = 1;
  143. ret = dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf),
  144. rbuf, sizeof(rbuf), 0);
  145. if (ret)
  146. deb_info("%s: failed enable demod reset\n", __func__);
  147. usleep_range(100, 10000);
  148. /* disable demod reset */
  149. sbuf[1] = 0;
  150. ret = dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf), rbuf,
  151. sizeof(rbuf), 0);
  152. if (ret)
  153. deb_info("%s: failed disable demod reset\n", __func__);
  154. return 0;
  155. }
  156. static struct hd29l2_config hdic_hd29l2_config = {
  157. .i2c_addr = 0x73,
  158. .tuner_i2c_addr = 0x60,
  159. .ts_mode = HD29L2_TS_PARALLEL,
  160. };
  161. static int hdic_frontend_attach(struct dvb_usb_adapter *adap)
  162. {
  163. int ret;
  164. u8 sbuf[2];
  165. u8 rbuf[3];
  166. deb_info("%s:\n", __func__);
  167. /* wake-up device */
  168. sbuf[0] = HDIC_CMD_GET_FIRMWARE_VERSION;
  169. ret = dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf), rbuf,
  170. sizeof(rbuf), 0);
  171. if (ret)
  172. deb_info("%s: failed wake-up\n", __func__);
  173. /* disable demod reset */
  174. sbuf[0] = HDIC_CMD_DEMOD_RESET;
  175. sbuf[1] = 0;
  176. ret = dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf), rbuf,
  177. sizeof(rbuf), 0);
  178. if (ret)
  179. deb_info("%s: failed disable demod reset\n", __func__);
  180. /* attach demod */
  181. adap->fe_adap[0].fe = dvb_attach(hd29l2_attach, &hdic_hd29l2_config,
  182. &adap->dev->i2c_adap);
  183. if (adap->fe_adap[0].fe == NULL) {
  184. ret = -ENODEV;
  185. goto err;
  186. }
  187. /* setup the reset callback */
  188. adap->fe_adap[0].fe->callback = hdic_frontend_callback;
  189. return 0;
  190. err:
  191. deb_info("%s: failed=%d\n", __func__, ret);
  192. return ret;
  193. }
  194. static struct mxl5007t_config hdic_mxl5007t_config = {
  195. .xtal_freq_hz = MxL_XTAL_24_MHZ,
  196. .if_freq_hz = MxL_IF_36_15_MHZ,
  197. .invert_if = 1,
  198. };
  199. static int hdic_tuner_attach(struct dvb_usb_adapter *adap)
  200. {
  201. int ret;
  202. deb_info("%s:\n", __func__);
  203. if (dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
  204. &adap->dev->i2c_adap, 0x60, &hdic_mxl5007t_config) == NULL) {
  205. ret = -ENODEV;
  206. goto err;
  207. }
  208. return 0;
  209. err:
  210. deb_info("%s: failed=%d\n", __func__, ret);
  211. return ret;
  212. }
  213. /* DVB USB Driver stuff */
  214. static struct dvb_usb_device_properties hdic_properties;
  215. static int hdic_probe(struct usb_interface *intf,
  216. const struct usb_device_id *id)
  217. {
  218. return dvb_usb_device_init(intf, &hdic_properties, THIS_MODULE, NULL,
  219. adapter_nr);
  220. }
  221. /*
  222. * 04b4:1004 HDIC development board firmware
  223. * 04b4:8613 CY7C68013 EZ-USB FX2 USB 2.0 Development Kit
  224. */
  225. static struct usb_device_id hdic_id[] = {
  226. #define HDIC_8613 0 /* CY7C68013 EZ-USB FX2 USB 2.0 Development Kit */
  227. #define HDIC_1004 1 /* HDIC 04b4:1004 */
  228. #define HDIC_LINUX 2 /* HDIC Linux custom firmware */
  229. [HDIC_8613] = {USB_DEVICE(USB_VID_CYPRESS, 0x8613)},
  230. [HDIC_1004] = {USB_DEVICE(USB_VID_CYPRESS, 0x1004)},
  231. [HDIC_LINUX] = {USB_DEVICE(USB_VID_CYPRESS, 0x1e04)},
  232. {} /* terminating entry */
  233. };
  234. MODULE_DEVICE_TABLE(usb, hdic_id);
  235. static struct dvb_usb_device_properties hdic_properties = {
  236. .caps = DVB_USB_IS_AN_I2C_ADAPTER,
  237. .usb_ctrl = CYPRESS_FX2,
  238. .firmware = "dvb-usb-hdic.fw",
  239. .num_adapters = 1,
  240. .adapter = {
  241. {
  242. .num_frontends = 1,
  243. .fe = {
  244. {
  245. .streaming_ctrl = hdic_streaming_ctrl,
  246. .frontend_attach = hdic_frontend_attach,
  247. .tuner_attach = hdic_tuner_attach,
  248. .stream = {
  249. .type = USB_BULK,
  250. .count = 5,
  251. .endpoint = 0x02,
  252. .u = {
  253. .bulk = {
  254. .buffersize =
  255. (4*512),
  256. }
  257. }
  258. },
  259. }
  260. },
  261. }
  262. },
  263. .power_ctrl = hdic_power_ctrl,
  264. .i2c_algo = &hdic_i2c_algo,
  265. .generic_bulk_ctrl_endpoint = 1,
  266. .num_device_descs = 1,
  267. .devices = {
  268. {
  269. .name = "HDIC reference design",
  270. .cold_ids = {&hdic_id[HDIC_8613],
  271. &hdic_id[HDIC_1004], NULL},
  272. .warm_ids = {&hdic_id[HDIC_LINUX], NULL},
  273. },
  274. }
  275. };
  276. static struct usb_driver hdic_driver = {
  277. .name = "dvb_usb_hdic",
  278. .probe = hdic_probe,
  279. .disconnect = dvb_usb_device_exit,
  280. .id_table = hdic_id,
  281. };
  282. /* module stuff */
  283. static int __init hdic_module_init(void)
  284. {
  285. int ret;
  286. deb_info("%s:\n", __func__);
  287. ret = usb_register(&hdic_driver);
  288. if (ret)
  289. err("module init failed=%d", ret);
  290. return ret;
  291. }
  292. static void __exit hdic_module_exit(void)
  293. {
  294. deb_info("%s:\n", __func__);
  295. /* deregister this driver from the USB subsystem */
  296. usb_deregister(&hdic_driver);
  297. }
  298. module_init(hdic_module_init);
  299. module_exit(hdic_module_exit);
  300. MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
  301. MODULE_DESCRIPTION("HDIC DMB-TH reference design USB2.0 driver (custom firmware)");
  302. MODULE_LICENSE("GPL");