fq1216me_tuner.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /*
  2. * PHILIPS FQ1216ME-MK3 Tuner Device Driver
  3. *
  4. * Author: Bobby Yang <bo.yang@amlogic.com>
  5. *
  6. *
  7. * Copyright (C) 2010 Amlogic Inc.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. /* Standard Liniux Headers */
  14. #include <linux/module.h>
  15. #include <linux/i2c.h>
  16. /* Amlogic Headers */
  17. #include <linux/tvin/tvin.h>
  18. /* Local Headers */
  19. #include "tvin_tuner.h"
  20. #define FQ1216_TUNER_I2C_NAME "fq1216me_tuner_i2c"
  21. #define TUNER_DEVICE_NAME "fq1216me"
  22. /* tv tuner system standard selection for Philips FQ1216ME
  23. this value takes the low bits of control byte 2
  24. from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
  25. standard BG DK I L L`
  26. picture carrier 38.90 38.90 38.90 38.90 33.95
  27. colour 34.47 34.47 34.47 34.47 38.38
  28. sound 1 33.40 32.40 32.90 32.40 40.45
  29. sound 2 33.16 - - - -
  30. NICAM 33.05 33.05 32.35 33.05 39.80
  31. */
  32. #define PHILIPS_SET_PAL_I 0xce//0x01
  33. #define PHILIPS_SET_PAL_BGDK 0xce
  34. #define PHILIPS_SET_PAL_L 0x0b
  35. #define TUNER_FL 0x40
  36. #define FREQ_HIGH 442000000
  37. #define FREQ_LOW 160000000
  38. #define TUNER_STEP_SIZE_0 50000
  39. #define TUNER_STEP_SIZE_1 31250
  40. #define TUNER_STEP_SIZE_2 166700
  41. #define TUNER_STEP_SIZE_3 62500
  42. typedef struct fq1216me_s {
  43. tuner_std_id std_id;
  44. struct tuner_freq_s freq;
  45. struct tuner_parm_s parm;
  46. } tuner_fq1216me_t;
  47. static struct fq1216me_s fq1216me = {
  48. TUNER_STD_PAL_BG | TUNER_STD_PAL_DK |
  49. TUNER_STD_PAL_I |TUNER_STD_SECAM_L |
  50. TUNER_STD_SECAM_LC, //tuner_std_id std_id;
  51. {48250000, 0}, //u32 frequency;
  52. {48250000, 863250000, 0, 0, 0}, //struct tuner_parm_s parm;
  53. };
  54. static int fq1216me_std_setup(u8 *cb, u32 *step_size)
  55. {
  56. /* tv norm specific stuff for multi-norm tuners */
  57. *cb = 0x86;
  58. if (fq1216me.std_id & (TUNER_STD_PAL_BG|TUNER_STD_PAL_DK))
  59. {
  60. *cb |= PHILIPS_SET_PAL_BGDK; //(bit0)os == 0, normal mode
  61. //(bit[5:3])T == 0, normal mode
  62. //(bit[6])CP == 0, (charge pump current)fast tuning
  63. *step_size = TUNER_STEP_SIZE_3; //base on the(bit[2:1] of cb) RAS & RSB, set the step size
  64. }
  65. else if (fq1216me.std_id & TUNER_STD_PAL_I)
  66. {
  67. *cb |= PHILIPS_SET_PAL_I; //(bit0)os == 1, switch off the pll amplifier
  68. //(bit[5:3])T == 0, normal mode
  69. //(bit[6])CP == 1, (charge pump current) moderate tuning with slight better residual oscillator
  70. *step_size = TUNER_STEP_SIZE_3; //TUNER_STEP_SIZE_0; //base on the(bit[2:1] of cb) RAS & RSB, set the step size
  71. }
  72. else if (fq1216me.std_id & TUNER_STD_SECAM_L)
  73. {
  74. *cb |= PHILIPS_SET_PAL_L; //(bit0)os == 1, switch off the pll amplifier
  75. //(bit[5:3])T == 0, normal mode
  76. //(bit[6])CP == 1, (charge pump current) moderate tuning with slight better residual oscillator
  77. *step_size = TUNER_STEP_SIZE_1; //base on the(bit[2:1] of cb) RAS & RSB, set the step size
  78. }
  79. return 0;
  80. }
  81. static struct i2c_client *tuner_client = NULL;
  82. static int fq1216me_tuner_read(char *buf, int len)
  83. {
  84. int i2c_flag = -1;
  85. int i = 0;
  86. unsigned int i2c_try_cnt = I2C_TRY_MAX_CNT;
  87. struct i2c_msg msg[] = {
  88. {
  89. .addr = tuner_client->addr,
  90. .flags = I2C_M_RD,
  91. .len = len,
  92. .buf = buf,
  93. },
  94. };
  95. repeat:
  96. i2c_flag = i2c_transfer(tuner_client->adapter, msg, 1);
  97. if (i2c_flag < 0) {
  98. pr_info("error in read fq1216me_tuner, %d byte(s) should be read,. \n", len);
  99. if (i++ < i2c_try_cnt)
  100. goto repeat;
  101. return -EIO;
  102. }
  103. else
  104. {
  105. // pr_info("fq1216me_tuner_read is ok. \n");
  106. return 0;
  107. }
  108. }
  109. static int fq1216me_tuner_write(char *buf, int len)
  110. {
  111. int i2c_flag = -1;
  112. int i = 0;
  113. unsigned int i2c_try_cnt = I2C_TRY_MAX_CNT;
  114. struct i2c_msg msg[] = {
  115. {
  116. .addr = tuner_client->addr,
  117. .flags = 0, //|I2C_M_TEN,
  118. .len = len,
  119. .buf = buf,
  120. }
  121. };
  122. repeat:
  123. i2c_flag = i2c_transfer(tuner_client->adapter, msg, 1);
  124. if (i2c_flag < 0) {
  125. pr_info("error in writing fq1216me_tuner, %d byte(s) should be writen,. \n", len);
  126. if (i++ < i2c_try_cnt)
  127. goto repeat;
  128. return -EIO;
  129. }
  130. else
  131. {
  132. // pr_info("fq1216me_tuner_write is ok. \n");
  133. return 0;
  134. }
  135. }
  136. /* ---------------------------------------------------------------------- */
  137. static enum tuner_signal_status_e tuner_islocked(void)
  138. {
  139. unsigned char status = 0;
  140. fq1216me_tuner_read(&status, 1);
  141. if ((status & TUNER_FL) != 0)
  142. return TUNER_SIGNAL_STATUS_STRONG;
  143. else
  144. return TUNER_SIGNAL_STATUS_WEAK;
  145. }
  146. /* ---------------------------------------------------------------------- */
  147. int tvin_set_tuner(void)
  148. {
  149. u8 buffer[5] = {0};
  150. u8 ab, cb, bb;
  151. u32 div, step_size = 0;
  152. unsigned int f_if;
  153. int i2c_flag;
  154. /* IFPCoff = Video Intermediate Frequency - Vif:
  155. 940 =16*58.75 NTSC/J (Japan)
  156. 732 =16*45.75 M/N STD
  157. 704 =16*44 ATSC (at DVB code)
  158. 632 =16*39.50 I U.K.
  159. 622.4=16*38.90 B/G D/K I, L STD
  160. 592 =16*37.00 D China
  161. 590 =16.36.875 B Australia
  162. 543.2=16*33.95 L' STD
  163. 171.2=16*10.70 FM Radio (at set_radio_freq)
  164. */
  165. if (fq1216me.std_id == TUNER_STD_SECAM_LC)
  166. f_if = 33950000;
  167. else
  168. f_if = 38900000;
  169. if (fq1216me.freq.freq < FREQ_LOW)
  170. bb = 0x01; //low band
  171. else if (fq1216me.freq.freq > FREQ_HIGH)
  172. bb = 0x04; //high band
  173. else
  174. bb = 0x02; //mid band
  175. //tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, "
  176. // "Offset=%d.%02d MHz, div=%0d\n",
  177. // params->frequency / 16, params->frequency % 16 * 100 / 16,
  178. // IFPCoff / 16, IFPCoff % 16 * 100 / 16,
  179. // offset / 16, offset % 16 * 100 / 16, div);
  180. /* tv norm specific stuff for multi-norm tuners */
  181. fq1216me_std_setup(&cb, &step_size);
  182. if (step_size > 0)
  183. div = (fq1216me.freq.freq + f_if)/step_size; //with 62.5Khz step
  184. else
  185. div = (fq1216me.freq.freq + f_if)/TUNER_STEP_SIZE_0; //with 50Khz step
  186. ab = 0x60; //external AGC
  187. buffer[0] = (div >> 8) & 0xff;
  188. buffer[1] = div & 0xff;
  189. buffer[2] = cb;
  190. buffer[3] = bb;
  191. buffer[4] = ab;
  192. i2c_flag = fq1216me_tuner_write(buffer, 5);
  193. return i2c_flag;
  194. }
  195. char *tvin_tuenr_get_name(void)
  196. {
  197. return TUNER_DEVICE_NAME;
  198. }
  199. void tvin_get_tuner( struct tuner_parm_s *ptp)
  200. {
  201. ptp->rangehigh = fq1216me.parm.rangehigh;
  202. ptp->rangelow = fq1216me.parm.rangelow;
  203. ptp->signal = tuner_islocked();
  204. }
  205. void tvin_tuner_get_std(tuner_std_id *ptstd)
  206. {
  207. *ptstd = fq1216me.std_id;
  208. }
  209. void tvin_tuner_set_std(tuner_std_id ptstd)
  210. {
  211. fq1216me.std_id = ptstd;
  212. }
  213. void tvin_tuner_get_freq(struct tuner_freq_s *ptf)
  214. {
  215. ptf->freq = fq1216me.freq.freq;
  216. }
  217. void tvin_tuner_set_freq(struct tuner_freq_s tf)
  218. {
  219. fq1216me.freq.freq = tf.freq;
  220. }
  221. static int fq1216me_tuner_probe(struct i2c_client *client, const struct i2c_device_id *id)
  222. {
  223. if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  224. pr_info("%s: functionality check failed\n", __FUNCTION__);
  225. return -ENODEV;
  226. }
  227. tuner_client = client;
  228. printk( "tuner_client->addr = %x\n", tuner_client->addr);
  229. return 0;
  230. }
  231. static int fq1216me_tuner_remove(struct i2c_client *client)
  232. {
  233. pr_info("%s driver removed ok.\n", client->name);
  234. return 0;
  235. }
  236. static const struct i2c_device_id fq1216me_tuner_id[] = {
  237. { FQ1216_TUNER_I2C_NAME, 0 },
  238. { }
  239. };
  240. MODULE_DEVICE_TABLE(i2c, fq1216me_tuner_id);
  241. static struct i2c_driver fq1216me_tuner_driver = {
  242. .driver = {
  243. .owner = THIS_MODULE,
  244. .name = FQ1216_TUNER_I2C_NAME,
  245. },
  246. .probe = fq1216me_tuner_probe,
  247. .remove = fq1216me_tuner_remove,
  248. .id_table = fq1216me_tuner_id,
  249. };
  250. static int __init fq1216me_tuner_init(void)
  251. {
  252. int ret = 0;
  253. pr_info( "%s . \n", __FUNCTION__ );
  254. ret = i2c_add_driver(&fq1216me_tuner_driver);
  255. if (ret < 0 || tuner_client == NULL) {
  256. pr_err("tuner: failed to add i2c driver. \n");
  257. ret = -ENOTSUPP;
  258. }
  259. return ret;
  260. }
  261. static void __exit f11216me_tuner_exit(void)
  262. {
  263. pr_info( "%s . \n", __FUNCTION__ );
  264. i2c_del_driver(&fq1216me_tuner_driver);
  265. }
  266. MODULE_AUTHOR("Bobby Yang <bo.yang@amlogic.com>");
  267. MODULE_DESCRIPTION("Philips FQ1216ME-MK3 tuner i2c device driver");
  268. MODULE_LICENSE("GPL");
  269. module_init(fq1216me_tuner_init);
  270. module_exit(f11216me_tuner_exit);