htm9aw125_demod.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. * Xuguang htm-9a-w125 Demodulation 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_demod.h"
  20. /*********************IF configure*****************************/
  21. //// first reg (b)
  22. #define HTM_VideoTrapBypassOFF 0x00 // bit b0
  23. #define HTM_VideoTrapBypassON 0x01 // bit b0
  24. #define HTM_AutoMuteFmInactive 0x00 // bit b1
  25. #define HTM_AutoMuteFmActive 0x02 // bit b1
  26. #define HTM_Intercarrier 0x00 // bit b2
  27. #define HTM_QSS 0x04 // bit b2
  28. #define HTM_PositiveAmTV 0x10 // bit b3:4
  29. #define HTM_NegativeFmTV 0x00 // bit b3:4
  30. #define HTM_ForcedMuteAudioON 0x20 // bit b5
  31. #define HTM_ForcedMuteAudioOFF 0x00 // bit b5
  32. #define HTM_OutputPort1Active 0x00 // bit b6
  33. #define HTM_OutputPort1Inactive 0x40 // bit b6
  34. #define HTM_OutputPort2Active 0x00 // bit b7
  35. #define HTM_OutputPort2Inactive 0x80 // bit b7
  36. //// second reg (c)
  37. #define HTM_TopMask 0x1f // bit c0:4
  38. #define HTM_TopDefault 0x10 // bit c0:4
  39. #define HTM_DeemphasisOFF 0x00 // bit c5
  40. #define HTM_DeemphasisON 0x20 // bit c5
  41. #define HTM_Deemphasis75 0x00 // bit c6
  42. #define HTM_Deemphasis50 0x40 // bit c6
  43. #define HTM_AudioGain0 0x00 // bit c7
  44. #define HTM_AudioGain6 0x80 // bit c7
  45. //// third reg (e)
  46. #define HTM_AudioIF_4_5 0x00 // bit e0:1
  47. #define HTM_AudioIF_5_5 0x01 // bit e0:1
  48. #define HTM_AudioIF_6_0 0x02 // bit e0:1
  49. #define HTM_AudioIF_6_5 0x03 // bit e0:1
  50. /* Video IF selection in TV Mode (bit B3=0) */
  51. #define HTM_VideoIF_58_75 0x00 // bit e2:4
  52. #define HTM_VideoIF_45_75 0x04 // bit e2:4
  53. #define HTM_VideoIF_38_90 0x08 // bit e2:4
  54. #define HTM_VideoIF_38_00 0x0C // bit e2:4
  55. #define HTM_VideoIF_33_90 0x10 // bit e2:4
  56. #define HTM_VideoIF_33_40 0x14 // bit e2:4
  57. #define HTM_TunerGainNormal 0x00 // bit e5
  58. #define HTM_TunerGainLow 0x20 // bit e5
  59. #define HTM_Gating_18 0x00 // bit e6
  60. #define HTM_Gating_36 0x40 // bit e6
  61. #define HTM_AgcOutON 0x80 // bit e7
  62. #define HTM_AgcOutOFF 0x00 // bit e7
  63. #define HTM_DEMOD_I2C_NAME "htm9aw125_demod_i2c"
  64. typedef struct htm_if_param_s {
  65. tuner_std_id std;
  66. unsigned char b;
  67. unsigned char c;
  68. unsigned char e;
  69. } htm_if_param_t;
  70. static struct htm_if_param_s htm_if_param[] = {
  71. {
  72. .std = TUNER_STD_PAL_BG,
  73. .b = ( HTM_VideoTrapBypassOFF |
  74. HTM_AutoMuteFmInactive |
  75. HTM_QSS |
  76. HTM_PositiveAmTV |
  77. HTM_ForcedMuteAudioOFF |
  78. HTM_OutputPort1Inactive |
  79. HTM_OutputPort2Inactive),
  80. .c = ( HTM_TopDefault |
  81. HTM_DeemphasisON |
  82. HTM_Deemphasis50 |
  83. HTM_AudioGain6),
  84. .e = ( HTM_Gating_36 |
  85. HTM_AudioIF_5_5 |
  86. HTM_VideoIF_38_90 |
  87. HTM_AgcOutON),
  88. },
  89. {
  90. .std = TUNER_STD_PAL_I,
  91. .b = ( HTM_VideoTrapBypassOFF |
  92. HTM_AutoMuteFmInactive |
  93. HTM_QSS |
  94. HTM_PositiveAmTV |
  95. HTM_ForcedMuteAudioOFF |
  96. HTM_OutputPort1Inactive |
  97. HTM_OutputPort2Inactive),
  98. .c = ( HTM_TopDefault |
  99. HTM_DeemphasisON |
  100. HTM_Deemphasis50 |
  101. HTM_AudioGain6),
  102. .e = ( HTM_AudioIF_6_0 |
  103. HTM_VideoIF_38_90 |
  104. HTM_AgcOutON ),
  105. },
  106. {
  107. .std = TUNER_STD_PAL_DK,
  108. .b = ( HTM_VideoTrapBypassOFF |
  109. HTM_AutoMuteFmInactive |
  110. HTM_QSS |
  111. HTM_PositiveAmTV |
  112. HTM_ForcedMuteAudioOFF |
  113. HTM_OutputPort1Inactive |
  114. HTM_OutputPort2Inactive),
  115. .c = ( HTM_TopDefault |
  116. HTM_DeemphasisON |
  117. HTM_Deemphasis50 |
  118. HTM_AudioGain6),
  119. .e = ( HTM_AudioIF_6_5 |
  120. HTM_VideoIF_38_90 |
  121. HTM_AgcOutON),
  122. },
  123. {
  124. .std = TUNER_STD_NTSC_M,
  125. .b = (0x14),
  126. .c = (0x30),
  127. .e = (0x08),
  128. }
  129. };
  130. static tuner_std_id htm_demod_std = 0;
  131. void tvin_demod_set_std(tuner_std_id ptstd)
  132. {
  133. htm_demod_std = ptstd;
  134. }
  135. static struct i2c_client *tuner_afc_client = NULL;
  136. static int htm_afc_read(char *buf, int len)
  137. {
  138. int i2c_flag = -1;
  139. int i = 0;
  140. unsigned int i2c_try_cnt = I2C_TRY_MAX_CNT;
  141. struct i2c_msg msg[] = {
  142. {
  143. .addr = tuner_afc_client->addr,
  144. .flags = I2C_M_RD,
  145. .len = len,
  146. .buf = buf,
  147. },
  148. };
  149. repeat:
  150. i2c_flag = i2c_transfer(tuner_afc_client->adapter, msg, 1);
  151. if (i2c_flag < 0) {
  152. pr_err("error in read htm_afc, %d byte(s) should be read,. \n", len);
  153. if (i++ < i2c_try_cnt)
  154. goto repeat;
  155. return -EIO;
  156. }
  157. else
  158. {
  159. //pr_info("htm_afc_read is ok. \n");
  160. return 0;
  161. }
  162. }
  163. static int htm_afc_write(char *buf, int len)
  164. {
  165. int i2c_flag = -1;
  166. int i = 0;
  167. unsigned int i2c_try_cnt = I2C_TRY_MAX_CNT;
  168. struct i2c_msg msg[] = {
  169. {
  170. .addr = tuner_afc_client->addr,
  171. .flags = 0, //|I2C_M_TEN,
  172. .len = len,
  173. .buf = buf,
  174. }
  175. };
  176. repeat:
  177. i2c_flag = i2c_transfer(tuner_afc_client->adapter, msg, 1);
  178. if (i2c_flag < 0) {
  179. pr_err("error in writing htm_afc, %d byte(s) should be writen,. \n", len);
  180. if (i++ < i2c_try_cnt)
  181. goto repeat;
  182. return -EIO;
  183. }
  184. else
  185. {
  186. //pr_info("htm_afc_write is ok. \n");
  187. return 0;
  188. }
  189. }
  190. void tvin_demod_get_afc(struct tuner_parm_s *ptp)
  191. {
  192. #if 0
  193. static int afc_bits_2_hz[] = {
  194. -12500, -37500, -62500, -87500,
  195. -112500, -137500, -162500, -187500,
  196. 187500, 162500, 137500, 112500,
  197. 87500, 62500, 37500, 12500
  198. };
  199. #endif
  200. int i2c_flag;
  201. unsigned char status;
  202. i2c_flag = htm_afc_read(&status, 1);
  203. if(i2c_flag == 0)
  204. ptp->if_status = status; //afc_bits_2_hz[(status >> 1) & 0x0F];
  205. }
  206. int tvin_set_demod(unsigned int bce)
  207. {
  208. struct htm_if_param_s *param = NULL;
  209. unsigned char buf[4] = {0, 0, 0, 0};
  210. int i, i2c_flag = -1;
  211. if (bce != 0)
  212. {
  213. buf[1] = (unsigned char)((bce&0xff0000) >> 16);//param->b;
  214. buf[2] = (unsigned char)((bce&0x00ff00) >> 8);//param->c;
  215. buf[3] = (unsigned char)((bce&0x0000ff) >> 0);//param->e;
  216. //pr_info( " %s: b=0x%x, c=0x%x, e=0x%x\n", __func__, buf[1], buf[2], buf[3]);
  217. i2c_flag = htm_afc_write(buf, 4);
  218. return i2c_flag;
  219. }
  220. for (i = 0; i < ARRAY_SIZE(htm_if_param); i++) {
  221. if (htm_if_param[i].std & htm_demod_std) {
  222. param = htm_if_param + i;
  223. break;
  224. }
  225. }
  226. if (NULL == param) {
  227. //tuner_dbg("Unsupported tvnorm entry - audio muted\n");
  228. /*audio muted*/
  229. buf[1] = htm_if_param[0].b | HTM_ForcedMuteAudioON;
  230. buf[2] = htm_if_param[0].c;
  231. buf[3] = htm_if_param[0].e;
  232. i2c_flag = htm_afc_write(buf, 4);
  233. return -1;
  234. }
  235. //tuner_dbg("configure for: %s\n", norm->name);
  236. buf[1] = param->b;
  237. buf[2] = param->c;
  238. buf[3] = param->e;
  239. i2c_flag = htm_afc_write(buf, 4);
  240. return i2c_flag;
  241. }
  242. static int htm_demod_probe(struct i2c_client *client, const struct i2c_device_id *id)
  243. {
  244. if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  245. pr_info("%s: functionality check failed\n", __FUNCTION__);
  246. return -ENODEV;
  247. }
  248. tuner_afc_client = client;
  249. pr_info( " %s: tuner_demod_client->addr = %x\n", __FUNCTION__, tuner_afc_client->addr);
  250. return 0;
  251. }
  252. static int htm_demod_remove(struct i2c_client *client)
  253. {
  254. pr_info("%s driver removed ok.\n", client->name);
  255. return 0;
  256. }
  257. static const struct i2c_device_id htm_demod_id[] = {
  258. {HTM_DEMOD_I2C_NAME, 0},
  259. { }
  260. };
  261. static struct i2c_driver htm_demod_driver = {
  262. .driver = {
  263. .owner = THIS_MODULE,
  264. .name = HTM_DEMOD_I2C_NAME,
  265. },
  266. .probe = htm_demod_probe,
  267. .remove = htm_demod_remove,
  268. .id_table = htm_demod_id,
  269. };
  270. static int __init htm_demod_init(void)
  271. {
  272. int ret = 0;
  273. pr_info( "%s . \n", __FUNCTION__ );
  274. ret = i2c_add_driver(&htm_demod_driver);
  275. if (ret < 0 || tuner_afc_client == NULL) {
  276. pr_err("tuner demod: failed to add i2c driver. \n");
  277. ret = -ENOTSUPP;
  278. }
  279. return ret;
  280. }
  281. static void __exit htm_demod_exit(void)
  282. {
  283. pr_info( "%s . \n", __FUNCTION__ );
  284. i2c_del_driver(&htm_demod_driver);
  285. }
  286. MODULE_AUTHOR("Bobby Yang <bo.yang@amlogic.com>");
  287. MODULE_DESCRIPTION("Xuguang htm-9a-w125 demodulation i2c device driver");
  288. MODULE_LICENSE("GPL");
  289. module_init(htm_demod_init);
  290. module_exit(htm_demod_exit);