phydm_psd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2017 Realtek Corporation.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * The full GNU General Public License is included in this distribution in the
  15. * file called LICENSE.
  16. *
  17. * Contact Information:
  18. * wlanfae <wlanfae@realtek.com>
  19. * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20. * Hsinchu 300, Taiwan.
  21. *
  22. * Larry Finger <Larry.Finger@lwfinger.net>
  23. *
  24. *****************************************************************************/
  25. /******************************************************************************
  26. * include files
  27. *****************************************************************************/
  28. #include "mp_precomp.h"
  29. #include "phydm_precomp.h"
  30. #ifdef CONFIG_PSD_TOOL
  31. u32 phydm_get_psd_data(void *dm_void, u32 psd_tone_idx, u32 igi)
  32. {
  33. struct dm_struct *dm = (struct dm_struct *)dm_void;
  34. struct psd_info *dm_psd_table = &dm->dm_psd_table;
  35. u32 psd_report = 0;
  36. odm_set_bb_reg(dm, dm_psd_table->psd_reg, 0x3ff, psd_tone_idx);
  37. odm_set_bb_reg(dm, dm_psd_table->psd_reg, BIT(22), 1); /*PSD trigger start*/
  38. ODM_delay_us(10);
  39. odm_set_bb_reg(dm, dm_psd_table->psd_reg, BIT(22), 0); /*PSD trigger stop*/
  40. if (dm->support_ic_type & ODM_RTL8821C) {
  41. psd_report = odm_get_bb_reg(dm, dm_psd_table->psd_report_reg,
  42. 0xffffff);
  43. psd_report = psd_report >> 5;
  44. } else {
  45. psd_report = odm_get_bb_reg(dm, dm_psd_table->psd_report_reg,
  46. 0xffff);
  47. }
  48. psd_report = odm_convert_to_db(psd_report) + igi;
  49. return psd_report;
  50. }
  51. u8 psd_result_cali_tone_8821[7] = {21, 28, 33, 93, 98, 105, 127};
  52. u8 psd_result_cali_val_8821[7] = {67, 69, 71, 72, 71, 69, 67};
  53. void phydm_psd(void *dm_void, u32 igi, u16 start_point, u16 stop_point)
  54. {
  55. struct dm_struct *dm = (struct dm_struct *)dm_void;
  56. struct psd_info *dm_psd_table = &dm->dm_psd_table;
  57. u32 i = 0, mod_tone_idx;
  58. u32 t = 0;
  59. u16 fft_max_half_bw;
  60. u32 psd_igi_a_reg;
  61. u32 psd_igi_b_reg;
  62. u16 psd_fc_channel = dm_psd_table->psd_fc_channel;
  63. u8 ag_rf_mode_reg = 0;
  64. u8 rf_reg18_9_8 = 0;
  65. u32 psd_result_tmp = 0;
  66. u8 psd_result = 0;
  67. u8 psd_result_cali_tone[7] = {0};
  68. u8 psd_result_cali_val[7] = {0};
  69. u8 noise_table_idx = 0;
  70. u8 set_result;
  71. if (dm->support_ic_type == ODM_RTL8821) {
  72. odm_move_memory(dm, psd_result_cali_tone,
  73. psd_result_cali_tone_8821, 7);
  74. odm_move_memory(dm, psd_result_cali_val,
  75. psd_result_cali_val_8821, 7);
  76. }
  77. dm_psd_table->psd_in_progress = 1;
  78. /*@[Stop DIG]*/
  79. dm->support_ability &= ~(ODM_BB_DIG);
  80. dm->support_ability &= ~(ODM_BB_FA_CNT);
  81. PHYDM_DBG(dm, ODM_COMP_API, "PSD Start =>\n");
  82. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  83. psd_igi_a_reg = 0xc50;
  84. psd_igi_b_reg = 0xe50;
  85. } else {
  86. psd_igi_a_reg = 0xc50;
  87. psd_igi_b_reg = 0xc58;
  88. }
  89. /*@[back up IGI]*/
  90. dm_psd_table->initial_gain_backup = odm_get_bb_reg(dm, psd_igi_a_reg,
  91. 0xff);
  92. odm_set_bb_reg(dm, psd_igi_a_reg, 0xff, 0x6e); /*@IGI target at 0dBm & make it can't CCA*/
  93. odm_set_bb_reg(dm, psd_igi_b_reg, 0xff, 0x6e); /*@IGI target at 0dBm & make it can't CCA*/
  94. ODM_delay_us(10);
  95. if (phydm_stop_ic_trx(dm, PHYDM_SET) == PHYDM_SET_FAIL) {
  96. PHYDM_DBG(dm, ODM_COMP_API, "STOP_TRX_FAIL\n");
  97. return;
  98. }
  99. /*@[Set IGI]*/
  100. odm_set_bb_reg(dm, psd_igi_a_reg, 0xff, igi);
  101. odm_set_bb_reg(dm, psd_igi_b_reg, 0xff, igi);
  102. /*@[Backup RF Reg]*/
  103. dm_psd_table->rf_0x18_bkp = odm_get_rf_reg(dm, RF_PATH_A, RF_0x18,
  104. RFREGOFFSETMASK);
  105. dm_psd_table->rf_0x18_bkp_b = odm_get_rf_reg(dm, RF_PATH_B, RF_0x18,
  106. RFREGOFFSETMASK);
  107. if (psd_fc_channel > 14) {
  108. rf_reg18_9_8 = 1;
  109. if (psd_fc_channel >= 36 && psd_fc_channel <= 64)
  110. ag_rf_mode_reg = 0x1;
  111. else if (psd_fc_channel >= 100 && psd_fc_channel <= 140)
  112. ag_rf_mode_reg = 0x3;
  113. else if (psd_fc_channel > 140)
  114. ag_rf_mode_reg = 0x5;
  115. }
  116. /* RF path-a */
  117. odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, 0xff, psd_fc_channel); /* Set RF fc*/
  118. odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, 0x300, rf_reg18_9_8);
  119. /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
  120. odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, 0xc00,
  121. dm_psd_table->psd_bw_rf_reg);
  122. /* Set RF ag fc mode*/
  123. odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, 0xf0000, ag_rf_mode_reg);
  124. /* RF path-b */
  125. odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, 0xff, psd_fc_channel); /* Set RF fc*/
  126. odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, 0x300, rf_reg18_9_8);
  127. /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
  128. odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, 0xc00,
  129. dm_psd_table->psd_bw_rf_reg);
  130. odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, 0xf0000, ag_rf_mode_reg); /* Set RF ag fc mode*/
  131. PHYDM_DBG(dm, ODM_COMP_API, "0xc50=((0x%x))\n",
  132. odm_get_bb_reg(dm, R_0xc50, MASKDWORD));
  133. #if 0
  134. /*PHYDM_DBG(dm, ODM_COMP_API, "RF0x0=((0x%x))\n", odm_get_rf_reg(dm, RF_PATH_A, RF_0x0, RFREGOFFSETMASK));*/
  135. #endif
  136. PHYDM_DBG(dm, ODM_COMP_API, "RF0x18=((0x%x))\n",
  137. odm_get_rf_reg(dm, RF_PATH_A, RF_0x18, RFREGOFFSETMASK));
  138. /*@[Stop 3-wires]*/
  139. phydm_stop_3_wire(dm, PHYDM_SET);
  140. ODM_delay_us(10);
  141. if (stop_point > (dm_psd_table->fft_smp_point - 1))
  142. stop_point = (dm_psd_table->fft_smp_point - 1);
  143. if (start_point > (dm_psd_table->fft_smp_point - 1))
  144. start_point = (dm_psd_table->fft_smp_point - 1);
  145. if (start_point > stop_point)
  146. stop_point = start_point;
  147. for (i = start_point; i <= stop_point; i++) {
  148. fft_max_half_bw = (dm_psd_table->fft_smp_point) >> 1;
  149. if (i < fft_max_half_bw)
  150. mod_tone_idx = i + fft_max_half_bw;
  151. else
  152. mod_tone_idx = i - fft_max_half_bw;
  153. psd_result_tmp = 0;
  154. for (t = 0; t < dm_psd_table->sw_avg_time; t++)
  155. psd_result_tmp += phydm_get_psd_data(dm, mod_tone_idx,
  156. igi);
  157. psd_result =
  158. (u8)((psd_result_tmp / dm_psd_table->sw_avg_time)) -
  159. dm_psd_table->psd_pwr_common_offset;
  160. if (dm_psd_table->fft_smp_point == 128 &&
  161. dm_psd_table->noise_k_en) {
  162. if (i > psd_result_cali_tone[noise_table_idx])
  163. noise_table_idx++;
  164. if (noise_table_idx > 6)
  165. noise_table_idx = 6;
  166. if (psd_result >= psd_result_cali_val[noise_table_idx])
  167. psd_result =
  168. psd_result -
  169. psd_result_cali_val[noise_table_idx];
  170. else
  171. psd_result = 0;
  172. dm_psd_table->psd_result[i] = psd_result;
  173. }
  174. PHYDM_DBG(dm, ODM_COMP_API, "[%d] N_cali = %d, PSD = %d\n",
  175. mod_tone_idx, psd_result_cali_val[noise_table_idx],
  176. psd_result);
  177. }
  178. /*@[Start 3-wires]*/
  179. phydm_stop_3_wire(dm, PHYDM_REVERT);
  180. ODM_delay_us(10);
  181. /*@[Revert Reg]*/
  182. set_result = phydm_stop_ic_trx(dm, PHYDM_REVERT);
  183. odm_set_bb_reg(dm, psd_igi_a_reg, 0xff,
  184. dm_psd_table->initial_gain_backup);
  185. odm_set_bb_reg(dm, psd_igi_b_reg, 0xff,
  186. dm_psd_table->initial_gain_backup);
  187. odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, RFREGOFFSETMASK,
  188. dm_psd_table->rf_0x18_bkp);
  189. odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, RFREGOFFSETMASK,
  190. dm_psd_table->rf_0x18_bkp_b);
  191. PHYDM_DBG(dm, ODM_COMP_API, "PSD finished\n\n");
  192. dm->support_ability |= ODM_BB_DIG;
  193. dm->support_ability |= ODM_BB_FA_CNT;
  194. dm_psd_table->psd_in_progress = 0;
  195. }
  196. void phydm_psd_para_setting(void *dm_void, u8 sw_avg_time,
  197. u8 hw_avg_time, u8 i_q_setting,
  198. u16 fft_smp_point, u8 ant_sel,
  199. u8 psd_input, u8 channel, u8 noise_k_en)
  200. {
  201. struct dm_struct *dm = (struct dm_struct *)dm_void;
  202. struct psd_info *dm_psd_table = &dm->dm_psd_table;
  203. u8 fft_smp_point_idx = 0;
  204. dm_psd_table->fft_smp_point = fft_smp_point;
  205. if (sw_avg_time == 0)
  206. sw_avg_time = 1;
  207. dm_psd_table->sw_avg_time = sw_avg_time;
  208. dm_psd_table->psd_fc_channel = channel;
  209. dm_psd_table->noise_k_en = noise_k_en;
  210. if (fft_smp_point == 128)
  211. fft_smp_point_idx = 0;
  212. else if (fft_smp_point == 256)
  213. fft_smp_point_idx = 1;
  214. else if (fft_smp_point == 512)
  215. fft_smp_point_idx = 2;
  216. else if (fft_smp_point == 1024)
  217. fft_smp_point_idx = 3;
  218. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  219. odm_set_bb_reg(dm, R_0x910, BIT(11) | BIT(10), i_q_setting);
  220. odm_set_bb_reg(dm, R_0x910, BIT(13) | BIT(12), hw_avg_time);
  221. odm_set_bb_reg(dm, R_0x910, BIT(15) | BIT(14),
  222. fft_smp_point_idx);
  223. odm_set_bb_reg(dm, R_0x910, BIT(17) | BIT(16), ant_sel);
  224. odm_set_bb_reg(dm, R_0x910, BIT(23), psd_input);
  225. #if 0
  226. } else { /*ODM_IC_11N_SERIES*/
  227. #endif
  228. }
  229. /*@bw = (*dm->band_width); //ODM_BW20M */
  230. /*@channel = *(dm->channel);*/
  231. }
  232. void phydm_psd_init(void *dm_void)
  233. {
  234. struct dm_struct *dm = (struct dm_struct *)dm_void;
  235. struct psd_info *dm_psd_table = &dm->dm_psd_table;
  236. PHYDM_DBG(dm, ODM_COMP_API, "PSD para init\n");
  237. dm_psd_table->psd_in_progress = false;
  238. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  239. dm_psd_table->psd_reg = 0x910;
  240. dm_psd_table->psd_report_reg = 0xF44;
  241. if (ODM_IC_11AC_2_SERIES)
  242. /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
  243. dm_psd_table->psd_bw_rf_reg = 1;
  244. else
  245. /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
  246. dm_psd_table->psd_bw_rf_reg = 2;
  247. } else {
  248. dm_psd_table->psd_reg = 0x808;
  249. dm_psd_table->psd_report_reg = 0x8B4;
  250. /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
  251. dm_psd_table->psd_bw_rf_reg = 2;
  252. }
  253. dm_psd_table->psd_pwr_common_offset = 0;
  254. phydm_psd_para_setting(dm, 1, 2, 3, 128, 0, 0, 7, 0);
  255. #if 0
  256. /*phydm_psd(dm, 0x3c, 0, 127);*/ /* target at -50dBm */
  257. #endif
  258. }
  259. void phydm_psd_debug(void *dm_void, char input[][16], u32 *_used,
  260. char *output, u32 *_out_len)
  261. {
  262. struct dm_struct *dm = (struct dm_struct *)dm_void;
  263. char help[] = "-h";
  264. u32 var1[10] = {0};
  265. u32 used = *_used;
  266. u32 out_len = *_out_len;
  267. u8 i;
  268. if ((strcmp(input[1], help) == 0)) {
  269. PDM_SNPF(out_len, used, output + used, out_len - used,
  270. "{0} {sw_avg} {hw_avg 0:3} {1:I,2:Q,3:IQ} {fft_point: 128*(1:4)} {path_sel 0~3} {0:ADC, 1:RXIQC} {CH} {noise_k}\n");
  271. PDM_SNPF(out_len, used, output + used, out_len - used,
  272. "{1} {IGI(hex)} {start_point} {stop_point}\n");
  273. goto out;
  274. }
  275. PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
  276. if (var1[0] == 0) {
  277. for (i = 1; i < 10; i++) {
  278. if (input[i + 1])
  279. PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
  280. &var1[i]);
  281. }
  282. PDM_SNPF(out_len, used, output + used, out_len - used,
  283. "sw_avg_time=((%d)), hw_avg_time=((%d)), IQ=((%d)), fft=((%d)), path=((%d)), input =((%d)) ch=((%d)), noise_k=((%d))\n",
  284. var1[1], var1[2], var1[3], var1[4], var1[5], var1[6],
  285. (u8)var1[7], (u8)var1[8]);
  286. phydm_psd_para_setting(dm, (u8)var1[1], (u8)var1[2],
  287. (u8)var1[3], (u16)var1[4], (u8)var1[5],
  288. (u8)var1[6], (u8)var1[7], (u8)var1[8]);
  289. } else if (var1[0] == 1) {
  290. PHYDM_SSCANF(input[2], DCMD_HEX, &var1[1]);
  291. PHYDM_SSCANF(input[3], DCMD_DECIMAL, &var1[2]);
  292. PHYDM_SSCANF(input[4], DCMD_DECIMAL, &var1[3]);
  293. PDM_SNPF(out_len, used, output + used, out_len - used,
  294. "IGI=((0x%x)), start_point=((%d)), stop_point=((%d))\n",
  295. var1[1], var1[2], var1[3]);
  296. dm->debug_components |= ODM_COMP_API;
  297. phydm_psd(dm, var1[1], (u16)var1[2], (u16)var1[3]);
  298. dm->debug_components &= (~ODM_COMP_API);
  299. }
  300. out:
  301. *_used = used;
  302. *_out_len = out_len;
  303. }
  304. u8 phydm_get_psd_result_table(void *dm_void, int index)
  305. {
  306. struct dm_struct *dm = (struct dm_struct *)dm_void;
  307. struct psd_info *dm_psd_table = &dm->dm_psd_table;
  308. u8 result = 0;
  309. if (index < 128)
  310. result = dm_psd_table->psd_result[index];
  311. return result;
  312. }
  313. #endif