mxl111sf-tuner.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /*
  2. * mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
  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-tuner.h"
  21. #include "mxl111sf-phy.h"
  22. #include "mxl111sf-reg.h"
  23. /* debug */
  24. static int mxl111sf_tuner_debug;
  25. module_param_named(debug, mxl111sf_tuner_debug, int, 0644);
  26. MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
  27. #define mxl_dbg(fmt, arg...) \
  28. if (mxl111sf_tuner_debug) \
  29. mxl_printk(KERN_DEBUG, fmt, ##arg)
  30. #define err pr_err
  31. /* ------------------------------------------------------------------------ */
  32. struct mxl111sf_tuner_state {
  33. struct mxl111sf_state *mxl_state;
  34. struct mxl111sf_tuner_config *cfg;
  35. enum mxl_if_freq if_freq;
  36. u32 frequency;
  37. u32 bandwidth;
  38. };
  39. static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
  40. u8 addr, u8 *data)
  41. {
  42. return (state->cfg->read_reg) ?
  43. state->cfg->read_reg(state->mxl_state, addr, data) :
  44. -EINVAL;
  45. }
  46. static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
  47. u8 addr, u8 data)
  48. {
  49. return (state->cfg->write_reg) ?
  50. state->cfg->write_reg(state->mxl_state, addr, data) :
  51. -EINVAL;
  52. }
  53. static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
  54. struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
  55. {
  56. return (state->cfg->program_regs) ?
  57. state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
  58. -EINVAL;
  59. }
  60. static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
  61. int onoff)
  62. {
  63. return (state->cfg->top_master_ctrl) ?
  64. state->cfg->top_master_ctrl(state->mxl_state, onoff) :
  65. -EINVAL;
  66. }
  67. /* ------------------------------------------------------------------------ */
  68. static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
  69. {0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
  70. DIG_MODEINDEX, _A, _CSF, */
  71. {0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
  72. {0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
  73. {0, 0, 0}
  74. };
  75. /* ------------------------------------------------------------------------ */
  76. static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
  77. u8 bw)
  78. {
  79. u8 filt_bw;
  80. /* set channel bandwidth */
  81. switch (bw) {
  82. case 0: /* ATSC */
  83. filt_bw = 25;
  84. break;
  85. case 1: /* QAM */
  86. filt_bw = 69;
  87. break;
  88. case 6:
  89. filt_bw = 21;
  90. break;
  91. case 7:
  92. filt_bw = 42;
  93. break;
  94. case 8:
  95. filt_bw = 63;
  96. break;
  97. default:
  98. err("%s: invalid bandwidth setting!", __func__);
  99. return NULL;
  100. }
  101. /* calculate RF channel */
  102. freq /= 1000000;
  103. freq *= 64;
  104. #if 0
  105. /* do round */
  106. freq += 0.5;
  107. #endif
  108. /* set bandwidth */
  109. mxl_phy_tune_rf[0].data = filt_bw;
  110. /* set RF */
  111. mxl_phy_tune_rf[1].data = (freq & 0xff);
  112. mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
  113. /* start tune */
  114. return mxl_phy_tune_rf;
  115. }
  116. static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
  117. {
  118. int ret;
  119. u8 ctrl;
  120. #if 0
  121. u16 iffcw;
  122. u32 if_freq;
  123. #endif
  124. mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
  125. state->cfg->invert_spectrum, state->cfg->if_freq);
  126. /* set IF polarity */
  127. ctrl = state->cfg->invert_spectrum;
  128. ctrl |= state->cfg->if_freq;
  129. ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
  130. if (mxl_fail(ret))
  131. goto fail;
  132. #if 0
  133. if_freq /= 1000000;
  134. /* do round */
  135. if_freq += 0.5;
  136. if (MXL_IF_LO == state->cfg->if_freq) {
  137. ctrl = 0x08;
  138. iffcw = (u16)(if_freq / (108 * 4096));
  139. } else if (MXL_IF_HI == state->cfg->if_freq) {
  140. ctrl = 0x08;
  141. iffcw = (u16)(if_freq / (216 * 4096));
  142. } else {
  143. ctrl = 0;
  144. iffcw = 0;
  145. }
  146. ctrl |= (iffcw >> 8);
  147. #endif
  148. ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
  149. if (mxl_fail(ret))
  150. goto fail;
  151. ctrl &= 0xf0;
  152. ctrl |= 0x90;
  153. ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
  154. if (mxl_fail(ret))
  155. goto fail;
  156. #if 0
  157. ctrl = iffcw & 0x00ff;
  158. #endif
  159. ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
  160. if (mxl_fail(ret))
  161. goto fail;
  162. state->if_freq = state->cfg->if_freq;
  163. fail:
  164. return ret;
  165. }
  166. static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
  167. {
  168. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  169. static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
  170. int ret;
  171. u8 mxl_mode;
  172. mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
  173. /* stop tune */
  174. ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
  175. if (mxl_fail(ret))
  176. goto fail;
  177. /* check device mode */
  178. ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
  179. if (mxl_fail(ret))
  180. goto fail;
  181. /* Fill out registers for channel tune */
  182. reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
  183. if (!reg_ctrl_array)
  184. return -EINVAL;
  185. ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
  186. if (mxl_fail(ret))
  187. goto fail;
  188. if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
  189. /* IF tuner mode only */
  190. mxl1x1sf_tuner_top_master_ctrl(state, 0);
  191. mxl1x1sf_tuner_top_master_ctrl(state, 1);
  192. mxl1x1sf_tuner_set_if_output_freq(state);
  193. }
  194. ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
  195. if (mxl_fail(ret))
  196. goto fail;
  197. if (state->cfg->ant_hunt)
  198. state->cfg->ant_hunt(fe);
  199. fail:
  200. return ret;
  201. }
  202. static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
  203. int *rf_synth_lock,
  204. int *ref_synth_lock)
  205. {
  206. int ret;
  207. u8 data;
  208. *rf_synth_lock = 0;
  209. *ref_synth_lock = 0;
  210. ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
  211. if (mxl_fail(ret))
  212. goto fail;
  213. *ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
  214. *rf_synth_lock = ((data & 0x0c) == 0x0c) ? 1 : 0;
  215. fail:
  216. return ret;
  217. }
  218. #if 0
  219. static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
  220. int onoff)
  221. {
  222. return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
  223. onoff ? 1 : 0);
  224. }
  225. #endif
  226. /* ------------------------------------------------------------------------ */
  227. static int mxl111sf_tuner_set_params(struct dvb_frontend *fe)
  228. {
  229. struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  230. u32 delsys = c->delivery_system;
  231. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  232. int ret;
  233. u8 bw;
  234. mxl_dbg("()");
  235. switch (delsys) {
  236. case SYS_ATSC:
  237. case SYS_ATSCMH:
  238. bw = 0; /* ATSC */
  239. break;
  240. case SYS_DVBC_ANNEX_B:
  241. bw = 1; /* US CABLE */
  242. break;
  243. case SYS_DVBT:
  244. switch (c->bandwidth_hz) {
  245. case 6000000:
  246. bw = 6;
  247. break;
  248. case 7000000:
  249. bw = 7;
  250. break;
  251. case 8000000:
  252. bw = 8;
  253. break;
  254. default:
  255. err("%s: bandwidth not set!", __func__);
  256. return -EINVAL;
  257. }
  258. break;
  259. default:
  260. err("%s: modulation type not supported!", __func__);
  261. return -EINVAL;
  262. }
  263. ret = mxl1x1sf_tune_rf(fe, c->frequency, bw);
  264. if (mxl_fail(ret))
  265. goto fail;
  266. state->frequency = c->frequency;
  267. state->bandwidth = c->bandwidth_hz;
  268. fail:
  269. return ret;
  270. }
  271. /* ------------------------------------------------------------------------ */
  272. #if 0
  273. static int mxl111sf_tuner_init(struct dvb_frontend *fe)
  274. {
  275. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  276. int ret;
  277. /* wake from standby handled by usb driver */
  278. return ret;
  279. }
  280. static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
  281. {
  282. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  283. int ret;
  284. /* enter standby mode handled by usb driver */
  285. return ret;
  286. }
  287. #endif
  288. /* ------------------------------------------------------------------------ */
  289. static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
  290. {
  291. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  292. int rf_locked, ref_locked, ret;
  293. *status = 0;
  294. ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
  295. if (mxl_fail(ret))
  296. goto fail;
  297. mxl_info("%s%s", rf_locked ? "rf locked " : "",
  298. ref_locked ? "ref locked" : "");
  299. if ((rf_locked) || (ref_locked))
  300. *status |= TUNER_STATUS_LOCKED;
  301. fail:
  302. return ret;
  303. }
  304. static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
  305. {
  306. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  307. u8 val1, val2;
  308. int ret;
  309. *strength = 0;
  310. ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
  311. if (mxl_fail(ret))
  312. goto fail;
  313. ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
  314. if (mxl_fail(ret))
  315. goto fail;
  316. ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
  317. if (mxl_fail(ret))
  318. goto fail;
  319. *strength = val1 | ((val2 & 0x07) << 8);
  320. fail:
  321. ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
  322. mxl_fail(ret);
  323. return ret;
  324. }
  325. /* ------------------------------------------------------------------------ */
  326. static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
  327. {
  328. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  329. *frequency = state->frequency;
  330. return 0;
  331. }
  332. static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
  333. {
  334. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  335. *bandwidth = state->bandwidth;
  336. return 0;
  337. }
  338. static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe,
  339. u32 *frequency)
  340. {
  341. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  342. *frequency = 0;
  343. switch (state->if_freq) {
  344. case MXL_IF_4_0: /* 4.0 MHz */
  345. *frequency = 4000000;
  346. break;
  347. case MXL_IF_4_5: /* 4.5 MHz */
  348. *frequency = 4500000;
  349. break;
  350. case MXL_IF_4_57: /* 4.57 MHz */
  351. *frequency = 4570000;
  352. break;
  353. case MXL_IF_5_0: /* 5.0 MHz */
  354. *frequency = 5000000;
  355. break;
  356. case MXL_IF_5_38: /* 5.38 MHz */
  357. *frequency = 5380000;
  358. break;
  359. case MXL_IF_6_0: /* 6.0 MHz */
  360. *frequency = 6000000;
  361. break;
  362. case MXL_IF_6_28: /* 6.28 MHz */
  363. *frequency = 6280000;
  364. break;
  365. case MXL_IF_7_2: /* 7.2 MHz */
  366. *frequency = 7200000;
  367. break;
  368. case MXL_IF_35_25: /* 35.25 MHz */
  369. *frequency = 35250000;
  370. break;
  371. case MXL_IF_36: /* 36 MHz */
  372. *frequency = 36000000;
  373. break;
  374. case MXL_IF_36_15: /* 36.15 MHz */
  375. *frequency = 36150000;
  376. break;
  377. case MXL_IF_44: /* 44 MHz */
  378. *frequency = 44000000;
  379. break;
  380. }
  381. return 0;
  382. }
  383. static int mxl111sf_tuner_release(struct dvb_frontend *fe)
  384. {
  385. struct mxl111sf_tuner_state *state = fe->tuner_priv;
  386. mxl_dbg("()");
  387. kfree(state);
  388. fe->tuner_priv = NULL;
  389. return 0;
  390. }
  391. /* ------------------------------------------------------------------------- */
  392. static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
  393. .info = {
  394. .name = "MaxLinear MxL111SF",
  395. #if 0
  396. .frequency_min = ,
  397. .frequency_max = ,
  398. .frequency_step = ,
  399. #endif
  400. },
  401. #if 0
  402. .init = mxl111sf_tuner_init,
  403. .sleep = mxl111sf_tuner_sleep,
  404. #endif
  405. .set_params = mxl111sf_tuner_set_params,
  406. .get_status = mxl111sf_tuner_get_status,
  407. .get_rf_strength = mxl111sf_get_rf_strength,
  408. .get_frequency = mxl111sf_tuner_get_frequency,
  409. .get_bandwidth = mxl111sf_tuner_get_bandwidth,
  410. .get_if_frequency = mxl111sf_tuner_get_if_frequency,
  411. .release = mxl111sf_tuner_release,
  412. };
  413. struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
  414. struct mxl111sf_state *mxl_state,
  415. struct mxl111sf_tuner_config *cfg)
  416. {
  417. struct mxl111sf_tuner_state *state = NULL;
  418. mxl_dbg("()");
  419. state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
  420. if (state == NULL)
  421. return NULL;
  422. state->mxl_state = mxl_state;
  423. state->cfg = cfg;
  424. memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
  425. sizeof(struct dvb_tuner_ops));
  426. fe->tuner_priv = state;
  427. return fe;
  428. }
  429. EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
  430. MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
  431. MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
  432. MODULE_LICENSE("GPL");
  433. MODULE_VERSION("0.1");
  434. /*
  435. * Overrides for Emacs so that we follow Linus's tabbing style.
  436. * ---------------------------------------------------------------------------
  437. * Local variables:
  438. * c-basic-offset: 8
  439. * End:
  440. */