OSDN Git Service

Add rtl8821ce driver version 5.5.2
[android-x86/external-kernel-drivers.git] / rtl8821ce / hal / phydm / phydm_psd.c
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 /******************************************************************************
27  * include files
28  *****************************************************************************/
29 #include "mp_precomp.h"
30 #include "phydm_precomp.h"
31
32 #ifdef CONFIG_PSD_TOOL
33 u32 phydm_get_psd_data(void *dm_void, u32 psd_tone_idx, u32 igi)
34 {
35         struct dm_struct *dm = (struct dm_struct *)dm_void;
36         struct psd_info *dm_psd_table = &dm->dm_psd_table;
37         u32 psd_report = 0;
38
39         odm_set_bb_reg(dm, dm_psd_table->psd_reg, 0x3ff, psd_tone_idx);
40
41         odm_set_bb_reg(dm, dm_psd_table->psd_reg, BIT(22), 1); /*PSD trigger start*/
42         ODM_delay_us(10);
43         odm_set_bb_reg(dm, dm_psd_table->psd_reg, BIT(22), 0); /*PSD trigger stop*/
44
45         if (dm->support_ic_type & ODM_RTL8821C) {
46                 psd_report = odm_get_bb_reg(dm, dm_psd_table->psd_report_reg,
47                                             0xffffff);
48                 psd_report = psd_report >> 5;
49         } else {
50                 psd_report = odm_get_bb_reg(dm, dm_psd_table->psd_report_reg,
51                                             0xffff);
52         }
53         psd_report = odm_convert_to_db(psd_report) + igi;
54
55         return psd_report;
56 }
57
58 u8 psd_result_cali_tone_8821[7] = {21, 28, 33, 93, 98, 105, 127};
59 u8 psd_result_cali_val_8821[7] = {67, 69, 71, 72, 71, 69, 67};
60
61 void phydm_psd(void *dm_void, u32 igi, u16 start_point, u16 stop_point)
62 {
63         struct dm_struct *dm = (struct dm_struct *)dm_void;
64         struct psd_info *dm_psd_table = &dm->dm_psd_table;
65         u32 i = 0, mod_tone_idx;
66         u32 t = 0;
67         u16 fft_max_half_bw;
68         u32 psd_igi_a_reg;
69         u32 psd_igi_b_reg;
70         u16 psd_fc_channel = dm_psd_table->psd_fc_channel;
71         u8 ag_rf_mode_reg = 0;
72         u8 rf_reg18_9_8 = 0;
73         u32 psd_result_tmp = 0;
74         u8 psd_result = 0;
75         u8 psd_result_cali_tone[7] = {0};
76         u8 psd_result_cali_val[7] = {0};
77         u8 noise_table_idx = 0;
78         u8 set_result;
79
80         if (dm->support_ic_type == ODM_RTL8821) {
81                 odm_move_memory(dm, psd_result_cali_tone,
82                                 psd_result_cali_tone_8821, 7);
83                 odm_move_memory(dm, psd_result_cali_val,
84                                 psd_result_cali_val_8821, 7);
85         }
86
87         dm_psd_table->psd_in_progress = 1;
88
89         /*@[Stop DIG]*/
90         dm->support_ability &= ~(ODM_BB_DIG);
91         dm->support_ability &= ~(ODM_BB_FA_CNT);
92
93         PHYDM_DBG(dm, ODM_COMP_API, "PSD Start =>\n");
94
95         if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
96                 psd_igi_a_reg = 0xc50;
97                 psd_igi_b_reg = 0xe50;
98         } else {
99                 psd_igi_a_reg = 0xc50;
100                 psd_igi_b_reg = 0xc58;
101         }
102
103         /*@[back up IGI]*/
104         dm_psd_table->initial_gain_backup = odm_get_bb_reg(dm, psd_igi_a_reg,
105                                                            0xff);
106         odm_set_bb_reg(dm, psd_igi_a_reg, 0xff, 0x6e); /*@IGI target at 0dBm & make it can't CCA*/
107         odm_set_bb_reg(dm, psd_igi_b_reg, 0xff, 0x6e); /*@IGI target at 0dBm & make it can't CCA*/
108         ODM_delay_us(10);
109
110         if (phydm_stop_ic_trx(dm, PHYDM_SET) == PHYDM_SET_FAIL) {
111                 PHYDM_DBG(dm, ODM_COMP_API, "STOP_TRX_FAIL\n");
112                 return;
113         }
114
115         /*@[Set IGI]*/
116         odm_set_bb_reg(dm, psd_igi_a_reg, 0xff, igi);
117         odm_set_bb_reg(dm, psd_igi_b_reg, 0xff, igi);
118
119         /*@[Backup RF Reg]*/
120         dm_psd_table->rf_0x18_bkp = odm_get_rf_reg(dm, RF_PATH_A, RF_0x18,
121                                                    RFREGOFFSETMASK);
122         dm_psd_table->rf_0x18_bkp_b = odm_get_rf_reg(dm, RF_PATH_B, RF_0x18,
123                                                      RFREGOFFSETMASK);
124
125         if (psd_fc_channel > 14) {
126                 rf_reg18_9_8 = 1;
127                 if (psd_fc_channel >= 36 && psd_fc_channel <= 64)
128                         ag_rf_mode_reg = 0x1;
129                 else if (psd_fc_channel >= 100 && psd_fc_channel <= 140)
130                         ag_rf_mode_reg = 0x3;
131                 else if (psd_fc_channel > 140)
132                         ag_rf_mode_reg = 0x5;
133         }
134
135         /* RF path-a */
136         odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, 0xff, psd_fc_channel); /* Set RF fc*/
137         odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, 0x300, rf_reg18_9_8);
138         /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
139         odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, 0xc00,
140                        dm_psd_table->psd_bw_rf_reg);
141         /* Set RF ag fc mode*/
142         odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, 0xf0000, ag_rf_mode_reg);
143
144         /* RF path-b */
145         odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, 0xff, psd_fc_channel); /* Set RF fc*/
146         odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, 0x300, rf_reg18_9_8);
147         /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
148         odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, 0xc00,
149                        dm_psd_table->psd_bw_rf_reg);
150         odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, 0xf0000, ag_rf_mode_reg); /* Set RF ag fc mode*/
151
152         PHYDM_DBG(dm, ODM_COMP_API, "0xc50=((0x%x))\n",
153                   odm_get_bb_reg(dm, R_0xc50, MASKDWORD));
154 #if 0
155         /*PHYDM_DBG(dm, ODM_COMP_API, "RF0x0=((0x%x))\n", odm_get_rf_reg(dm, RF_PATH_A, RF_0x0, RFREGOFFSETMASK));*/
156 #endif
157         PHYDM_DBG(dm, ODM_COMP_API, "RF0x18=((0x%x))\n",
158                   odm_get_rf_reg(dm, RF_PATH_A, RF_0x18, RFREGOFFSETMASK));
159
160         /*@[Stop 3-wires]*/
161         phydm_stop_3_wire(dm, PHYDM_SET);
162
163         ODM_delay_us(10);
164
165         if (stop_point > (dm_psd_table->fft_smp_point - 1))
166                 stop_point = (dm_psd_table->fft_smp_point - 1);
167
168         if (start_point > (dm_psd_table->fft_smp_point - 1))
169                 start_point = (dm_psd_table->fft_smp_point - 1);
170
171         if (start_point > stop_point)
172                 stop_point = start_point;
173
174         for (i = start_point; i <= stop_point; i++) {
175                 fft_max_half_bw = (dm_psd_table->fft_smp_point) >> 1;
176
177                 if (i < fft_max_half_bw)
178                         mod_tone_idx = i + fft_max_half_bw;
179                 else
180                         mod_tone_idx = i - fft_max_half_bw;
181
182                 psd_result_tmp = 0;
183                 for (t = 0; t < dm_psd_table->sw_avg_time; t++)
184                         psd_result_tmp += phydm_get_psd_data(dm, mod_tone_idx,
185                                                              igi);
186                 psd_result =
187                         (u8)((psd_result_tmp / dm_psd_table->sw_avg_time)) -
188                         dm_psd_table->psd_pwr_common_offset;
189
190                 if (dm_psd_table->fft_smp_point == 128 &&
191                     dm_psd_table->noise_k_en) {
192                         if (i > psd_result_cali_tone[noise_table_idx])
193                                 noise_table_idx++;
194
195                         if (noise_table_idx > 6)
196                                 noise_table_idx = 6;
197
198                         if (psd_result >= psd_result_cali_val[noise_table_idx])
199                                 psd_result =
200                                         psd_result -
201                                         psd_result_cali_val[noise_table_idx];
202                         else
203                                 psd_result = 0;
204
205                         dm_psd_table->psd_result[i] = psd_result;
206                 }
207
208                 PHYDM_DBG(dm, ODM_COMP_API, "[%d] N_cali = %d, PSD = %d\n",
209                           mod_tone_idx, psd_result_cali_val[noise_table_idx],
210                           psd_result);
211         }
212
213         /*@[Start 3-wires]*/
214         phydm_stop_3_wire(dm, PHYDM_REVERT);
215
216         ODM_delay_us(10);
217
218         /*@[Revert Reg]*/
219         set_result = phydm_stop_ic_trx(dm, PHYDM_REVERT);
220
221         odm_set_bb_reg(dm, psd_igi_a_reg, 0xff,
222                        dm_psd_table->initial_gain_backup);
223         odm_set_bb_reg(dm, psd_igi_b_reg, 0xff,
224                        dm_psd_table->initial_gain_backup);
225
226         odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, RFREGOFFSETMASK,
227                        dm_psd_table->rf_0x18_bkp);
228         odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, RFREGOFFSETMASK,
229                        dm_psd_table->rf_0x18_bkp_b);
230
231         PHYDM_DBG(dm, ODM_COMP_API, "PSD finished\n\n");
232
233         dm->support_ability |= ODM_BB_DIG;
234         dm->support_ability |= ODM_BB_FA_CNT;
235         dm_psd_table->psd_in_progress = 0;
236 }
237
238 void phydm_psd_para_setting(void *dm_void, u8 sw_avg_time,
239                             u8 hw_avg_time, u8 i_q_setting,
240                             u16 fft_smp_point, u8 ant_sel,
241                             u8 psd_input, u8 channel, u8 noise_k_en)
242 {
243         struct dm_struct *dm = (struct dm_struct *)dm_void;
244         struct psd_info *dm_psd_table = &dm->dm_psd_table;
245         u8 fft_smp_point_idx = 0;
246
247         dm_psd_table->fft_smp_point = fft_smp_point;
248
249         if (sw_avg_time == 0)
250                 sw_avg_time = 1;
251
252         dm_psd_table->sw_avg_time = sw_avg_time;
253         dm_psd_table->psd_fc_channel = channel;
254         dm_psd_table->noise_k_en = noise_k_en;
255
256         if (fft_smp_point == 128)
257                 fft_smp_point_idx = 0;
258         else if (fft_smp_point == 256)
259                 fft_smp_point_idx = 1;
260         else if (fft_smp_point == 512)
261                 fft_smp_point_idx = 2;
262         else if (fft_smp_point == 1024)
263                 fft_smp_point_idx = 3;
264
265         if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
266                 odm_set_bb_reg(dm, R_0x910, BIT(11) | BIT(10), i_q_setting);
267                 odm_set_bb_reg(dm, R_0x910, BIT(13) | BIT(12), hw_avg_time);
268                 odm_set_bb_reg(dm, R_0x910, BIT(15) | BIT(14),
269                                fft_smp_point_idx);
270                 odm_set_bb_reg(dm, R_0x910, BIT(17) | BIT(16), ant_sel);
271                 odm_set_bb_reg(dm, R_0x910, BIT(23), psd_input);
272 #if 0
273         } else {        /*ODM_IC_11N_SERIES*/
274 #endif
275         }
276
277         /*@bw = (*dm->band_width); //ODM_BW20M */
278         /*@channel = *(dm->channel);*/
279 }
280
281 void phydm_psd_init(void *dm_void)
282 {
283         struct dm_struct *dm = (struct dm_struct *)dm_void;
284         struct psd_info *dm_psd_table = &dm->dm_psd_table;
285
286         PHYDM_DBG(dm, ODM_COMP_API, "PSD para init\n");
287
288         dm_psd_table->psd_in_progress = false;
289
290         if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
291                 dm_psd_table->psd_reg = 0x910;
292                 dm_psd_table->psd_report_reg = 0xF44;
293
294                 if (ODM_IC_11AC_2_SERIES)
295                         /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
296                         dm_psd_table->psd_bw_rf_reg = 1;
297                 else
298                         /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
299                         dm_psd_table->psd_bw_rf_reg = 2;
300
301         } else {
302                 dm_psd_table->psd_reg = 0x808;
303                 dm_psd_table->psd_report_reg = 0x8B4;
304                 /*@2b'11: 20MHz, 2b'10: 40MHz, 2b'01: 80MHz */
305                 dm_psd_table->psd_bw_rf_reg = 2;
306         }
307
308         dm_psd_table->psd_pwr_common_offset = 0;
309
310         phydm_psd_para_setting(dm, 1, 2, 3, 128, 0, 0, 7, 0);
311 #if 0
312         /*phydm_psd(dm, 0x3c, 0, 127);*/ /* target at -50dBm */
313 #endif
314 }
315
316 void phydm_psd_debug(void *dm_void, char input[][16], u32 *_used,
317                      char *output, u32 *_out_len)
318 {
319         struct dm_struct *dm = (struct dm_struct *)dm_void;
320         char help[] = "-h";
321         u32 var1[10] = {0};
322         u32 used = *_used;
323         u32 out_len = *_out_len;
324         u8 i;
325
326         if ((strcmp(input[1], help) == 0)) {
327                 PDM_SNPF(out_len, used, output + used, out_len - used,
328                          "{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");
329                 PDM_SNPF(out_len, used, output + used, out_len - used,
330                          "{1} {IGI(hex)} {start_point} {stop_point}\n");
331                 goto out;
332         }
333
334         PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
335
336         if (var1[0] == 0) {
337                 for (i = 1; i < 10; i++) {
338                         if (input[i + 1])
339                                 PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
340                                              &var1[i]);
341                 }
342
343                 PDM_SNPF(out_len, used, output + used, out_len - used,
344                          "sw_avg_time=((%d)), hw_avg_time=((%d)), IQ=((%d)), fft=((%d)), path=((%d)), input =((%d)) ch=((%d)), noise_k=((%d))\n",
345                          var1[1], var1[2], var1[3], var1[4], var1[5], var1[6],
346                          (u8)var1[7], (u8)var1[8]);
347                 phydm_psd_para_setting(dm, (u8)var1[1], (u8)var1[2],
348                                        (u8)var1[3], (u16)var1[4], (u8)var1[5],
349                                        (u8)var1[6], (u8)var1[7], (u8)var1[8]);
350
351         } else if (var1[0] == 1) {
352                 PHYDM_SSCANF(input[2], DCMD_HEX, &var1[1]);
353                 PHYDM_SSCANF(input[3], DCMD_DECIMAL, &var1[2]);
354                 PHYDM_SSCANF(input[4], DCMD_DECIMAL, &var1[3]);
355                 PDM_SNPF(out_len, used, output + used, out_len - used,
356                          "IGI=((0x%x)), start_point=((%d)), stop_point=((%d))\n",
357                          var1[1], var1[2], var1[3]);
358                 dm->debug_components |= ODM_COMP_API;
359                 phydm_psd(dm, var1[1], (u16)var1[2], (u16)var1[3]);
360                 dm->debug_components &= (~ODM_COMP_API);
361         }
362
363 out:
364         *_used = used;
365         *_out_len = out_len;
366 }
367
368 u8 phydm_get_psd_result_table(void *dm_void, int index)
369 {
370         struct dm_struct *dm = (struct dm_struct *)dm_void;
371         struct psd_info *dm_psd_table = &dm->dm_psd_table;
372         u8 result = 0;
373
374         if (index < 128)
375                 result = dm_psd_table->psd_result[index];
376
377         return result;
378 }
379
380 #endif