at76c651.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*
  2. * at76c651.c
  3. *
  4. * Atmel DVB-C Frontend Driver (at76c651/tua6010xs)
  5. *
  6. * Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
  7. * & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
  8. * & 2003 Wolfram Joost <dbox2@frokaschwei.de>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. *
  24. * AT76C651
  25. * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
  26. * http://www.atmel.com/atmel/acrobat/doc1320.pdf
  27. */
  28. #include <linux/init.h>
  29. #include <linux/module.h>
  30. #include <linux/moduleparam.h>
  31. #include <linux/kernel.h>
  32. #include <linux/string.h>
  33. #include <linux/slab.h>
  34. #include <linux/bitops.h>
  35. #include "dvb_frontend.h"
  36. #include "at76c651.h"
  37. struct at76c651_state {
  38. struct i2c_adapter* i2c;
  39. struct dvb_frontend_ops ops;
  40. const struct at76c651_config* config;
  41. struct dvb_frontend frontend;
  42. /* revision of the chip */
  43. u8 revision;
  44. /* last QAM value set */
  45. u8 qam;
  46. };
  47. static int debug;
  48. #define dprintk(args...) \
  49. do { \
  50. if (debug) printk(KERN_DEBUG "at76c651: " args); \
  51. } while (0)
  52. #if ! defined(__powerpc__)
  53. static __inline__ int __ilog2(unsigned long x)
  54. {
  55. int i;
  56. if (x == 0)
  57. return -1;
  58. for (i = 0; x != 0; i++)
  59. x >>= 1;
  60. return i - 1;
  61. }
  62. #endif
  63. static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data)
  64. {
  65. int ret;
  66. u8 buf[] = { reg, data };
  67. struct i2c_msg msg =
  68. { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
  69. ret = i2c_transfer(state->i2c, &msg, 1);
  70. if (ret != 1)
  71. dprintk("%s: writereg error "
  72. "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
  73. __FUNCTION__, reg, data, ret);
  74. msleep(10);
  75. return (ret != 1) ? -EREMOTEIO : 0;
  76. }
  77. static u8 at76c651_readreg(struct at76c651_state* state, u8 reg)
  78. {
  79. int ret;
  80. u8 val;
  81. struct i2c_msg msg[] = {
  82. { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
  83. { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 }
  84. };
  85. ret = i2c_transfer(state->i2c, msg, 2);
  86. if (ret != 2)
  87. dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
  88. return val;
  89. }
  90. static int at76c651_reset(struct at76c651_state* state)
  91. {
  92. return at76c651_writereg(state, 0x07, 0x01);
  93. }
  94. static void at76c651_disable_interrupts(struct at76c651_state* state)
  95. {
  96. at76c651_writereg(state, 0x0b, 0x00);
  97. }
  98. static int at76c651_set_auto_config(struct at76c651_state *state)
  99. {
  100. /*
  101. * Autoconfig
  102. */
  103. at76c651_writereg(state, 0x06, 0x01);
  104. /*
  105. * Performance optimizations, should be done after autoconfig
  106. */
  107. at76c651_writereg(state, 0x10, 0x06);
  108. at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10);
  109. at76c651_writereg(state, 0x15, 0x28);
  110. at76c651_writereg(state, 0x20, 0x09);
  111. at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90);
  112. at76c651_writereg(state, 0x30, 0x90);
  113. if (state->qam == 5)
  114. at76c651_writereg(state, 0x35, 0x2A);
  115. /*
  116. * Initialize A/D-converter
  117. */
  118. if (state->revision == 0x11) {
  119. at76c651_writereg(state, 0x2E, 0x38);
  120. at76c651_writereg(state, 0x2F, 0x13);
  121. }
  122. at76c651_disable_interrupts(state);
  123. /*
  124. * Restart operation
  125. */
  126. at76c651_reset(state);
  127. return 0;
  128. }
  129. static void at76c651_set_bbfreq(struct at76c651_state* state)
  130. {
  131. at76c651_writereg(state, 0x04, 0x3f);
  132. at76c651_writereg(state, 0x05, 0xee);
  133. }
  134. static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate)
  135. {
  136. u8 exponent;
  137. u32 mantissa;
  138. if (symbol_rate > 9360000)
  139. return -EINVAL;
  140. /*
  141. * FREF = 57800 kHz
  142. * exponent = 10 + floor (log2(symbol_rate / FREF))
  143. * mantissa = (symbol_rate / FREF) * (1 << (30 - exponent))
  144. */
  145. exponent = __ilog2((symbol_rate << 4) / 903125);
  146. mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289;
  147. at76c651_writereg(state, 0x00, mantissa >> 13);
  148. at76c651_writereg(state, 0x01, mantissa >> 5);
  149. at76c651_writereg(state, 0x02, (mantissa << 3) | exponent);
  150. return 0;
  151. }
  152. static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam)
  153. {
  154. switch (qam) {
  155. case QPSK:
  156. state->qam = 0x02;
  157. break;
  158. case QAM_16:
  159. state->qam = 0x04;
  160. break;
  161. case QAM_32:
  162. state->qam = 0x05;
  163. break;
  164. case QAM_64:
  165. state->qam = 0x06;
  166. break;
  167. case QAM_128:
  168. state->qam = 0x07;
  169. break;
  170. case QAM_256:
  171. state->qam = 0x08;
  172. break;
  173. #if 0
  174. case QAM_512:
  175. state->qam = 0x09;
  176. break;
  177. case QAM_1024:
  178. state->qam = 0x0A;
  179. break;
  180. #endif
  181. default:
  182. return -EINVAL;
  183. }
  184. return at76c651_writereg(state, 0x03, state->qam);
  185. }
  186. static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion)
  187. {
  188. u8 feciqinv = at76c651_readreg(state, 0x60);
  189. switch (inversion) {
  190. case INVERSION_OFF:
  191. feciqinv |= 0x02;
  192. feciqinv &= 0xFE;
  193. break;
  194. case INVERSION_ON:
  195. feciqinv |= 0x03;
  196. break;
  197. case INVERSION_AUTO:
  198. feciqinv &= 0xFC;
  199. break;
  200. default:
  201. return -EINVAL;
  202. }
  203. return at76c651_writereg(state, 0x60, feciqinv);
  204. }
  205. static int at76c651_set_parameters(struct dvb_frontend* fe,
  206. struct dvb_frontend_parameters *p)
  207. {
  208. int ret;
  209. struct at76c651_state* state = fe->demodulator_priv;
  210. at76c651_writereg(state, 0x0c, 0xc3);
  211. state->config->pll_set(fe, p);
  212. at76c651_writereg(state, 0x0c, 0xc2);
  213. if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate)))
  214. return ret;
  215. if ((ret = at76c651_set_inversion(state, p->inversion)))
  216. return ret;
  217. return at76c651_set_auto_config(state);
  218. }
  219. static int at76c651_set_defaults(struct dvb_frontend* fe)
  220. {
  221. struct at76c651_state* state = fe->demodulator_priv;
  222. at76c651_set_symbol_rate(state, 6900000);
  223. at76c651_set_qam(state, QAM_64);
  224. at76c651_set_bbfreq(state);
  225. at76c651_set_auto_config(state);
  226. if (state->config->pll_init) {
  227. at76c651_writereg(state, 0x0c, 0xc3);
  228. state->config->pll_init(fe);
  229. at76c651_writereg(state, 0x0c, 0xc2);
  230. }
  231. return 0;
  232. }
  233. static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status)
  234. {
  235. struct at76c651_state* state = fe->demodulator_priv;
  236. u8 sync;
  237. /*
  238. * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0)
  239. */
  240. sync = at76c651_readreg(state, 0x80);
  241. *status = 0;
  242. if (sync & (0x04 | 0x10)) /* AGC1 || TIM */
  243. *status |= FE_HAS_SIGNAL;
  244. if (sync & 0x10) /* TIM */
  245. *status |= FE_HAS_CARRIER;
  246. if (sync & 0x80) /* FEC */
  247. *status |= FE_HAS_VITERBI;
  248. if (sync & 0x40) /* CAR */
  249. *status |= FE_HAS_SYNC;
  250. if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */
  251. *status |= FE_HAS_LOCK;
  252. return 0;
  253. }
  254. static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber)
  255. {
  256. struct at76c651_state* state = fe->demodulator_priv;
  257. *ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16;
  258. *ber |= at76c651_readreg(state, 0x82) << 8;
  259. *ber |= at76c651_readreg(state, 0x83);
  260. *ber *= 10;
  261. return 0;
  262. }
  263. static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength)
  264. {
  265. struct at76c651_state* state = fe->demodulator_priv;
  266. u8 gain = ~at76c651_readreg(state, 0x91);
  267. *strength = (gain << 8) | gain;
  268. return 0;
  269. }
  270. static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr)
  271. {
  272. struct at76c651_state* state = fe->demodulator_priv;
  273. *snr = 0xFFFF -
  274. ((at76c651_readreg(state, 0x8F) << 8) |
  275. at76c651_readreg(state, 0x90));
  276. return 0;
  277. }
  278. static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
  279. {
  280. struct at76c651_state* state = fe->demodulator_priv;
  281. *ucblocks = at76c651_readreg(state, 0x82);
  282. return 0;
  283. }
  284. static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings)
  285. {
  286. fesettings->min_delay_ms = 50;
  287. fesettings->step_size = 0;
  288. fesettings->max_drift = 0;
  289. return 0;
  290. }
  291. static void at76c651_release(struct dvb_frontend* fe)
  292. {
  293. struct at76c651_state* state = fe->demodulator_priv;
  294. kfree(state);
  295. }
  296. static struct dvb_frontend_ops at76c651_ops;
  297. struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
  298. struct i2c_adapter* i2c)
  299. {
  300. struct at76c651_state* state = NULL;
  301. /* allocate memory for the internal state */
  302. state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL);
  303. if (state == NULL) goto error;
  304. /* setup the state */
  305. state->config = config;
  306. state->qam = 0;
  307. /* check if the demod is there */
  308. if (at76c651_readreg(state, 0x0e) != 0x65) goto error;
  309. /* finalise state setup */
  310. state->i2c = i2c;
  311. state->revision = at76c651_readreg(state, 0x0f) & 0xfe;
  312. memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops));
  313. /* create dvb_frontend */
  314. state->frontend.ops = &state->ops;
  315. state->frontend.demodulator_priv = state;
  316. return &state->frontend;
  317. error:
  318. kfree(state);
  319. return NULL;
  320. }
  321. static struct dvb_frontend_ops at76c651_ops = {
  322. .info = {
  323. .name = "Atmel AT76C651B DVB-C",
  324. .type = FE_QAM,
  325. .frequency_min = 48250000,
  326. .frequency_max = 863250000,
  327. .frequency_stepsize = 62500,
  328. /*.frequency_tolerance = */ /* FIXME: 12% of SR */
  329. .symbol_rate_min = 0, /* FIXME */
  330. .symbol_rate_max = 9360000, /* FIXME */
  331. .symbol_rate_tolerance = 4000,
  332. .caps = FE_CAN_INVERSION_AUTO |
  333. FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
  334. FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
  335. FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
  336. FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 |
  337. FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
  338. },
  339. .release = at76c651_release,
  340. .init = at76c651_set_defaults,
  341. .set_frontend = at76c651_set_parameters,
  342. .get_tune_settings = at76c651_get_tune_settings,
  343. .read_status = at76c651_read_status,
  344. .read_ber = at76c651_read_ber,
  345. .read_signal_strength = at76c651_read_signal_strength,
  346. .read_snr = at76c651_read_snr,
  347. .read_ucblocks = at76c651_read_ucblocks,
  348. };
  349. module_param(debug, int, 0644);
  350. MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
  351. MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver");
  352. MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
  353. MODULE_LICENSE("GPL");
  354. EXPORT_SYMBOL(at76c651_attach);