au8522.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /*
  2. Auvitek AU8522 QAM/8VSB demodulator driver
  3. Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/init.h>
  18. #include <linux/module.h>
  19. #include <linux/string.h>
  20. #include <linux/slab.h>
  21. #include <linux/delay.h>
  22. #include "dvb_frontend.h"
  23. #include "dvb-pll.h"
  24. #include "au8522.h"
  25. struct au8522_state {
  26. struct i2c_adapter *i2c;
  27. /* configuration settings */
  28. const struct au8522_config *config;
  29. struct dvb_frontend frontend;
  30. u32 current_frequency;
  31. fe_modulation_t current_modulation;
  32. };
  33. static int debug = 0;
  34. #define dprintk if (debug) printk
  35. /* 16 bit registers, 8 bit values */
  36. static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
  37. {
  38. int ret;
  39. u8 buf [] = { reg >> 8, reg & 0xff, data };
  40. struct i2c_msg msg = { .addr = state->config->demod_address,
  41. .flags = 0, .buf = buf, .len = 3 };
  42. ret = i2c_transfer(state->i2c, &msg, 1);
  43. if (ret != 1)
  44. printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
  45. "ret == %i)\n", __FUNCTION__, reg, data, ret);
  46. return (ret != 1) ? -1 : 0;
  47. }
  48. static u8 au8522_readreg(struct au8522_state *state, u16 reg)
  49. {
  50. int ret;
  51. u8 b0 [] = { reg >> 8, reg & 0xff };
  52. u8 b1 [] = { 0 };
  53. struct i2c_msg msg [] = {
  54. { .addr = state->config->demod_address, .flags = 0,
  55. .buf = b0, .len = 2 },
  56. { .addr = state->config->demod_address, .flags = I2C_M_RD,
  57. .buf = b1, .len = 1 } };
  58. ret = i2c_transfer(state->i2c, msg, 2);
  59. if (ret != 2)
  60. printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
  61. return b1[0];
  62. }
  63. static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
  64. {
  65. struct au8522_state *state = fe->demodulator_priv;
  66. dprintk("%s(%d)\n", __FUNCTION__, enable);
  67. if (enable)
  68. return au8522_writereg(state, 0x106, 1);
  69. else
  70. return au8522_writereg(state, 0x106, 0);
  71. }
  72. static int au8522_enable_modulation(struct dvb_frontend *fe,
  73. fe_modulation_t m)
  74. {
  75. struct au8522_state *state = fe->demodulator_priv;
  76. dprintk("%s(0x%08x)\n", __FUNCTION__, m);
  77. switch(m) {
  78. case VSB_8:
  79. dprintk("%s() VSB_8\n", __FUNCTION__);
  80. //au8522_writereg(state, 0x410b, 0x84); // Serial
  81. //au8522_writereg(state, 0x8090, 0x82);
  82. au8522_writereg(state, 0x8090, 0x84);
  83. au8522_writereg(state, 0x4092, 0x11);
  84. au8522_writereg(state, 0x2005, 0x00);
  85. au8522_writereg(state, 0x8091, 0x80);
  86. au8522_writereg(state, 0x80a3, 0x0c);
  87. au8522_writereg(state, 0x80a4, 0xe8);
  88. au8522_writereg(state, 0x8081, 0xc4);
  89. au8522_writereg(state, 0x80a5, 0x40);
  90. au8522_writereg(state, 0x80a7, 0x40);
  91. au8522_writereg(state, 0x80a6, 0x67);
  92. au8522_writereg(state, 0x8262, 0x20);
  93. au8522_writereg(state, 0x821c, 0x30);
  94. au8522_writereg(state, 0x80d8, 0x1a);
  95. au8522_writereg(state, 0x8227, 0xa0);
  96. au8522_writereg(state, 0x8121, 0xff);
  97. au8522_writereg(state, 0x80a8, 0xf0);
  98. au8522_writereg(state, 0x80a9, 0x05);
  99. au8522_writereg(state, 0x80aa, 0x77);
  100. au8522_writereg(state, 0x80ab, 0xf0);
  101. au8522_writereg(state, 0x80ac, 0x05);
  102. au8522_writereg(state, 0x80ad, 0x77);
  103. au8522_writereg(state, 0x80ae, 0x41);
  104. au8522_writereg(state, 0x80af, 0x66);
  105. au8522_writereg(state, 0x821b, 0xcc);
  106. au8522_writereg(state, 0x821d, 0x80);
  107. au8522_writereg(state, 0x80b5, 0xfb);
  108. au8522_writereg(state, 0x80b6, 0x8e);
  109. au8522_writereg(state, 0x80b7, 0x39);
  110. au8522_writereg(state, 0x80a4, 0xe8);
  111. au8522_writereg(state, 0x8231, 0x13);
  112. break;
  113. case QAM_64:
  114. case QAM_256:
  115. au8522_writereg(state, 0x80a3, 0x09);
  116. au8522_writereg(state, 0x80a4, 0x00);
  117. au8522_writereg(state, 0x8081, 0xc4);
  118. au8522_writereg(state, 0x80a5, 0x40);
  119. au8522_writereg(state, 0x80b5, 0xfb);
  120. au8522_writereg(state, 0x80b6, 0x8e);
  121. au8522_writereg(state, 0x80b7, 0x39);
  122. au8522_writereg(state, 0x80aa, 0x77);
  123. au8522_writereg(state, 0x80ad, 0x77);
  124. au8522_writereg(state, 0x80a6, 0x67);
  125. au8522_writereg(state, 0x8262, 0x20);
  126. au8522_writereg(state, 0x821c, 0x30);
  127. au8522_writereg(state, 0x80b8, 0x3e);
  128. au8522_writereg(state, 0x80b9, 0xf0);
  129. au8522_writereg(state, 0x80ba, 0x01);
  130. au8522_writereg(state, 0x80bb, 0x18);
  131. au8522_writereg(state, 0x80bc, 0x50);
  132. au8522_writereg(state, 0x80bd, 0x00);
  133. au8522_writereg(state, 0x80be, 0xea);
  134. au8522_writereg(state, 0x80bf, 0xef);
  135. au8522_writereg(state, 0x80c0, 0xfc);
  136. au8522_writereg(state, 0x80c1, 0xbd);
  137. au8522_writereg(state, 0x80c2, 0x1f);
  138. au8522_writereg(state, 0x80c3, 0xfc);
  139. au8522_writereg(state, 0x80c4, 0xdd);
  140. au8522_writereg(state, 0x80c5, 0xaf);
  141. au8522_writereg(state, 0x80c6, 0x00);
  142. au8522_writereg(state, 0x80c7, 0x38);
  143. au8522_writereg(state, 0x80c8, 0x30);
  144. au8522_writereg(state, 0x80c9, 0x05);
  145. au8522_writereg(state, 0x80ca, 0x4a);
  146. au8522_writereg(state, 0x80cb, 0xd0);
  147. au8522_writereg(state, 0x80cc, 0x01);
  148. au8522_writereg(state, 0x80cd, 0xd9);
  149. au8522_writereg(state, 0x80ce, 0x6f);
  150. au8522_writereg(state, 0x80cf, 0xf9);
  151. au8522_writereg(state, 0x80d0, 0x70);
  152. au8522_writereg(state, 0x80d1, 0xdf);
  153. au8522_writereg(state, 0x80d2, 0xf7);
  154. au8522_writereg(state, 0x80d3, 0xc2);
  155. au8522_writereg(state, 0x80d4, 0xdf);
  156. au8522_writereg(state, 0x80d5, 0x02);
  157. au8522_writereg(state, 0x80d6, 0x9a);
  158. au8522_writereg(state, 0x80d7, 0xd0);
  159. au8522_writereg(state, 0x8250, 0x0d);
  160. au8522_writereg(state, 0x8251, 0xcd);
  161. au8522_writereg(state, 0x8252, 0xe0);
  162. au8522_writereg(state, 0x8253, 0x05);
  163. au8522_writereg(state, 0x8254, 0xa7);
  164. au8522_writereg(state, 0x8255, 0xff);
  165. au8522_writereg(state, 0x8256, 0xed);
  166. au8522_writereg(state, 0x8257, 0x5b);
  167. au8522_writereg(state, 0x8258, 0xae);
  168. au8522_writereg(state, 0x8259, 0xe6);
  169. au8522_writereg(state, 0x825a, 0x3d);
  170. au8522_writereg(state, 0x825b, 0x0f);
  171. au8522_writereg(state, 0x825c, 0x0d);
  172. au8522_writereg(state, 0x825d, 0xea);
  173. au8522_writereg(state, 0x825e, 0xf2);
  174. au8522_writereg(state, 0x825f, 0x51);
  175. au8522_writereg(state, 0x8260, 0xf5);
  176. au8522_writereg(state, 0x8261, 0x06);
  177. au8522_writereg(state, 0x821a, 0x00);
  178. au8522_writereg(state, 0x8546, 0x40);
  179. au8522_writereg(state, 0x8210, 0x26);
  180. au8522_writereg(state, 0x8211, 0xf6);
  181. au8522_writereg(state, 0x8212, 0x84);
  182. au8522_writereg(state, 0x8213, 0x02);
  183. au8522_writereg(state, 0x8502, 0x01);
  184. au8522_writereg(state, 0x8121, 0x04);
  185. au8522_writereg(state, 0x8122, 0x04);
  186. au8522_writereg(state, 0x852e, 0x10);
  187. au8522_writereg(state, 0x80a4, 0xca);
  188. au8522_writereg(state, 0x80a7, 0x40);
  189. au8522_writereg(state, 0x8526, 0x01);
  190. break;
  191. default:
  192. dprintk("%s() Invalid modulation\n", __FUNCTION__);
  193. return -EINVAL;
  194. }
  195. state->current_modulation = m;
  196. return 0;
  197. }
  198. /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
  199. static int au8522_set_frontend(struct dvb_frontend *fe,
  200. struct dvb_frontend_parameters *p)
  201. {
  202. struct au8522_state *state = fe->demodulator_priv;
  203. dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency);
  204. state->current_frequency = p->frequency;
  205. au8522_enable_modulation(fe, p->u.vsb.modulation);
  206. /* Allow the demod to settle */
  207. msleep(100);
  208. if (fe->ops.tuner_ops.set_params) {
  209. if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);
  210. fe->ops.tuner_ops.set_params(fe, p);
  211. if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
  212. }
  213. return 0;
  214. }
  215. /* Reset the demod hardware and reset all of the configuration registers
  216. to a default state. */
  217. static int au8522_init(struct dvb_frontend *fe)
  218. {
  219. struct au8522_state *state = fe->demodulator_priv;
  220. dprintk("%s()\n", __FUNCTION__);
  221. au8522_writereg(state, 0xa4, 1 << 5);
  222. au8522_i2c_gate_ctrl(fe, 1);
  223. return 0;
  224. }
  225. static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
  226. {
  227. struct au8522_state *state = fe->demodulator_priv;
  228. u8 reg;
  229. u32 tuner_status = 0;
  230. *status = 0;
  231. if (state->current_modulation == VSB_8) {
  232. dprintk("%s() Checking VSB_8\n", __FUNCTION__);
  233. //au8522_writereg(state, 0x80a4, 0x20);
  234. reg = au8522_readreg(state, 0x4088);
  235. if (reg & 0x01)
  236. *status |= FE_HAS_VITERBI;
  237. if (reg & 0x02)
  238. *status |= FE_HAS_LOCK | FE_HAS_SYNC;
  239. } else {
  240. dprintk("%s() Checking QAM\n", __FUNCTION__);
  241. reg = au8522_readreg(state, 0x4541);
  242. if (reg & 0x80)
  243. *status |= FE_HAS_VITERBI;
  244. if (reg & 0x20)
  245. *status |= FE_HAS_LOCK | FE_HAS_SYNC;
  246. }
  247. switch(state->config->status_mode) {
  248. case AU8522_DEMODLOCKING:
  249. dprintk("%s() DEMODLOCKING\n", __FUNCTION__);
  250. if (*status & FE_HAS_VITERBI)
  251. *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
  252. break;
  253. case AU8522_TUNERLOCKING:
  254. /* Get the tuner status */
  255. dprintk("%s() TUNERLOCKING\n", __FUNCTION__);
  256. if (fe->ops.tuner_ops.get_status) {
  257. if (fe->ops.i2c_gate_ctrl)
  258. fe->ops.i2c_gate_ctrl(fe, 1);
  259. fe->ops.tuner_ops.get_status(fe, &tuner_status);
  260. if (fe->ops.i2c_gate_ctrl)
  261. fe->ops.i2c_gate_ctrl(fe, 0);
  262. }
  263. if (tuner_status)
  264. *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
  265. break;
  266. }
  267. dprintk("%s() status 0x%08x\n", __FUNCTION__, *status);
  268. return 0;
  269. }
  270. static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
  271. {
  272. dprintk("%s()\n", __FUNCTION__);
  273. *snr = 0;
  274. return 0;
  275. }
  276. static int au8522_read_signal_strength(struct dvb_frontend *fe,
  277. u16 *signal_strength)
  278. {
  279. return au8522_read_snr(fe, signal_strength);
  280. }
  281. static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
  282. {
  283. struct au8522_state *state = fe->demodulator_priv;
  284. *ucblocks = au8522_readreg(state, 0x4087);
  285. return 0;
  286. }
  287. static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
  288. {
  289. return au8522_read_ucblocks(fe, ber);
  290. }
  291. static int au8522_get_frontend(struct dvb_frontend *fe,
  292. struct dvb_frontend_parameters *p)
  293. {
  294. struct au8522_state *state = fe->demodulator_priv;
  295. p->frequency = state->current_frequency;
  296. p->u.vsb.modulation = state->current_modulation;
  297. return 0;
  298. }
  299. static int au8522_get_tune_settings(struct dvb_frontend *fe,
  300. struct dvb_frontend_tune_settings *tune)
  301. {
  302. tune->min_delay_ms = 1000;
  303. return 0;
  304. }
  305. static void au8522_release(struct dvb_frontend *fe)
  306. {
  307. struct au8522_state *state = fe->demodulator_priv;
  308. kfree(state);
  309. }
  310. static struct dvb_frontend_ops au8522_ops;
  311. struct dvb_frontend *au8522_attach(const struct au8522_config *config,
  312. struct i2c_adapter *i2c)
  313. {
  314. struct au8522_state *state = NULL;
  315. /* allocate memory for the internal state */
  316. state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
  317. if (state == NULL)
  318. goto error;
  319. /* setup the state */
  320. state->config = config;
  321. state->i2c = i2c;
  322. /* create dvb_frontend */
  323. memcpy(&state->frontend.ops, &au8522_ops,
  324. sizeof(struct dvb_frontend_ops));
  325. state->frontend.demodulator_priv = state;
  326. if (au8522_init(&state->frontend) != 0) {
  327. printk(KERN_ERR "%s: Failed to initialize correctly\n",
  328. __FUNCTION__);
  329. goto error;
  330. }
  331. /* Note: Leaving the I2C gate open here. */
  332. au8522_i2c_gate_ctrl(&state->frontend, 1);
  333. return &state->frontend;
  334. error:
  335. kfree(state);
  336. return NULL;
  337. }
  338. static struct dvb_frontend_ops au8522_ops = {
  339. .info = {
  340. .name = "Auvitek AU8522 QAM/8VSB Frontend",
  341. .type = FE_ATSC,
  342. .frequency_min = 54000000,
  343. .frequency_max = 858000000,
  344. .frequency_stepsize = 62500,
  345. .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
  346. },
  347. .init = au8522_init,
  348. .i2c_gate_ctrl = au8522_i2c_gate_ctrl,
  349. .set_frontend = au8522_set_frontend,
  350. .get_frontend = au8522_get_frontend,
  351. .get_tune_settings = au8522_get_tune_settings,
  352. .read_status = au8522_read_status,
  353. .read_ber = au8522_read_ber,
  354. .read_signal_strength = au8522_read_signal_strength,
  355. .read_snr = au8522_read_snr,
  356. .read_ucblocks = au8522_read_ucblocks,
  357. .release = au8522_release,
  358. };
  359. module_param(debug, int, 0644);
  360. MODULE_PARM_DESC(debug, "Enable verbose debug messages");
  361. MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
  362. MODULE_AUTHOR("Steven Toth");
  363. MODULE_LICENSE("GPL");
  364. EXPORT_SYMBOL(au8522_attach);
  365. /*
  366. * Local variables:
  367. * c-basic-offset: 8
  368. */