tua9001.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Infineon TUA9001 silicon tuner driver
  4. *
  5. * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
  6. */
  7. #include "tua9001_priv.h"
  8. static int tua9001_init(struct dvb_frontend *fe)
  9. {
  10. struct tua9001_dev *dev = fe->tuner_priv;
  11. struct i2c_client *client = dev->client;
  12. int ret, i;
  13. static const struct tua9001_reg_val data[] = {
  14. {0x1e, 0x6512},
  15. {0x25, 0xb888},
  16. {0x39, 0x5460},
  17. {0x3b, 0x00c0},
  18. {0x3a, 0xf000},
  19. {0x08, 0x0000},
  20. {0x32, 0x0030},
  21. {0x41, 0x703a},
  22. {0x40, 0x1c78},
  23. {0x2c, 0x1c00},
  24. {0x36, 0xc013},
  25. {0x37, 0x6f18},
  26. {0x27, 0x0008},
  27. {0x2a, 0x0001},
  28. {0x34, 0x0a40},
  29. };
  30. dev_dbg(&client->dev, "\n");
  31. if (fe->callback) {
  32. ret = fe->callback(client->adapter,
  33. DVB_FRONTEND_COMPONENT_TUNER,
  34. TUA9001_CMD_RESETN, 0);
  35. if (ret)
  36. goto err;
  37. }
  38. for (i = 0; i < ARRAY_SIZE(data); i++) {
  39. ret = regmap_write(dev->regmap, data[i].reg, data[i].val);
  40. if (ret)
  41. goto err;
  42. }
  43. return 0;
  44. err:
  45. dev_dbg(&client->dev, "failed=%d\n", ret);
  46. return ret;
  47. }
  48. static int tua9001_sleep(struct dvb_frontend *fe)
  49. {
  50. struct tua9001_dev *dev = fe->tuner_priv;
  51. struct i2c_client *client = dev->client;
  52. int ret;
  53. dev_dbg(&client->dev, "\n");
  54. if (fe->callback) {
  55. ret = fe->callback(client->adapter,
  56. DVB_FRONTEND_COMPONENT_TUNER,
  57. TUA9001_CMD_RESETN, 1);
  58. if (ret)
  59. goto err;
  60. }
  61. return 0;
  62. err:
  63. dev_dbg(&client->dev, "failed=%d\n", ret);
  64. return ret;
  65. }
  66. static int tua9001_set_params(struct dvb_frontend *fe)
  67. {
  68. struct tua9001_dev *dev = fe->tuner_priv;
  69. struct i2c_client *client = dev->client;
  70. struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  71. int ret, i;
  72. u16 val;
  73. struct tua9001_reg_val data[2];
  74. dev_dbg(&client->dev,
  75. "delivery_system=%u frequency=%u bandwidth_hz=%u\n",
  76. c->delivery_system, c->frequency, c->bandwidth_hz);
  77. switch (c->delivery_system) {
  78. case SYS_DVBT:
  79. switch (c->bandwidth_hz) {
  80. case 8000000:
  81. val = 0x0000;
  82. break;
  83. case 7000000:
  84. val = 0x1000;
  85. break;
  86. case 6000000:
  87. val = 0x2000;
  88. break;
  89. case 5000000:
  90. val = 0x3000;
  91. break;
  92. default:
  93. ret = -EINVAL;
  94. goto err;
  95. }
  96. break;
  97. default:
  98. ret = -EINVAL;
  99. goto err;
  100. }
  101. data[0].reg = 0x04;
  102. data[0].val = val;
  103. data[1].reg = 0x1f;
  104. data[1].val = div_u64((u64) (c->frequency - 150000000) * 48, 1000000);
  105. if (fe->callback) {
  106. ret = fe->callback(client->adapter,
  107. DVB_FRONTEND_COMPONENT_TUNER,
  108. TUA9001_CMD_RXEN, 0);
  109. if (ret)
  110. goto err;
  111. }
  112. for (i = 0; i < ARRAY_SIZE(data); i++) {
  113. ret = regmap_write(dev->regmap, data[i].reg, data[i].val);
  114. if (ret)
  115. goto err;
  116. }
  117. if (fe->callback) {
  118. ret = fe->callback(client->adapter,
  119. DVB_FRONTEND_COMPONENT_TUNER,
  120. TUA9001_CMD_RXEN, 1);
  121. if (ret)
  122. goto err;
  123. }
  124. return 0;
  125. err:
  126. dev_dbg(&client->dev, "failed=%d\n", ret);
  127. return ret;
  128. }
  129. static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
  130. {
  131. struct tua9001_dev *dev = fe->tuner_priv;
  132. struct i2c_client *client = dev->client;
  133. dev_dbg(&client->dev, "\n");
  134. *frequency = 0; /* Zero-IF */
  135. return 0;
  136. }
  137. static const struct dvb_tuner_ops tua9001_tuner_ops = {
  138. .info = {
  139. .name = "Infineon TUA9001",
  140. .frequency_min_hz = 170 * MHz,
  141. .frequency_max_hz = 862 * MHz,
  142. },
  143. .init = tua9001_init,
  144. .sleep = tua9001_sleep,
  145. .set_params = tua9001_set_params,
  146. .get_if_frequency = tua9001_get_if_frequency,
  147. };
  148. static int tua9001_probe(struct i2c_client *client,
  149. const struct i2c_device_id *id)
  150. {
  151. struct tua9001_dev *dev;
  152. struct tua9001_platform_data *pdata = client->dev.platform_data;
  153. struct dvb_frontend *fe = pdata->dvb_frontend;
  154. int ret;
  155. static const struct regmap_config regmap_config = {
  156. .reg_bits = 8,
  157. .val_bits = 16,
  158. };
  159. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  160. if (!dev) {
  161. ret = -ENOMEM;
  162. goto err;
  163. }
  164. dev->fe = pdata->dvb_frontend;
  165. dev->client = client;
  166. dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
  167. if (IS_ERR(dev->regmap)) {
  168. ret = PTR_ERR(dev->regmap);
  169. goto err_kfree;
  170. }
  171. if (fe->callback) {
  172. ret = fe->callback(client->adapter,
  173. DVB_FRONTEND_COMPONENT_TUNER,
  174. TUA9001_CMD_CEN, 1);
  175. if (ret)
  176. goto err_kfree;
  177. ret = fe->callback(client->adapter,
  178. DVB_FRONTEND_COMPONENT_TUNER,
  179. TUA9001_CMD_RXEN, 0);
  180. if (ret)
  181. goto err_kfree;
  182. ret = fe->callback(client->adapter,
  183. DVB_FRONTEND_COMPONENT_TUNER,
  184. TUA9001_CMD_RESETN, 1);
  185. if (ret)
  186. goto err_kfree;
  187. }
  188. fe->tuner_priv = dev;
  189. memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
  190. sizeof(struct dvb_tuner_ops));
  191. i2c_set_clientdata(client, dev);
  192. dev_info(&client->dev, "Infineon TUA9001 successfully attached\n");
  193. return 0;
  194. err_kfree:
  195. kfree(dev);
  196. err:
  197. dev_dbg(&client->dev, "failed=%d\n", ret);
  198. return ret;
  199. }
  200. static int tua9001_remove(struct i2c_client *client)
  201. {
  202. struct tua9001_dev *dev = i2c_get_clientdata(client);
  203. struct dvb_frontend *fe = dev->fe;
  204. int ret;
  205. dev_dbg(&client->dev, "\n");
  206. if (fe->callback) {
  207. ret = fe->callback(client->adapter,
  208. DVB_FRONTEND_COMPONENT_TUNER,
  209. TUA9001_CMD_CEN, 0);
  210. if (ret)
  211. goto err_kfree;
  212. }
  213. kfree(dev);
  214. return 0;
  215. err_kfree:
  216. kfree(dev);
  217. dev_dbg(&client->dev, "failed=%d\n", ret);
  218. return ret;
  219. }
  220. static const struct i2c_device_id tua9001_id_table[] = {
  221. {"tua9001", 0},
  222. {}
  223. };
  224. MODULE_DEVICE_TABLE(i2c, tua9001_id_table);
  225. static struct i2c_driver tua9001_driver = {
  226. .driver = {
  227. .name = "tua9001",
  228. .suppress_bind_attrs = true,
  229. },
  230. .probe = tua9001_probe,
  231. .remove = tua9001_remove,
  232. .id_table = tua9001_id_table,
  233. };
  234. module_i2c_driver(tua9001_driver);
  235. MODULE_DESCRIPTION("Infineon TUA9001 silicon tuner driver");
  236. MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
  237. MODULE_LICENSE("GPL");