tda665x.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. TDA665x tuner driver
  3. Copyright (C) Manu Abraham (abraham.manu@gmail.com)
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include <linux/init.h>
  17. #include <linux/kernel.h>
  18. #include <linux/module.h>
  19. #include "dvb_frontend.h"
  20. #include "tda665x.h"
  21. struct tda665x_state {
  22. struct dvb_frontend *fe;
  23. struct i2c_adapter *i2c;
  24. const struct tda665x_config *config;
  25. u32 frequency;
  26. u32 bandwidth;
  27. };
  28. static int tda665x_read(struct tda665x_state *state, u8 *buf)
  29. {
  30. const struct tda665x_config *config = state->config;
  31. int err = 0;
  32. struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 };
  33. err = i2c_transfer(state->i2c, &msg, 1);
  34. if (err != 1)
  35. goto exit;
  36. return err;
  37. exit:
  38. printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
  39. return err;
  40. }
  41. static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length)
  42. {
  43. const struct tda665x_config *config = state->config;
  44. int err = 0;
  45. struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length };
  46. err = i2c_transfer(state->i2c, &msg, 1);
  47. if (err != 1)
  48. goto exit;
  49. return err;
  50. exit:
  51. printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
  52. return err;
  53. }
  54. static int tda665x_get_state(struct dvb_frontend *fe,
  55. enum tuner_param param,
  56. struct tuner_state *tstate)
  57. {
  58. struct tda665x_state *state = fe->tuner_priv;
  59. int err = 0;
  60. switch (param) {
  61. case DVBFE_TUNER_FREQUENCY:
  62. tstate->frequency = state->frequency;
  63. break;
  64. case DVBFE_TUNER_BANDWIDTH:
  65. break;
  66. default:
  67. printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
  68. err = -EINVAL;
  69. break;
  70. }
  71. return err;
  72. }
  73. static int tda665x_get_status(struct dvb_frontend *fe, u32 *status)
  74. {
  75. struct tda665x_state *state = fe->tuner_priv;
  76. u8 result = 0;
  77. int err = 0;
  78. *status = 0;
  79. err = tda665x_read(state, &result);
  80. if (err < 0)
  81. goto exit;
  82. if ((result >> 6) & 0x01) {
  83. printk(KERN_DEBUG "%s: Tuner Phase Locked\n", __func__);
  84. *status = 1;
  85. }
  86. return err;
  87. exit:
  88. printk(KERN_ERR "%s: I/O Error\n", __func__);
  89. return err;
  90. }
  91. static int tda665x_set_state(struct dvb_frontend *fe,
  92. enum tuner_param param,
  93. struct tuner_state *tstate)
  94. {
  95. struct tda665x_state *state = fe->tuner_priv;
  96. const struct tda665x_config *config = state->config;
  97. u32 frequency, status = 0;
  98. u8 buf[4];
  99. int err = 0;
  100. if (param & DVBFE_TUNER_FREQUENCY) {
  101. frequency = tstate->frequency;
  102. if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) {
  103. printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
  104. return -EINVAL;
  105. }
  106. frequency += config->frequency_offst;
  107. frequency *= config->ref_multiplier;
  108. frequency += config->ref_divider >> 1;
  109. frequency /= config->ref_divider;
  110. buf[0] = (u8) ((frequency & 0x7f00) >> 8);
  111. buf[1] = (u8) (frequency & 0x00ff) >> 0;
  112. buf[2] = 0x80 | 0x40 | 0x02;
  113. buf[3] = 0x00;
  114. /* restore frequency */
  115. frequency = tstate->frequency;
  116. if (frequency < 153000000) {
  117. /* VHF-L */
  118. buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */
  119. if (frequency < 68000000)
  120. buf[3] |= 0x40; /* 83uA */
  121. if (frequency < 1040000000)
  122. buf[3] |= 0x60; /* 122uA */
  123. if (frequency < 1250000000)
  124. buf[3] |= 0x80; /* 163uA */
  125. else
  126. buf[3] |= 0xa0; /* 254uA */
  127. } else if (frequency < 438000000) {
  128. /* VHF-H */
  129. buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */
  130. if (frequency < 230000000)
  131. buf[3] |= 0x40;
  132. if (frequency < 300000000)
  133. buf[3] |= 0x60;
  134. else
  135. buf[3] |= 0x80;
  136. } else {
  137. /* UHF */
  138. buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */
  139. if (frequency < 470000000)
  140. buf[3] |= 0x60;
  141. if (frequency < 526000000)
  142. buf[3] |= 0x80;
  143. else
  144. buf[3] |= 0xa0;
  145. }
  146. /* Set params */
  147. err = tda665x_write(state, buf, 5);
  148. if (err < 0)
  149. goto exit;
  150. /* sleep for some time */
  151. printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__);
  152. msleep(20);
  153. /* check status */
  154. err = tda665x_get_status(fe, &status);
  155. if (err < 0)
  156. goto exit;
  157. if (status == 1) {
  158. printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status);
  159. state->frequency = frequency; /* cache successful state */
  160. } else {
  161. printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status);
  162. }
  163. } else {
  164. printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
  165. return -EINVAL;
  166. }
  167. return 0;
  168. exit:
  169. printk(KERN_ERR "%s: I/O Error\n", __func__);
  170. return err;
  171. }
  172. static int tda665x_release(struct dvb_frontend *fe)
  173. {
  174. struct tda665x_state *state = fe->tuner_priv;
  175. fe->tuner_priv = NULL;
  176. kfree(state);
  177. return 0;
  178. }
  179. static struct dvb_tuner_ops tda665x_ops = {
  180. .set_state = tda665x_set_state,
  181. .get_state = tda665x_get_state,
  182. .get_status = tda665x_get_status,
  183. .release = tda665x_release
  184. };
  185. struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
  186. const struct tda665x_config *config,
  187. struct i2c_adapter *i2c)
  188. {
  189. struct tda665x_state *state = NULL;
  190. struct dvb_tuner_info *info;
  191. state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL);
  192. if (state == NULL)
  193. goto exit;
  194. state->config = config;
  195. state->i2c = i2c;
  196. state->fe = fe;
  197. fe->tuner_priv = state;
  198. fe->ops.tuner_ops = tda665x_ops;
  199. info = &fe->ops.tuner_ops.info;
  200. memcpy(info->name, config->name, sizeof(config->name));
  201. info->frequency_min = config->frequency_min;
  202. info->frequency_max = config->frequency_max;
  203. info->frequency_step = config->frequency_offst;
  204. printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
  205. return fe;
  206. exit:
  207. kfree(state);
  208. return NULL;
  209. }
  210. EXPORT_SYMBOL(tda665x_attach);
  211. MODULE_DESCRIPTION("TDA665x driver");
  212. MODULE_AUTHOR("Manu Abraham");
  213. MODULE_LICENSE("GPL");