mxl111sf-demod.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /*
  2. * mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
  3. *
  4. * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #include "mxl111sf-demod.h"
  21. #include "mxl111sf-reg.h"
  22. /* debug */
  23. static int mxl111sf_demod_debug;
  24. module_param_named(debug, mxl111sf_demod_debug, int, 0644);
  25. MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
  26. #define mxl_dbg(fmt, arg...) \
  27. if (mxl111sf_demod_debug) \
  28. mxl_printk(KERN_DEBUG, fmt, ##arg)
  29. /* ------------------------------------------------------------------------ */
  30. struct mxl111sf_demod_state {
  31. struct mxl111sf_state *mxl_state;
  32. struct mxl111sf_demod_config *cfg;
  33. struct dvb_frontend fe;
  34. };
  35. /* ------------------------------------------------------------------------ */
  36. static int mxl111sf_demod_read_reg(struct mxl111sf_demod_state *state,
  37. u8 addr, u8 *data)
  38. {
  39. return (state->cfg->read_reg) ?
  40. state->cfg->read_reg(state->mxl_state, addr, data) :
  41. -EINVAL;
  42. }
  43. static int mxl111sf_demod_write_reg(struct mxl111sf_demod_state *state,
  44. u8 addr, u8 data)
  45. {
  46. return (state->cfg->write_reg) ?
  47. state->cfg->write_reg(state->mxl_state, addr, data) :
  48. -EINVAL;
  49. }
  50. static
  51. int mxl111sf_demod_program_regs(struct mxl111sf_demod_state *state,
  52. struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
  53. {
  54. return (state->cfg->program_regs) ?
  55. state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
  56. -EINVAL;
  57. }
  58. /* ------------------------------------------------------------------------ */
  59. /* TPS */
  60. static
  61. int mxl1x1sf_demod_get_tps_code_rate(struct mxl111sf_demod_state *state,
  62. fe_code_rate_t *code_rate)
  63. {
  64. u8 val;
  65. int ret = mxl111sf_demod_read_reg(state, V6_CODE_RATE_TPS_REG, &val);
  66. /* bit<2:0> - 000:1/2, 001:2/3, 010:3/4, 011:5/6, 100:7/8 */
  67. if (mxl_fail(ret))
  68. goto fail;
  69. switch (val & V6_CODE_RATE_TPS_MASK) {
  70. case 0:
  71. *code_rate = FEC_1_2;
  72. break;
  73. case 1:
  74. *code_rate = FEC_2_3;
  75. break;
  76. case 2:
  77. *code_rate = FEC_3_4;
  78. break;
  79. case 3:
  80. *code_rate = FEC_5_6;
  81. break;
  82. case 4:
  83. *code_rate = FEC_7_8;
  84. break;
  85. }
  86. fail:
  87. return ret;
  88. }
  89. static
  90. int mxl1x1sf_demod_get_tps_modulation(struct mxl111sf_demod_state *state,
  91. fe_modulation_t *modulation)
  92. {
  93. u8 val;
  94. int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val);
  95. /* Constellation, 00 : QPSK, 01 : 16QAM, 10:64QAM */
  96. if (mxl_fail(ret))
  97. goto fail;
  98. switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) {
  99. case 0:
  100. *modulation = QPSK;
  101. break;
  102. case 1:
  103. *modulation = QAM_16;
  104. break;
  105. case 2:
  106. *modulation = QAM_64;
  107. break;
  108. }
  109. fail:
  110. return ret;
  111. }
  112. static
  113. int mxl1x1sf_demod_get_tps_guard_fft_mode(struct mxl111sf_demod_state *state,
  114. fe_transmit_mode_t *fft_mode)
  115. {
  116. u8 val;
  117. int ret = mxl111sf_demod_read_reg(state, V6_MODE_TPS_REG, &val);
  118. /* FFT Mode, 00:2K, 01:8K, 10:4K */
  119. if (mxl_fail(ret))
  120. goto fail;
  121. switch ((val & V6_PARAM_FFT_MODE_MASK) >> 2) {
  122. case 0:
  123. *fft_mode = TRANSMISSION_MODE_2K;
  124. break;
  125. case 1:
  126. *fft_mode = TRANSMISSION_MODE_8K;
  127. break;
  128. case 2:
  129. *fft_mode = TRANSMISSION_MODE_4K;
  130. break;
  131. }
  132. fail:
  133. return ret;
  134. }
  135. static
  136. int mxl1x1sf_demod_get_tps_guard_interval(struct mxl111sf_demod_state *state,
  137. fe_guard_interval_t *guard)
  138. {
  139. u8 val;
  140. int ret = mxl111sf_demod_read_reg(state, V6_CP_TPS_REG, &val);
  141. /* 00:1/32, 01:1/16, 10:1/8, 11:1/4 */
  142. if (mxl_fail(ret))
  143. goto fail;
  144. switch ((val & V6_PARAM_GI_MASK) >> 4) {
  145. case 0:
  146. *guard = GUARD_INTERVAL_1_32;
  147. break;
  148. case 1:
  149. *guard = GUARD_INTERVAL_1_16;
  150. break;
  151. case 2:
  152. *guard = GUARD_INTERVAL_1_8;
  153. break;
  154. case 3:
  155. *guard = GUARD_INTERVAL_1_4;
  156. break;
  157. }
  158. fail:
  159. return ret;
  160. }
  161. static
  162. int mxl1x1sf_demod_get_tps_hierarchy(struct mxl111sf_demod_state *state,
  163. fe_hierarchy_t *hierarchy)
  164. {
  165. u8 val;
  166. int ret = mxl111sf_demod_read_reg(state, V6_TPS_HIERACHY_REG, &val);
  167. /* bit<6:4> - 000:Non hierarchy, 001:1, 010:2, 011:4 */
  168. if (mxl_fail(ret))
  169. goto fail;
  170. switch ((val & V6_TPS_HIERARCHY_INFO_MASK) >> 6) {
  171. case 0:
  172. *hierarchy = HIERARCHY_NONE;
  173. break;
  174. case 1:
  175. *hierarchy = HIERARCHY_1;
  176. break;
  177. case 2:
  178. *hierarchy = HIERARCHY_2;
  179. break;
  180. case 3:
  181. *hierarchy = HIERARCHY_4;
  182. break;
  183. }
  184. fail:
  185. return ret;
  186. }
  187. /* ------------------------------------------------------------------------ */
  188. /* LOCKS */
  189. static
  190. int mxl1x1sf_demod_get_sync_lock_status(struct mxl111sf_demod_state *state,
  191. int *sync_lock)
  192. {
  193. u8 val = 0;
  194. int ret = mxl111sf_demod_read_reg(state, V6_SYNC_LOCK_REG, &val);
  195. if (mxl_fail(ret))
  196. goto fail;
  197. *sync_lock = (val & SYNC_LOCK_MASK) >> 4;
  198. fail:
  199. return ret;
  200. }
  201. static
  202. int mxl1x1sf_demod_get_rs_lock_status(struct mxl111sf_demod_state *state,
  203. int *rs_lock)
  204. {
  205. u8 val = 0;
  206. int ret = mxl111sf_demod_read_reg(state, V6_RS_LOCK_DET_REG, &val);
  207. if (mxl_fail(ret))
  208. goto fail;
  209. *rs_lock = (val & RS_LOCK_DET_MASK) >> 3;
  210. fail:
  211. return ret;
  212. }
  213. static
  214. int mxl1x1sf_demod_get_tps_lock_status(struct mxl111sf_demod_state *state,
  215. int *tps_lock)
  216. {
  217. u8 val = 0;
  218. int ret = mxl111sf_demod_read_reg(state, V6_TPS_LOCK_REG, &val);
  219. if (mxl_fail(ret))
  220. goto fail;
  221. *tps_lock = (val & V6_PARAM_TPS_LOCK_MASK) >> 6;
  222. fail:
  223. return ret;
  224. }
  225. static
  226. int mxl1x1sf_demod_get_fec_lock_status(struct mxl111sf_demod_state *state,
  227. int *fec_lock)
  228. {
  229. u8 val = 0;
  230. int ret = mxl111sf_demod_read_reg(state, V6_IRQ_STATUS_REG, &val);
  231. if (mxl_fail(ret))
  232. goto fail;
  233. *fec_lock = (val & IRQ_MASK_FEC_LOCK) >> 4;
  234. fail:
  235. return ret;
  236. }
  237. #if 0
  238. static
  239. int mxl1x1sf_demod_get_cp_lock_status(struct mxl111sf_demod_state *state,
  240. int *cp_lock)
  241. {
  242. u8 val = 0;
  243. int ret = mxl111sf_demod_read_reg(state, V6_CP_LOCK_DET_REG, &val);
  244. if (mxl_fail(ret))
  245. goto fail;
  246. *cp_lock = (val & V6_CP_LOCK_DET_MASK) >> 2;
  247. fail:
  248. return ret;
  249. }
  250. #endif
  251. static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state)
  252. {
  253. return mxl111sf_demod_write_reg(state, 0x0e, 0xff);
  254. }
  255. /* ------------------------------------------------------------------------ */
  256. static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe)
  257. {
  258. struct mxl111sf_demod_state *state = fe->demodulator_priv;
  259. int ret = 0;
  260. struct mxl111sf_reg_ctrl_info phy_pll_patch[] = {
  261. {0x00, 0xff, 0x01}, /* change page to 1 */
  262. {0x40, 0xff, 0x05},
  263. {0x40, 0xff, 0x01},
  264. {0x41, 0xff, 0xca},
  265. {0x41, 0xff, 0xc0},
  266. {0x00, 0xff, 0x00}, /* change page to 0 */
  267. {0, 0, 0}
  268. };
  269. mxl_dbg("()");
  270. if (fe->ops.tuner_ops.set_params) {
  271. ret = fe->ops.tuner_ops.set_params(fe);
  272. if (mxl_fail(ret))
  273. goto fail;
  274. msleep(50);
  275. }
  276. ret = mxl111sf_demod_program_regs(state, phy_pll_patch);
  277. mxl_fail(ret);
  278. msleep(50);
  279. ret = mxl1x1sf_demod_reset_irq_status(state);
  280. mxl_fail(ret);
  281. msleep(100);
  282. fail:
  283. return ret;
  284. }
  285. /* ------------------------------------------------------------------------ */
  286. #if 0
  287. /* resets TS Packet error count */
  288. /* After setting 7th bit of V5_PER_COUNT_RESET_REG, it should be reset to 0. */
  289. static
  290. int mxl1x1sf_demod_reset_packet_error_count(struct mxl111sf_demod_state *state)
  291. {
  292. struct mxl111sf_reg_ctrl_info reset_per_count[] = {
  293. {0x20, 0x01, 0x01},
  294. {0x20, 0x01, 0x00},
  295. {0, 0, 0}
  296. };
  297. return mxl111sf_demod_program_regs(state, reset_per_count);
  298. }
  299. #endif
  300. /* returns TS Packet error count */
  301. /* PER Count = FEC_PER_COUNT * (2 ** (FEC_PER_SCALE * 4)) */
  302. static int mxl111sf_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
  303. {
  304. struct mxl111sf_demod_state *state = fe->demodulator_priv;
  305. u32 fec_per_count, fec_per_scale;
  306. u8 val;
  307. int ret;
  308. *ucblocks = 0;
  309. /* FEC_PER_COUNT Register */
  310. ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_COUNT_REG, &val);
  311. if (mxl_fail(ret))
  312. goto fail;
  313. fec_per_count = val;
  314. /* FEC_PER_SCALE Register */
  315. ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_SCALE_REG, &val);
  316. if (mxl_fail(ret))
  317. goto fail;
  318. val &= V6_FEC_PER_SCALE_MASK;
  319. val *= 4;
  320. fec_per_scale = 1 << val;
  321. fec_per_count *= fec_per_scale;
  322. *ucblocks = fec_per_count;
  323. fail:
  324. return ret;
  325. }
  326. #ifdef MXL111SF_DEMOD_ENABLE_CALCULATIONS
  327. /* FIXME: leaving this enabled breaks the build on some architectures,
  328. * and we shouldn't have any floating point math in the kernel, anyway.
  329. *
  330. * These macros need to be re-written, but it's harmless to simply
  331. * return zero for now. */
  332. #define CALCULATE_BER(avg_errors, count) \
  333. ((u32)(avg_errors * 4)/(count*64*188*8))
  334. #define CALCULATE_SNR(data) \
  335. ((u32)((10 * (u32)data / 64) - 2.5))
  336. #else
  337. #define CALCULATE_BER(avg_errors, count) 0
  338. #define CALCULATE_SNR(data) 0
  339. #endif
  340. static int mxl111sf_demod_read_ber(struct dvb_frontend *fe, u32 *ber)
  341. {
  342. struct mxl111sf_demod_state *state = fe->demodulator_priv;
  343. u8 val1, val2, val3;
  344. int ret;
  345. *ber = 0;
  346. ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_LSB_REG, &val1);
  347. if (mxl_fail(ret))
  348. goto fail;
  349. ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_MSB_REG, &val2);
  350. if (mxl_fail(ret))
  351. goto fail;
  352. ret = mxl111sf_demod_read_reg(state, V6_N_ACCUMULATE_REG, &val3);
  353. if (mxl_fail(ret))
  354. goto fail;
  355. *ber = CALCULATE_BER((val1 | (val2 << 8)), val3);
  356. fail:
  357. return ret;
  358. }
  359. static int mxl111sf_demod_calc_snr(struct mxl111sf_demod_state *state,
  360. u16 *snr)
  361. {
  362. u8 val1, val2;
  363. int ret;
  364. *snr = 0;
  365. ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_LSB_REG, &val1);
  366. if (mxl_fail(ret))
  367. goto fail;
  368. ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_MSB_REG, &val2);
  369. if (mxl_fail(ret))
  370. goto fail;
  371. *snr = CALCULATE_SNR(val1 | ((val2 & 0x03) << 8));
  372. fail:
  373. return ret;
  374. }
  375. static int mxl111sf_demod_read_snr(struct dvb_frontend *fe, u16 *snr)
  376. {
  377. struct mxl111sf_demod_state *state = fe->demodulator_priv;
  378. int ret = mxl111sf_demod_calc_snr(state, snr);
  379. if (mxl_fail(ret))
  380. goto fail;
  381. *snr /= 10; /* 0.1 dB */
  382. fail:
  383. return ret;
  384. }
  385. static int mxl111sf_demod_read_status(struct dvb_frontend *fe,
  386. fe_status_t *status)
  387. {
  388. struct mxl111sf_demod_state *state = fe->demodulator_priv;
  389. int ret, locked, cr_lock, sync_lock, fec_lock;
  390. *status = 0;
  391. ret = mxl1x1sf_demod_get_rs_lock_status(state, &locked);
  392. if (mxl_fail(ret))
  393. goto fail;
  394. ret = mxl1x1sf_demod_get_tps_lock_status(state, &cr_lock);
  395. if (mxl_fail(ret))
  396. goto fail;
  397. ret = mxl1x1sf_demod_get_sync_lock_status(state, &sync_lock);
  398. if (mxl_fail(ret))
  399. goto fail;
  400. ret = mxl1x1sf_demod_get_fec_lock_status(state, &fec_lock);
  401. if (mxl_fail(ret))
  402. goto fail;
  403. if (locked)
  404. *status |= FE_HAS_SIGNAL;
  405. if (cr_lock)
  406. *status |= FE_HAS_CARRIER;
  407. if (sync_lock)
  408. *status |= FE_HAS_SYNC;
  409. if (fec_lock) /* false positives? */
  410. *status |= FE_HAS_VITERBI;
  411. if ((locked) && (cr_lock) && (sync_lock))
  412. *status |= FE_HAS_LOCK;
  413. fail:
  414. return ret;
  415. }
  416. static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
  417. u16 *signal_strength)
  418. {
  419. struct mxl111sf_demod_state *state = fe->demodulator_priv;
  420. fe_modulation_t modulation;
  421. u16 snr;
  422. mxl111sf_demod_calc_snr(state, &snr);
  423. mxl1x1sf_demod_get_tps_modulation(state, &modulation);
  424. switch (modulation) {
  425. case QPSK:
  426. *signal_strength = (snr >= 1300) ?
  427. min(65535, snr * 44) : snr * 38;
  428. break;
  429. case QAM_16:
  430. *signal_strength = (snr >= 1500) ?
  431. min(65535, snr * 38) : snr * 33;
  432. break;
  433. case QAM_64:
  434. *signal_strength = (snr >= 2000) ?
  435. min(65535, snr * 29) : snr * 25;
  436. break;
  437. default:
  438. *signal_strength = 0;
  439. return -EINVAL;
  440. }
  441. return 0;
  442. }
  443. static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe)
  444. {
  445. struct dtv_frontend_properties *p = &fe->dtv_property_cache;
  446. struct mxl111sf_demod_state *state = fe->demodulator_priv;
  447. mxl_dbg("()");
  448. #if 0
  449. p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF;
  450. #endif
  451. if (fe->ops.tuner_ops.get_bandwidth)
  452. fe->ops.tuner_ops.get_bandwidth(fe, &p->bandwidth_hz);
  453. if (fe->ops.tuner_ops.get_frequency)
  454. fe->ops.tuner_ops.get_frequency(fe, &p->frequency);
  455. mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_HP);
  456. mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_LP);
  457. mxl1x1sf_demod_get_tps_modulation(state, &p->modulation);
  458. mxl1x1sf_demod_get_tps_guard_fft_mode(state,
  459. &p->transmission_mode);
  460. mxl1x1sf_demod_get_tps_guard_interval(state,
  461. &p->guard_interval);
  462. mxl1x1sf_demod_get_tps_hierarchy(state,
  463. &p->hierarchy);
  464. return 0;
  465. }
  466. static
  467. int mxl111sf_demod_get_tune_settings(struct dvb_frontend *fe,
  468. struct dvb_frontend_tune_settings *tune)
  469. {
  470. tune->min_delay_ms = 1000;
  471. return 0;
  472. }
  473. static void mxl111sf_demod_release(struct dvb_frontend *fe)
  474. {
  475. struct mxl111sf_demod_state *state = fe->demodulator_priv;
  476. mxl_dbg("()");
  477. kfree(state);
  478. fe->demodulator_priv = NULL;
  479. }
  480. static struct dvb_frontend_ops mxl111sf_demod_ops = {
  481. .delsys = { SYS_DVBT },
  482. .info = {
  483. .name = "MaxLinear MxL111SF DVB-T demodulator",
  484. .frequency_min = 177000000,
  485. .frequency_max = 858000000,
  486. .frequency_stepsize = 166666,
  487. .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
  488. FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
  489. FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
  490. FE_CAN_QAM_AUTO |
  491. FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
  492. FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
  493. },
  494. .release = mxl111sf_demod_release,
  495. #if 0
  496. .init = mxl111sf_init,
  497. .i2c_gate_ctrl = mxl111sf_i2c_gate_ctrl,
  498. #endif
  499. .set_frontend = mxl111sf_demod_set_frontend,
  500. .get_frontend = mxl111sf_demod_get_frontend,
  501. .get_tune_settings = mxl111sf_demod_get_tune_settings,
  502. .read_status = mxl111sf_demod_read_status,
  503. .read_signal_strength = mxl111sf_demod_read_signal_strength,
  504. .read_ber = mxl111sf_demod_read_ber,
  505. .read_snr = mxl111sf_demod_read_snr,
  506. .read_ucblocks = mxl111sf_demod_read_ucblocks,
  507. };
  508. struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
  509. struct mxl111sf_demod_config *cfg)
  510. {
  511. struct mxl111sf_demod_state *state = NULL;
  512. mxl_dbg("()");
  513. state = kzalloc(sizeof(struct mxl111sf_demod_state), GFP_KERNEL);
  514. if (state == NULL)
  515. return NULL;
  516. state->mxl_state = mxl_state;
  517. state->cfg = cfg;
  518. memcpy(&state->fe.ops, &mxl111sf_demod_ops,
  519. sizeof(struct dvb_frontend_ops));
  520. state->fe.demodulator_priv = state;
  521. return &state->fe;
  522. }
  523. EXPORT_SYMBOL_GPL(mxl111sf_demod_attach);
  524. MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
  525. MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
  526. MODULE_LICENSE("GPL");
  527. MODULE_VERSION("0.1");
  528. /*
  529. * Local variables:
  530. * c-basic-offset: 8
  531. * End:
  532. */