tda665x.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 <linux/slab.h>
  20. #include "dvb_frontend.h"
  21. #include "tda665x.h"
  22. struct tda665x_state {
  23. struct dvb_frontend *fe;
  24. struct i2c_adapter *i2c;
  25. const struct tda665x_config *config;
  26. u32 frequency;
  27. u32 bandwidth;
  28. };
  29. static int tda665x_read(struct tda665x_state *state, u8 *buf)
  30. {
  31. const struct tda665x_config *config = state->config;
  32. int err = 0;
  33. struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 };
  34. err = i2c_transfer(state->i2c, &msg, 1);
  35. if (err != 1)
  36. goto exit;
  37. return err;
  38. exit:
  39. printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
  40. return err;
  41. }
  42. static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length)
  43. {
  44. const struct tda665x_config *config = state->config;
  45. int err = 0;
  46. struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length };
  47. err = i2c_transfer(state->i2c, &msg, 1);
  48. if (err != 1)
  49. goto exit;
  50. return err;
  51. exit:
  52. printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
  53. return err;
  54. }
  55. static int tda665x_get_state(struct dvb_frontend *fe,
  56. enum tuner_param param,
  57. struct tuner_state *tstate)
  58. {
  59. struct tda665x_state *state = fe->tuner_priv;
  60. int err = 0;
  61. switch (param) {
  62. case DVBFE_TUNER_FREQUENCY:
  63. tstate->frequency = state->frequency;
  64. break;
  65. case DVBFE_TUNER_BANDWIDTH:
  66. break;
  67. default:
  68. printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
  69. err = -EINVAL;
  70. break;
  71. }
  72. return err;
  73. }
  74. static int tda665x_get_status(struct dvb_frontend *fe, u32 *status)
  75. {
  76. struct tda665x_state *state = fe->tuner_priv;
  77. u8 result = 0;
  78. int err = 0;
  79. *status = 0;
  80. err = tda665x_read(state, &result);
  81. if (err < 0)
  82. goto exit;
  83. if ((result >> 6) & 0x01) {
  84. printk(KERN_DEBUG "%s: Tuner Phase Locked\n", __func__);
  85. *status = 1;
  86. }
  87. return err;
  88. exit:
  89. printk(KERN_ERR "%s: I/O Error\n", __func__);
  90. return err;
  91. }
  92. static int tda665x_set_state(struct dvb_frontend *fe,
  93. enum tuner_param param,
  94. struct tuner_state *tstate)
  95. {
  96. struct tda665x_state *state = fe->tuner_priv;
  97. const struct tda665x_config *config = state->config;
  98. u32 frequency, status = 0;
  99. u8 buf[4];
  100. int err = 0;
  101. if (param & DVBFE_TUNER_FREQUENCY) {
  102. frequency = tstate->frequency;
  103. if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) {
  104. printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
  105. return -EINVAL;
  106. }
  107. frequency += config->frequency_offst;
  108. frequency *= config->ref_multiplier;
  109. frequency += config->ref_divider >> 1;
  110. frequency /= config->ref_divider;
  111. buf[0] = (u8) ((frequency & 0x7f00) >> 8);
  112. buf[1] = (u8) (frequency & 0x00ff) >> 0;
  113. buf[2] = 0x80 | 0x40 | 0x02;
  114. buf[3] = 0x00;
  115. /* restore frequency */
  116. frequency = tstate->frequency;
  117. if (frequency < 153000000) {
  118. /* VHF-L */
  119. buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */
  120. if (frequency < 68000000)
  121. buf[3] |= 0x40; /* 83uA */
  122. if (frequency < 1040000000)
  123. buf[3] |= 0x60; /* 122uA */
  124. if (frequency < 1250000000)
  125. buf[3] |= 0x80; /* 163uA */
  126. else
  127. buf[3] |= 0xa0; /* 254uA */
  128. } else if (frequency < 438000000) {
  129. /* VHF-H */
  130. buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */
  131. if (frequency < 230000000)
  132. buf[3] |= 0x40;
  133. if (frequency < 300000000)
  134. buf[3] |= 0x60;
  135. else
  136. buf[3] |= 0x80;
  137. } else {
  138. /* UHF */
  139. buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */
  140. if (frequency < 470000000)
  141. buf[3] |= 0x60;
  142. if (frequency < 526000000)
  143. buf[3] |= 0x80;
  144. else
  145. buf[3] |= 0xa0;
  146. }
  147. /* Set params */
  148. err = tda665x_write(state, buf, 5);
  149. if (err < 0)
  150. goto exit;
  151. /* sleep for some time */
  152. printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__);
  153. msleep(20);
  154. /* check status */
  155. err = tda665x_get_status(fe, &status);
  156. if (err < 0)
  157. goto exit;
  158. if (status == 1) {
  159. printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status);
  160. state->frequency = frequency; /* cache successful state */
  161. } else {
  162. printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status);
  163. }
  164. } else {
  165. printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
  166. return -EINVAL;
  167. }
  168. return 0;
  169. exit:
  170. printk(KERN_ERR "%s: I/O Error\n", __func__);
  171. return err;
  172. }
  173. static int tda665x_release(struct dvb_frontend *fe)
  174. {
  175. struct tda665x_state *state = fe->tuner_priv;
  176. fe->tuner_priv = NULL;
  177. kfree(state);
  178. return 0;
  179. }
  180. static struct dvb_tuner_ops tda665x_ops = {
  181. .set_state = tda665x_set_state,
  182. .get_state = tda665x_get_state,
  183. .get_status = tda665x_get_status,
  184. .release = tda665x_release
  185. };
  186. struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
  187. const struct tda665x_config *config,
  188. struct i2c_adapter *i2c)
  189. {
  190. struct tda665x_state *state = NULL;
  191. struct dvb_tuner_info *info;
  192. state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL);
  193. if (!state)
  194. return NULL;
  195. state->config = config;
  196. state->i2c = i2c;
  197. state->fe = fe;
  198. fe->tuner_priv = state;
  199. fe->ops.tuner_ops = tda665x_ops;
  200. info = &fe->ops.tuner_ops.info;
  201. memcpy(info->name, config->name, sizeof(config->name));
  202. info->frequency_min = config->frequency_min;
  203. info->frequency_max = config->frequency_max;
  204. info->frequency_step = config->frequency_offst;
  205. printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
  206. return fe;
  207. }
  208. EXPORT_SYMBOL(tda665x_attach);
  209. MODULE_DESCRIPTION("TDA665x driver");
  210. MODULE_AUTHOR("Manu Abraham");
  211. MODULE_LICENSE("GPL");