m88ts2022.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. /*
  2. * Montage M88TS2022 silicon tuner driver
  3. *
  4. * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
  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. * Some calculations are taken from existing TS2020 driver.
  17. */
  18. #include "m88ts2022_priv.h"
  19. static int m88ts2022_cmd(struct m88ts2022_dev *dev, int op, int sleep, u8 reg,
  20. u8 mask, u8 val, u8 *reg_val)
  21. {
  22. int ret, i;
  23. unsigned int utmp;
  24. struct m88ts2022_reg_val reg_vals[] = {
  25. {0x51, 0x1f - op},
  26. {0x51, 0x1f},
  27. {0x50, 0x00 + op},
  28. {0x50, 0x00},
  29. };
  30. for (i = 0; i < 2; i++) {
  31. dev_dbg(&dev->client->dev,
  32. "i=%d op=%02x reg=%02x mask=%02x val=%02x\n",
  33. i, op, reg, mask, val);
  34. for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
  35. ret = regmap_write(dev->regmap, reg_vals[i].reg,
  36. reg_vals[i].val);
  37. if (ret)
  38. goto err;
  39. }
  40. usleep_range(sleep * 1000, sleep * 10000);
  41. ret = regmap_read(dev->regmap, reg, &utmp);
  42. if (ret)
  43. goto err;
  44. if ((utmp & mask) != val)
  45. break;
  46. }
  47. if (reg_val)
  48. *reg_val = utmp;
  49. err:
  50. return ret;
  51. }
  52. static int m88ts2022_set_params(struct dvb_frontend *fe)
  53. {
  54. struct m88ts2022_dev *dev = fe->tuner_priv;
  55. struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  56. int ret;
  57. unsigned int utmp, frequency_khz, frequency_offset_khz, f_3db_hz;
  58. unsigned int f_ref_khz, f_vco_khz, div_ref, div_out, pll_n, gdiv28;
  59. u8 buf[3], u8tmp, cap_code, lpf_gm, lpf_mxdiv, div_max, div_min;
  60. u16 u16tmp;
  61. dev_dbg(&dev->client->dev,
  62. "frequency=%d symbol_rate=%d rolloff=%d\n",
  63. c->frequency, c->symbol_rate, c->rolloff);
  64. /*
  65. * Integer-N PLL synthesizer
  66. * kHz is used for all calculations to keep calculations within 32-bit
  67. */
  68. f_ref_khz = DIV_ROUND_CLOSEST(dev->cfg.clock, 1000);
  69. div_ref = DIV_ROUND_CLOSEST(f_ref_khz, 2000);
  70. if (c->symbol_rate < 5000000)
  71. frequency_offset_khz = 3000; /* 3 MHz */
  72. else
  73. frequency_offset_khz = 0;
  74. frequency_khz = c->frequency + frequency_offset_khz;
  75. if (frequency_khz < 1103000) {
  76. div_out = 4;
  77. u8tmp = 0x1b;
  78. } else {
  79. div_out = 2;
  80. u8tmp = 0x0b;
  81. }
  82. buf[0] = u8tmp;
  83. buf[1] = 0x40;
  84. ret = regmap_bulk_write(dev->regmap, 0x10, buf, 2);
  85. if (ret)
  86. goto err;
  87. f_vco_khz = frequency_khz * div_out;
  88. pll_n = f_vco_khz * div_ref / f_ref_khz;
  89. pll_n += pll_n % 2;
  90. dev->frequency_khz = pll_n * f_ref_khz / div_ref / div_out;
  91. if (pll_n < 4095)
  92. u16tmp = pll_n - 1024;
  93. else if (pll_n < 6143)
  94. u16tmp = pll_n + 1024;
  95. else
  96. u16tmp = pll_n + 3072;
  97. buf[0] = (u16tmp >> 8) & 0x3f;
  98. buf[1] = (u16tmp >> 0) & 0xff;
  99. buf[2] = div_ref - 8;
  100. ret = regmap_bulk_write(dev->regmap, 0x01, buf, 3);
  101. if (ret)
  102. goto err;
  103. dev_dbg(&dev->client->dev,
  104. "frequency=%u offset=%d f_vco_khz=%u pll_n=%u div_ref=%u div_out=%u\n",
  105. dev->frequency_khz, dev->frequency_khz - c->frequency,
  106. f_vco_khz, pll_n, div_ref, div_out);
  107. ret = m88ts2022_cmd(dev, 0x10, 5, 0x15, 0x40, 0x00, NULL);
  108. if (ret)
  109. goto err;
  110. ret = regmap_read(dev->regmap, 0x14, &utmp);
  111. if (ret)
  112. goto err;
  113. utmp &= 0x7f;
  114. if (utmp < 64) {
  115. ret = regmap_update_bits(dev->regmap, 0x10, 0x80, 0x80);
  116. if (ret)
  117. goto err;
  118. ret = regmap_write(dev->regmap, 0x11, 0x6f);
  119. if (ret)
  120. goto err;
  121. ret = m88ts2022_cmd(dev, 0x10, 5, 0x15, 0x40, 0x00, NULL);
  122. if (ret)
  123. goto err;
  124. }
  125. ret = regmap_read(dev->regmap, 0x14, &utmp);
  126. if (ret)
  127. goto err;
  128. utmp &= 0x1f;
  129. if (utmp > 19) {
  130. ret = regmap_update_bits(dev->regmap, 0x10, 0x02, 0x00);
  131. if (ret)
  132. goto err;
  133. }
  134. ret = m88ts2022_cmd(dev, 0x08, 5, 0x3c, 0xff, 0x00, NULL);
  135. if (ret)
  136. goto err;
  137. ret = regmap_write(dev->regmap, 0x25, 0x00);
  138. if (ret)
  139. goto err;
  140. ret = regmap_write(dev->regmap, 0x27, 0x70);
  141. if (ret)
  142. goto err;
  143. ret = regmap_write(dev->regmap, 0x41, 0x09);
  144. if (ret)
  145. goto err;
  146. ret = regmap_write(dev->regmap, 0x08, 0x0b);
  147. if (ret)
  148. goto err;
  149. /* filters */
  150. gdiv28 = DIV_ROUND_CLOSEST(f_ref_khz * 1694U, 1000000U);
  151. ret = regmap_write(dev->regmap, 0x04, gdiv28);
  152. if (ret)
  153. goto err;
  154. ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp);
  155. if (ret)
  156. goto err;
  157. cap_code = u8tmp & 0x3f;
  158. ret = regmap_write(dev->regmap, 0x41, 0x0d);
  159. if (ret)
  160. goto err;
  161. ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp);
  162. if (ret)
  163. goto err;
  164. u8tmp &= 0x3f;
  165. cap_code = (cap_code + u8tmp) / 2;
  166. gdiv28 = gdiv28 * 207 / (cap_code * 2 + 151);
  167. div_max = gdiv28 * 135 / 100;
  168. div_min = gdiv28 * 78 / 100;
  169. div_max = clamp_val(div_max, 0U, 63U);
  170. f_3db_hz = mult_frac(c->symbol_rate, 135, 200);
  171. f_3db_hz += 2000000U + (frequency_offset_khz * 1000U);
  172. f_3db_hz = clamp(f_3db_hz, 7000000U, 40000000U);
  173. #define LPF_COEFF 3200U
  174. lpf_gm = DIV_ROUND_CLOSEST(f_3db_hz * gdiv28, LPF_COEFF * f_ref_khz);
  175. lpf_gm = clamp_val(lpf_gm, 1U, 23U);
  176. lpf_mxdiv = DIV_ROUND_CLOSEST(lpf_gm * LPF_COEFF * f_ref_khz, f_3db_hz);
  177. if (lpf_mxdiv < div_min)
  178. lpf_mxdiv = DIV_ROUND_CLOSEST(++lpf_gm * LPF_COEFF * f_ref_khz, f_3db_hz);
  179. lpf_mxdiv = clamp_val(lpf_mxdiv, 0U, div_max);
  180. ret = regmap_write(dev->regmap, 0x04, lpf_mxdiv);
  181. if (ret)
  182. goto err;
  183. ret = regmap_write(dev->regmap, 0x06, lpf_gm);
  184. if (ret)
  185. goto err;
  186. ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp);
  187. if (ret)
  188. goto err;
  189. cap_code = u8tmp & 0x3f;
  190. ret = regmap_write(dev->regmap, 0x41, 0x09);
  191. if (ret)
  192. goto err;
  193. ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp);
  194. if (ret)
  195. goto err;
  196. u8tmp &= 0x3f;
  197. cap_code = (cap_code + u8tmp) / 2;
  198. u8tmp = cap_code | 0x80;
  199. ret = regmap_write(dev->regmap, 0x25, u8tmp);
  200. if (ret)
  201. goto err;
  202. ret = regmap_write(dev->regmap, 0x27, 0x30);
  203. if (ret)
  204. goto err;
  205. ret = regmap_write(dev->regmap, 0x08, 0x09);
  206. if (ret)
  207. goto err;
  208. ret = m88ts2022_cmd(dev, 0x01, 20, 0x21, 0xff, 0x00, NULL);
  209. if (ret)
  210. goto err;
  211. err:
  212. if (ret)
  213. dev_dbg(&dev->client->dev, "failed=%d\n", ret);
  214. return ret;
  215. }
  216. static int m88ts2022_init(struct dvb_frontend *fe)
  217. {
  218. struct m88ts2022_dev *dev = fe->tuner_priv;
  219. int ret, i;
  220. u8 u8tmp;
  221. static const struct m88ts2022_reg_val reg_vals[] = {
  222. {0x7d, 0x9d},
  223. {0x7c, 0x9a},
  224. {0x7a, 0x76},
  225. {0x3b, 0x01},
  226. {0x63, 0x88},
  227. {0x61, 0x85},
  228. {0x22, 0x30},
  229. {0x30, 0x40},
  230. {0x20, 0x23},
  231. {0x24, 0x02},
  232. {0x12, 0xa0},
  233. };
  234. dev_dbg(&dev->client->dev, "\n");
  235. ret = regmap_write(dev->regmap, 0x00, 0x01);
  236. if (ret)
  237. goto err;
  238. ret = regmap_write(dev->regmap, 0x00, 0x03);
  239. if (ret)
  240. goto err;
  241. switch (dev->cfg.clock_out) {
  242. case M88TS2022_CLOCK_OUT_DISABLED:
  243. u8tmp = 0x60;
  244. break;
  245. case M88TS2022_CLOCK_OUT_ENABLED:
  246. u8tmp = 0x70;
  247. ret = regmap_write(dev->regmap, 0x05, dev->cfg.clock_out_div);
  248. if (ret)
  249. goto err;
  250. break;
  251. case M88TS2022_CLOCK_OUT_ENABLED_XTALOUT:
  252. u8tmp = 0x6c;
  253. break;
  254. default:
  255. goto err;
  256. }
  257. ret = regmap_write(dev->regmap, 0x42, u8tmp);
  258. if (ret)
  259. goto err;
  260. if (dev->cfg.loop_through)
  261. u8tmp = 0xec;
  262. else
  263. u8tmp = 0x6c;
  264. ret = regmap_write(dev->regmap, 0x62, u8tmp);
  265. if (ret)
  266. goto err;
  267. for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
  268. ret = regmap_write(dev->regmap, reg_vals[i].reg, reg_vals[i].val);
  269. if (ret)
  270. goto err;
  271. }
  272. err:
  273. if (ret)
  274. dev_dbg(&dev->client->dev, "failed=%d\n", ret);
  275. return ret;
  276. }
  277. static int m88ts2022_sleep(struct dvb_frontend *fe)
  278. {
  279. struct m88ts2022_dev *dev = fe->tuner_priv;
  280. int ret;
  281. dev_dbg(&dev->client->dev, "\n");
  282. ret = regmap_write(dev->regmap, 0x00, 0x00);
  283. if (ret)
  284. goto err;
  285. err:
  286. if (ret)
  287. dev_dbg(&dev->client->dev, "failed=%d\n", ret);
  288. return ret;
  289. }
  290. static int m88ts2022_get_frequency(struct dvb_frontend *fe, u32 *frequency)
  291. {
  292. struct m88ts2022_dev *dev = fe->tuner_priv;
  293. dev_dbg(&dev->client->dev, "\n");
  294. *frequency = dev->frequency_khz;
  295. return 0;
  296. }
  297. static int m88ts2022_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
  298. {
  299. struct m88ts2022_dev *dev = fe->tuner_priv;
  300. dev_dbg(&dev->client->dev, "\n");
  301. *frequency = 0; /* Zero-IF */
  302. return 0;
  303. }
  304. static int m88ts2022_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
  305. {
  306. struct m88ts2022_dev *dev = fe->tuner_priv;
  307. int ret;
  308. u16 gain, u16tmp;
  309. unsigned int utmp, gain1, gain2, gain3;
  310. ret = regmap_read(dev->regmap, 0x3d, &utmp);
  311. if (ret)
  312. goto err;
  313. gain1 = (utmp >> 0) & 0x1f;
  314. gain1 = clamp(gain1, 0U, 15U);
  315. ret = regmap_read(dev->regmap, 0x21, &utmp);
  316. if (ret)
  317. goto err;
  318. gain2 = (utmp >> 0) & 0x1f;
  319. gain2 = clamp(gain2, 2U, 16U);
  320. ret = regmap_read(dev->regmap, 0x66, &utmp);
  321. if (ret)
  322. goto err;
  323. gain3 = (utmp >> 3) & 0x07;
  324. gain3 = clamp(gain3, 0U, 6U);
  325. gain = gain1 * 265 + gain2 * 338 + gain3 * 285;
  326. /* scale value to 0x0000-0xffff */
  327. u16tmp = (0xffff - gain);
  328. u16tmp = clamp_val(u16tmp, 59000U, 61500U);
  329. *strength = (u16tmp - 59000) * 0xffff / (61500 - 59000);
  330. err:
  331. if (ret)
  332. dev_dbg(&dev->client->dev, "failed=%d\n", ret);
  333. return ret;
  334. }
  335. static const struct dvb_tuner_ops m88ts2022_tuner_ops = {
  336. .info = {
  337. .name = "Montage M88TS2022",
  338. .frequency_min = 950000,
  339. .frequency_max = 2150000,
  340. },
  341. .init = m88ts2022_init,
  342. .sleep = m88ts2022_sleep,
  343. .set_params = m88ts2022_set_params,
  344. .get_frequency = m88ts2022_get_frequency,
  345. .get_if_frequency = m88ts2022_get_if_frequency,
  346. .get_rf_strength = m88ts2022_get_rf_strength,
  347. };
  348. static int m88ts2022_probe(struct i2c_client *client,
  349. const struct i2c_device_id *id)
  350. {
  351. struct m88ts2022_config *cfg = client->dev.platform_data;
  352. struct dvb_frontend *fe = cfg->fe;
  353. struct m88ts2022_dev *dev;
  354. int ret;
  355. u8 u8tmp;
  356. unsigned int utmp;
  357. static const struct regmap_config regmap_config = {
  358. .reg_bits = 8,
  359. .val_bits = 8,
  360. };
  361. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  362. if (!dev) {
  363. ret = -ENOMEM;
  364. dev_err(&client->dev, "kzalloc() failed\n");
  365. goto err;
  366. }
  367. memcpy(&dev->cfg, cfg, sizeof(struct m88ts2022_config));
  368. dev->client = client;
  369. dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
  370. if (IS_ERR(dev->regmap)) {
  371. ret = PTR_ERR(dev->regmap);
  372. goto err;
  373. }
  374. /* check if the tuner is there */
  375. ret = regmap_read(dev->regmap, 0x00, &utmp);
  376. if (ret)
  377. goto err;
  378. if ((utmp & 0x03) == 0x00) {
  379. ret = regmap_write(dev->regmap, 0x00, 0x01);
  380. if (ret)
  381. goto err;
  382. usleep_range(2000, 50000);
  383. }
  384. ret = regmap_write(dev->regmap, 0x00, 0x03);
  385. if (ret)
  386. goto err;
  387. usleep_range(2000, 50000);
  388. ret = regmap_read(dev->regmap, 0x00, &utmp);
  389. if (ret)
  390. goto err;
  391. dev_dbg(&dev->client->dev, "chip_id=%02x\n", utmp);
  392. switch (utmp) {
  393. case 0xc3:
  394. case 0x83:
  395. break;
  396. default:
  397. ret = -ENODEV;
  398. goto err;
  399. }
  400. switch (dev->cfg.clock_out) {
  401. case M88TS2022_CLOCK_OUT_DISABLED:
  402. u8tmp = 0x60;
  403. break;
  404. case M88TS2022_CLOCK_OUT_ENABLED:
  405. u8tmp = 0x70;
  406. ret = regmap_write(dev->regmap, 0x05, dev->cfg.clock_out_div);
  407. if (ret)
  408. goto err;
  409. break;
  410. case M88TS2022_CLOCK_OUT_ENABLED_XTALOUT:
  411. u8tmp = 0x6c;
  412. break;
  413. default:
  414. ret = -EINVAL;
  415. goto err;
  416. }
  417. ret = regmap_write(dev->regmap, 0x42, u8tmp);
  418. if (ret)
  419. goto err;
  420. if (dev->cfg.loop_through)
  421. u8tmp = 0xec;
  422. else
  423. u8tmp = 0x6c;
  424. ret = regmap_write(dev->regmap, 0x62, u8tmp);
  425. if (ret)
  426. goto err;
  427. /* sleep */
  428. ret = regmap_write(dev->regmap, 0x00, 0x00);
  429. if (ret)
  430. goto err;
  431. dev_info(&dev->client->dev, "Montage M88TS2022 successfully identified\n");
  432. fe->tuner_priv = dev;
  433. memcpy(&fe->ops.tuner_ops, &m88ts2022_tuner_ops,
  434. sizeof(struct dvb_tuner_ops));
  435. i2c_set_clientdata(client, dev);
  436. return 0;
  437. err:
  438. dev_dbg(&client->dev, "failed=%d\n", ret);
  439. kfree(dev);
  440. return ret;
  441. }
  442. static int m88ts2022_remove(struct i2c_client *client)
  443. {
  444. struct m88ts2022_dev *dev = i2c_get_clientdata(client);
  445. struct dvb_frontend *fe = dev->cfg.fe;
  446. dev_dbg(&client->dev, "\n");
  447. memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
  448. fe->tuner_priv = NULL;
  449. kfree(dev);
  450. return 0;
  451. }
  452. static const struct i2c_device_id m88ts2022_id[] = {
  453. {"m88ts2022", 0},
  454. {}
  455. };
  456. MODULE_DEVICE_TABLE(i2c, m88ts2022_id);
  457. static struct i2c_driver m88ts2022_driver = {
  458. .driver = {
  459. .owner = THIS_MODULE,
  460. .name = "m88ts2022",
  461. },
  462. .probe = m88ts2022_probe,
  463. .remove = m88ts2022_remove,
  464. .id_table = m88ts2022_id,
  465. };
  466. module_i2c_driver(m88ts2022_driver);
  467. MODULE_DESCRIPTION("Montage M88TS2022 silicon tuner driver");
  468. MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
  469. MODULE_LICENSE("GPL");