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 "mp_precomp.h"
27 #include "phydm_precomp.h"
28
29 #define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, _delta_thermal)\
30 do { \
31 u32 __offset = (u32)_offset; \
32 u32 __size = (u32)_size; \
33 for (__offset = 0; __offset < __size; __offset++) { \
34 if (_delta_thermal < \
35 thermal_threshold[_direction][__offset]) { \
36 if (__offset != 0) \
37 __offset--; \
38 break; \
39 } \
40 } \
41 if (__offset >= __size) \
42 __offset = __size - 1; \
43 } while (0)
44
configure_txpower_track(void * dm_void,struct txpwrtrack_cfg * config)45 void configure_txpower_track(void *dm_void, struct txpwrtrack_cfg *config)
46 {
47 struct dm_struct *dm = (struct dm_struct *)dm_void;
48
49 #if RTL8192E_SUPPORT
50 if (dm->support_ic_type == ODM_RTL8192E)
51 configure_txpower_track_8192e(config);
52 #endif
53 #if RTL8821A_SUPPORT
54 if (dm->support_ic_type == ODM_RTL8821)
55 configure_txpower_track_8821a(config);
56 #endif
57 #if RTL8812A_SUPPORT
58 if (dm->support_ic_type == ODM_RTL8812)
59 configure_txpower_track_8812a(config);
60 #endif
61 #if RTL8188E_SUPPORT
62 if (dm->support_ic_type == ODM_RTL8188E)
63 configure_txpower_track_8188e(config);
64 #endif
65
66 #if RTL8723B_SUPPORT
67 if (dm->support_ic_type == ODM_RTL8723B)
68 configure_txpower_track_8723b(config);
69 #endif
70
71 #if RTL8814A_SUPPORT
72 if (dm->support_ic_type == ODM_RTL8814A)
73 configure_txpower_track_8814a(config);
74 #endif
75
76 #if RTL8703B_SUPPORT
77 if (dm->support_ic_type == ODM_RTL8703B)
78 configure_txpower_track_8703b(config);
79 #endif
80
81 #if RTL8188F_SUPPORT
82 if (dm->support_ic_type == ODM_RTL8188F)
83 configure_txpower_track_8188f(config);
84 #endif
85 #if RTL8723D_SUPPORT
86 if (dm->support_ic_type == ODM_RTL8723D)
87 configure_txpower_track_8723d(config);
88 #endif
89 /*@ JJ ADD 20161014 */
90 #if RTL8710B_SUPPORT
91 if (dm->support_ic_type == ODM_RTL8710B)
92 configure_txpower_track_8710b(config);
93 #endif
94 #if RTL8822B_SUPPORT
95 if (dm->support_ic_type == ODM_RTL8822B)
96 configure_txpower_track_8822b(config);
97 #endif
98 #if RTL8821C_SUPPORT
99 if (dm->support_ic_type == ODM_RTL8821C)
100 configure_txpower_track_8821c(config);
101 #endif
102
103 #if RTL8192F_SUPPORT
104 if (dm->support_ic_type == ODM_RTL8192F)
105 configure_txpower_track_8192f(config);
106 #endif
107
108 #if RTL8822C_SUPPORT
109 if (dm->support_ic_type == ODM_RTL8822C)
110 configure_txpower_track_8822c(config);
111 #endif
112
113 #if RTL8814B_SUPPORT
114 if (dm->support_ic_type == ODM_RTL8814B)
115 configure_txpower_track_8814b(config);
116 #endif
117
118
119 }
120
121 /*@ **********************************************************************
122 * <20121113, Kordan> This function should be called when tx_agc changed.
123 * Otherwise the previous compensation is gone, because we record the
124 * delta of temperature between two TxPowerTracking watch dogs.
125 *
126 * NOTE: If Tx BB swing or Tx scaling is varified during run-time, still
127 * need to call this function.
128 * **********************************************************************
129 */
odm_clear_txpowertracking_state(void * dm_void)130 void odm_clear_txpowertracking_state(void *dm_void)
131 {
132 struct dm_struct *dm = (struct dm_struct *)dm_void;
133 struct _hal_rf_ *rf = &dm->rf_table;
134 u8 p = 0;
135 struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
136
137 cali_info->bb_swing_idx_cck_base = cali_info->default_cck_index;
138 cali_info->bb_swing_idx_cck = cali_info->default_cck_index;
139 dm->rf_calibrate_info.CCK_index = 0;
140
141 for (p = RF_PATH_A; p < MAX_RF_PATH; ++p) {
142 cali_info->bb_swing_idx_ofdm_base[p]
143 = cali_info->default_ofdm_index;
144 cali_info->bb_swing_idx_ofdm[p] = cali_info->default_ofdm_index;
145 cali_info->OFDM_index[p] = cali_info->default_ofdm_index;
146
147 cali_info->power_index_offset[p] = 0;
148 cali_info->delta_power_index[p] = 0;
149 cali_info->delta_power_index_last[p] = 0;
150
151 /* Initial Mix mode power tracking*/
152 cali_info->absolute_ofdm_swing_idx[p] = 0;
153 cali_info->remnant_ofdm_swing_idx[p] = 0;
154 cali_info->kfree_offset[p] = 0;
155 }
156 /* Initial Mix mode power tracking*/
157 cali_info->modify_tx_agc_flag_path_a = false;
158 cali_info->modify_tx_agc_flag_path_b = false;
159 cali_info->modify_tx_agc_flag_path_c = false;
160 cali_info->modify_tx_agc_flag_path_d = false;
161 cali_info->remnant_cck_swing_idx = 0;
162 cali_info->thermal_value = rf->eeprom_thermal;
163 cali_info->modify_tx_agc_value_cck = 0;
164 cali_info->modify_tx_agc_value_ofdm = 0;
165 }
166
odm_get_tracking_table(void * dm_void,u8 thermal_value,u8 delta)167 void odm_get_tracking_table(void *dm_void, u8 thermal_value, u8 delta)
168 {
169 struct dm_struct *dm = (struct dm_struct *)dm_void;
170 struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
171 struct _hal_rf_ *rf = &dm->rf_table;
172 struct txpwrtrack_cfg c = {0};
173
174 u8 p;
175 /* 4 1. TWO tables decide the final index of OFDM/CCK swing table. */
176 u8 *pwrtrk_tab_up_a = NULL;
177 u8 *pwrtrk_tab_down_a = NULL;
178 u8 *pwrtrk_tab_up_b = NULL;
179 u8 *pwrtrk_tab_down_b = NULL;
180 /*for 8814 add by Yu Chen*/
181 u8 *pwrtrk_tab_up_c = NULL;
182 u8 *pwrtrk_tab_down_c = NULL;
183 u8 *pwrtrk_tab_up_d = NULL;
184 u8 *pwrtrk_tab_down_d = NULL;
185 /*for Xtal Offset by James.Tung*/
186 s8 *xtal_tab_up = NULL;
187 s8 *xtal_tab_down = NULL;
188
189 configure_txpower_track(dm, &c);
190
191 (*c.get_delta_swing_table)(dm,
192 (u8 **)&pwrtrk_tab_up_a,
193 (u8 **)&pwrtrk_tab_down_a,
194 (u8 **)&pwrtrk_tab_up_b,
195 (u8 **)&pwrtrk_tab_down_b);
196
197 if (dm->support_ic_type & ODM_RTL8814A) /*for 8814 path C & D*/
198 (*c.get_delta_swing_table8814only)(dm,
199 (u8 **)&pwrtrk_tab_up_c,
200 (u8 **)&pwrtrk_tab_down_c,
201 (u8 **)&pwrtrk_tab_up_d,
202 (u8 **)&pwrtrk_tab_down_d);
203 /*for Xtal Offset*/
204 if (dm->support_ic_type &
205 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F))
206 (*c.get_delta_swing_xtal_table)(dm,
207 (s8 **)&xtal_tab_up,
208 (s8 **)&xtal_tab_down);
209
210 if (thermal_value > rf->eeprom_thermal) {
211 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
212 /*recording power index offset*/
213 cali_info->delta_power_index_last[p] =
214 cali_info->delta_power_index[p];
215 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
216 "******Temp is higher******\n");
217 switch (p) {
218 case RF_PATH_B:
219 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
220 "pwrtrk_tab_up_b[%d] = %d\n", delta,
221 pwrtrk_tab_up_b[delta]);
222
223 cali_info->delta_power_index[p] =
224 pwrtrk_tab_up_b[delta];
225 cali_info->absolute_ofdm_swing_idx[p] =
226 pwrtrk_tab_up_b[delta];
227 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
228 "absolute_ofdm_swing_idx[PATH_B] = %d\n",
229 cali_info->absolute_ofdm_swing_idx[p]);
230 break;
231
232 case RF_PATH_C:
233 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
234 "pwrtrk_tab_up_c[%d] = %d\n", delta,
235 pwrtrk_tab_up_c[delta]);
236
237 cali_info->delta_power_index[p] =
238 pwrtrk_tab_up_c[delta];
239 cali_info->absolute_ofdm_swing_idx[p] =
240 pwrtrk_tab_up_c[delta];
241 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
242 "absolute_ofdm_swing_idx[PATH_C] = %d\n",
243 cali_info->absolute_ofdm_swing_idx[p]);
244 break;
245
246 case RF_PATH_D:
247 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
248 "pwrtrk_tab_up_d[%d] = %d\n", delta,
249 pwrtrk_tab_up_d[delta]);
250
251 cali_info->delta_power_index[p] =
252 pwrtrk_tab_up_d[delta];
253 cali_info->absolute_ofdm_swing_idx[p] =
254 pwrtrk_tab_up_d[delta];
255 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
256 "absolute_ofdm_swing_idx[PATH_D] = %d\n",
257 cali_info->absolute_ofdm_swing_idx[p]);
258 break;
259
260 default:
261 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
262 "pwrtrk_tab_up_a[%d] = %d\n", delta,
263 pwrtrk_tab_up_a[delta]);
264
265 cali_info->delta_power_index[p] =
266 pwrtrk_tab_up_a[delta];
267 cali_info->absolute_ofdm_swing_idx[p] =
268 pwrtrk_tab_up_a[delta];
269 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
270 "absolute_ofdm_swing_idx[PATH_A] = %d\n",
271 cali_info->absolute_ofdm_swing_idx[p]);
272 break;
273 }
274 }
275 /* @JJ ADD 20161014 */
276 /*Save xtal_offset from Xtal table*/
277 if (dm->support_ic_type &
278 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B |
279 ODM_RTL8192F)) {
280 /*recording last Xtal offset*/
281 cali_info->xtal_offset_last = cali_info->xtal_offset;
282 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
283 "[Xtal] xtal_tab_up[%d] = %d\n",
284 delta, xtal_tab_up[delta]);
285 cali_info->xtal_offset = xtal_tab_up[delta];
286 if (cali_info->xtal_offset_last != xtal_tab_up[delta])
287 cali_info->xtal_offset_eanble = 1;
288 }
289 } else {
290 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
291 /*recording power index offset*/
292 cali_info->delta_power_index_last[p] =
293 cali_info->delta_power_index[p];
294 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
295 "******Temp is lower******\n");
296 switch (p) {
297 case RF_PATH_B:
298 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
299 "pwrtrk_tab_down_b[%d] = %d\n", delta,
300 pwrtrk_tab_down_b[delta]);
301 cali_info->delta_power_index[p] =
302 -1 * pwrtrk_tab_down_b[delta];
303 cali_info->absolute_ofdm_swing_idx[p] =
304 -1 * pwrtrk_tab_down_b[delta];
305 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
306 "absolute_ofdm_swing_idx[PATH_B] = %d\n",
307 cali_info->absolute_ofdm_swing_idx[p]);
308 break;
309
310 case RF_PATH_C:
311 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
312 "pwrtrk_tab_down_c[%d] = %d\n", delta,
313 pwrtrk_tab_down_c[delta]);
314 cali_info->delta_power_index[p] =
315 -1 * pwrtrk_tab_down_c[delta];
316 cali_info->absolute_ofdm_swing_idx[p] =
317 -1 * pwrtrk_tab_down_c[delta];
318 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
319 "absolute_ofdm_swing_idx[PATH_C] = %d\n",
320 cali_info->absolute_ofdm_swing_idx[p]);
321 break;
322
323 case RF_PATH_D:
324 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
325 "pwrtrk_tab_down_d[%d] = %d\n", delta,
326 pwrtrk_tab_down_d[delta]);
327 cali_info->delta_power_index[p] =
328 -1 * pwrtrk_tab_down_d[delta];
329 cali_info->absolute_ofdm_swing_idx[p] =
330 -1 * pwrtrk_tab_down_d[delta];
331 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
332 "absolute_ofdm_swing_idx[PATH_D] = %d\n",
333 cali_info->absolute_ofdm_swing_idx[p]);
334 break;
335
336 default:
337 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
338 "pwrtrk_tab_down_a[%d] = %d\n", delta,
339 pwrtrk_tab_down_a[delta]);
340 cali_info->delta_power_index[p] =
341 -1 * pwrtrk_tab_down_a[delta];
342 cali_info->absolute_ofdm_swing_idx[p] =
343 -1 * pwrtrk_tab_down_a[delta];
344 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
345 "absolute_ofdm_swing_idx[PATH_A] = %d\n",
346 cali_info->absolute_ofdm_swing_idx[p]);
347 break;
348 }
349 }
350 /* @JJ ADD 20161014 */
351 if (dm->support_ic_type &
352 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B |
353 ODM_RTL8192F)) {
354 /*recording last Xtal offset*/
355 cali_info->xtal_offset_last = cali_info->xtal_offset;
356 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
357 "[Xtal] xtal_tab_down[%d] = %d\n", delta,
358 xtal_tab_down[delta]);
359 /*Save xtal_offset from Xtal table*/
360 cali_info->xtal_offset = xtal_tab_down[delta];
361 if (cali_info->xtal_offset_last != xtal_tab_down[delta])
362 cali_info->xtal_offset_eanble = 1;
363 }
364 }
365 }
366
odm_pwrtrk_method(void * dm_void)367 void odm_pwrtrk_method(void *dm_void)
368 {
369 struct dm_struct *dm = (struct dm_struct *)dm_void;
370 u8 p, idxforchnl = 0;
371
372 struct txpwrtrack_cfg c = {0};
373
374 configure_txpower_track(dm, &c);
375
376 if (dm->support_ic_type &
377 (ODM_RTL8188E | ODM_RTL8192E | ODM_RTL8821 | ODM_RTL8812 |
378 ODM_RTL8723B | ODM_RTL8814A | ODM_RTL8703B | ODM_RTL8188F |
379 ODM_RTL8822B | ODM_RTL8821C | ODM_RTL8710B |
380 ODM_RTL8192F)) {
381 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
382 "***Enter PwrTrk MIX_MODE***\n");
383 for (p = RF_PATH_A; p < c.rf_path_count; p++)
384 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
385 } else if (dm->support_ic_type & ODM_RTL8723D) {
386 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
387 "***Enter PwrTrk MIX_MODE***\n");
388 p = (u8)odm_get_bb_reg(dm, R_0x948, 0x00000080);
389 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
390 /*if open ant_div 0x948=140,do 2 path pwr_track*/
391 if (odm_get_bb_reg(dm, R_0x948, 0x00000040))
392 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, 1, 0);
393 } else {
394 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
395 "***Enter PwrTrk BBSWING_MODE***\n");
396 for (p = RF_PATH_A; p < c.rf_path_count; p++)
397 (*c.odm_tx_pwr_track_set_pwr)
398 (dm, BBSWING, p, idxforchnl);
399 }
400 }
401
402 #if (DM_ODM_SUPPORT_TYPE & ODM_AP)
odm_txpowertracking_callback_thermal_meter(struct dm_struct * dm)403 void odm_txpowertracking_callback_thermal_meter(struct dm_struct *dm)
404 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
405 void odm_txpowertracking_callback_thermal_meter(void *dm_void)
406 #else
407 void odm_txpowertracking_callback_thermal_meter(void *adapter)
408 #endif
409 {
410 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
411 HAL_DATA_TYPE *hal_data = GET_HAL_DATA(((PADAPTER)adapter));
412 struct dm_struct *dm = &hal_data->DM_OutSrc;
413 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
414 struct dm_struct *dm = (struct dm_struct *)dm_void;
415 #endif
416
417 struct _hal_rf_ *rf = &dm->rf_table;
418 struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
419 struct dm_iqk_info *iqk_info = &dm->IQK_info;
420
421 u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
422 u8 thermal_value_avg_count = 0;
423 u32 thermal_value_avg = 0, regc80, regcd0, regcd4, regab4;
424
425 /* OFDM BB Swing should be less than +3.0dB, required by Arthur */
426 #if 0
427 u8 OFDM_min_index = 0;
428 #endif
429 #if 0
430 /* get_right_chnl_place_for_iqk(hal_data->current_channel) */
431 #endif
432 u8 power_tracking_type = rf->pwt_type;
433 s8 thermal_value_temp = 0;
434
435 struct txpwrtrack_cfg c = {0};
436
437 /* @4 2. Initialization ( 7 steps in total ) */
438
439 configure_txpower_track(dm, &c);
440
441 cali_info->txpowertracking_callback_cnt++;
442 cali_info->is_txpowertracking_init = true;
443
444 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
445 "\n\n\n===>%s bbsw_idx_cck_base=%d\n",
446 __func__, cali_info->bb_swing_idx_cck_base);
447
448 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
449 "bbsw_idx_ofdm_base[A]=%d default_ofdm_idx=%d\n",
450 cali_info->bb_swing_idx_ofdm_base[RF_PATH_A],
451 cali_info->default_ofdm_index);
452
453 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
454 "cali_info->txpowertrack_control=%d, rf->eeprom_thermal %d\n",
455 cali_info->txpowertrack_control, rf->eeprom_thermal);
456
457 /* 0x42: RF Reg[15:10] 88E */
458 thermal_value =
459 (u8)odm_get_rf_reg(dm, RF_PATH_A, c.thermal_reg_addr, 0xfc00);
460
461 thermal_value_temp = thermal_value + phydm_get_thermal_offset(dm);
462
463 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
464 "thermal_value_temp(%d) = ther_value(%d) + pwr_trim_ther(%d)\n",
465 thermal_value_temp, thermal_value,
466 phydm_get_thermal_offset(dm));
467
468 if (thermal_value_temp > 63)
469 thermal_value = 63;
470 else if (thermal_value_temp < 0)
471 thermal_value = 0;
472 else
473 thermal_value = thermal_value_temp;
474
475 /*@add log by zhao he, check c80/c94/c14/ca0 value*/
476 if (dm->support_ic_type &
477 (ODM_RTL8723D | ODM_RTL8710B)) {
478 regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
479 regcd0 = odm_get_bb_reg(dm, R_0xcd0, MASKDWORD);
480 regcd4 = odm_get_bb_reg(dm, R_0xcd4, MASKDWORD);
481 regab4 = odm_get_bb_reg(dm, R_0xab4, 0x000007FF);
482 RF_DBG(dm, DBG_RF_IQK,
483 "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n",
484 regc80, regcd0, regcd4, regab4);
485 }
486
487 if (!cali_info->txpowertrack_control)
488 return;
489
490 if (rf->eeprom_thermal == 0xff) {
491 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
492 "no pg, hal_data->eeprom_thermal_meter = 0x%x\n",
493 rf->eeprom_thermal);
494 return;
495 }
496
497 /*@4 3. Initialize ThermalValues of rf_calibrate_info*/
498
499 if (cali_info->is_reloadtxpowerindex)
500 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
501 "reload ofdm index for band switch\n");
502
503 /*@4 4. Calculate average thermal meter*/
504
505 cali_info->thermal_value_avg[cali_info->thermal_value_avg_index]
506 = thermal_value;
507
508 cali_info->thermal_value_avg_index++;
509 /*Average times = c.average_thermal_num*/
510 if (cali_info->thermal_value_avg_index == c.average_thermal_num)
511 cali_info->thermal_value_avg_index = 0;
512
513 for (i = 0; i < c.average_thermal_num; i++) {
514 if (cali_info->thermal_value_avg[i]) {
515 thermal_value_avg += cali_info->thermal_value_avg[i];
516 thermal_value_avg_count++;
517 }
518 }
519
520 /* Calculate Average thermal_value after average enough times */
521 if (thermal_value_avg_count) {
522 thermal_value =
523 (u8)(thermal_value_avg / thermal_value_avg_count);
524 cali_info->thermal_value_delta
525 = thermal_value - rf->eeprom_thermal;
526 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
527 "AVG Thermal Meter = 0x%X, EFUSE Thermal base = 0x%X\n",
528 thermal_value, rf->eeprom_thermal);
529 }
530
531 /* @4 5. Calculate delta, delta_lck, delta_iqk. */
532 /* "delta" here is used to determine thermal value changes or not. */
533 if (thermal_value > cali_info->thermal_value)
534 delta = thermal_value - cali_info->thermal_value;
535 else
536 delta = cali_info->thermal_value - thermal_value;
537
538 if (thermal_value > cali_info->thermal_value_lck)
539 delta_lck = thermal_value - cali_info->thermal_value_lck;
540 else
541 delta_lck = cali_info->thermal_value_lck - thermal_value;
542
543 if (thermal_value > cali_info->thermal_value_iqk)
544 delta_iqk = thermal_value - cali_info->thermal_value_iqk;
545 else
546 delta_iqk = cali_info->thermal_value_iqk - thermal_value;
547
548 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
549 "(delta, delta_lck, delta_iqk) = (%d, %d, %d)\n", delta,
550 delta_lck, delta_iqk);
551
552 /*@4 6. If necessary, do LCK.*/
553 /* Wait sacn to do LCK by RF Jenyu*/
554 if (!(*dm->is_scan_in_process) && !iqk_info->rfk_forbidden) {
555 /* Delta temperature is equal to or larger than 20 centigrade.*/
556 if (delta_lck >= c.threshold_iqk) {
557 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
558 "delta_lck(%d) >= threshold_iqk(%d)\n",
559 delta_lck, c.threshold_iqk);
560 cali_info->thermal_value_lck = thermal_value;
561
562 /*Use RTLCK, close power tracking driver LCK*/
563 /*8821 don't do LCK*/
564 if (!(dm->support_ic_type &
565 (ODM_RTL8821 | ODM_RTL8814A | ODM_RTL8822B)) &&
566 c.phy_lc_calibrate) {
567 (*c.phy_lc_calibrate)(dm);
568 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
569 "do pwrtrk lck\n");
570 }
571 }
572 }
573
574 /*@3 7. If necessary, move the index of swing table to adjust Tx power.*/
575 /* "delta" here is used to record the absolute value of difference. */
576 if (delta > 0 && cali_info->txpowertrack_control) {
577 if (thermal_value > rf->eeprom_thermal)
578 delta = thermal_value - rf->eeprom_thermal;
579 else
580 delta = rf->eeprom_thermal - thermal_value;
581
582 if (delta >= TXPWR_TRACK_TABLE_SIZE)
583 delta = TXPWR_TRACK_TABLE_SIZE - 1;
584
585 odm_get_tracking_table(dm, thermal_value, delta);
586
587 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
588 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
589 "\n[path-%d] Calculate pwr_idx_offset\n", p);
590
591 /*If Thermal value changes but table value is the same*/
592 if (cali_info->delta_power_index[p] ==
593 cali_info->delta_power_index_last[p])
594 cali_info->power_index_offset[p] = 0;
595 else
596 cali_info->power_index_offset[p] =
597 cali_info->delta_power_index[p] -
598 cali_info->delta_power_index_last[p];
599
600 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
601 "path-%d pwridx_diff%d=pwr_idx%d - last_idx%d\n",
602 p, cali_info->power_index_offset[p],
603 cali_info->delta_power_index[p],
604 cali_info->delta_power_index_last[p]);
605 #if 0
606
607 cali_info->OFDM_index[p] = cali_info->bb_swing_idx_ofdm_base[p] + cali_info->power_index_offset[p];
608 cali_info->CCK_index = cali_info->bb_swing_idx_cck_base + cali_info->power_index_offset[p];
609
610 cali_info->bb_swing_idx_cck = cali_info->CCK_index;
611 cali_info->bb_swing_idx_ofdm[p] = cali_info->OFDM_index[p];
612
613 /*************Print BB Swing base and index Offset*************/
614
615 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
616 "The 'CCK' final index(%d) = BaseIndex(%d) + power_index_offset(%d)\n",
617 cali_info->bb_swing_idx_cck,
618 cali_info->bb_swing_idx_cck_base,
619 cali_info->power_index_offset[p]);
620 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
621 "The 'OFDM' final index(%d) = BaseIndex[%d](%d) + power_index_offset(%d)\n",
622 cali_info->bb_swing_idx_ofdm[p], p,
623 cali_info->bb_swing_idx_ofdm_base[p],
624 cali_info->power_index_offset[p]);
625
626 /*4 7.1 Handle boundary conditions of index.*/
627
628 if (cali_info->OFDM_index[p] > c.swing_table_size_ofdm - 1)
629 cali_info->OFDM_index[p] = c.swing_table_size_ofdm - 1;
630 else if (cali_info->OFDM_index[p] <= OFDM_min_index)
631 cali_info->OFDM_index[p] = OFDM_min_index;
632 #endif
633 }
634 #if 0
635 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
636 "\n\n========================================================================================================\n");
637
638 if (cali_info->CCK_index > c.swing_table_size_cck - 1)
639 cali_info->CCK_index = c.swing_table_size_cck - 1;
640 else if (cali_info->CCK_index <= 0)
641 cali_info->CCK_index = 0;
642 #endif
643 } else {
644 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
645 "Thermal is unchanged thermal=%d last_thermal=%d\n",
646 thermal_value,
647 cali_info->thermal_value);
648 for (p = RF_PATH_A; p < c.rf_path_count; p++)
649 cali_info->power_index_offset[p] = 0;
650 }
651
652 #if 0
653 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
654 "TxPowerTracking: [CCK] Swing Current index: %d, Swing base index: %d\n",
655 cali_info->CCK_index,
656 cali_info->bb_swing_idx_cck_base); /*Print Swing base & current*/
657
658 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
659 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
660 "TxPowerTracking: [OFDM] Swing Current index: %d, Swing base index[%d]: %d\n",
661 cali_info->OFDM_index[p], p,
662 cali_info->bb_swing_idx_ofdm_base[p]);
663 }
664 #endif
665
666 if ((dm->support_ic_type & ODM_RTL8814A)) {
667 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "power_tracking_type=%d\n",
668 power_tracking_type);
669
670 if (power_tracking_type == 0) {
671 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
672 "***Enter PwrTrk MIX_MODE***\n");
673 for (p = RF_PATH_A; p < c.rf_path_count; p++)
674 (*c.odm_tx_pwr_track_set_pwr)
675 (dm, MIX_MODE, p, 0);
676 } else if (power_tracking_type == 1) {
677 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
678 "***Enter PwrTrk MIX(2G) TSSI(5G) MODE***\n");
679 for (p = RF_PATH_A; p < c.rf_path_count; p++)
680 (*c.odm_tx_pwr_track_set_pwr)
681 (dm, MIX_2G_TSSI_5G_MODE, p, 0);
682 } else if (power_tracking_type == 2) {
683 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
684 "***Enter PwrTrk MIX(5G) TSSI(2G)MODE***\n");
685 for (p = RF_PATH_A; p < c.rf_path_count; p++)
686 (*c.odm_tx_pwr_track_set_pwr)
687 (dm, MIX_5G_TSSI_2G_MODE, p, 0);
688 } else if (power_tracking_type == 3) {
689 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
690 "***Enter PwrTrk TSSI MODE***\n");
691 for (p = RF_PATH_A; p < c.rf_path_count; p++)
692 (*c.odm_tx_pwr_track_set_pwr)
693 (dm, TSSI_MODE, p, 0);
694 }
695 } else if ((cali_info->power_index_offset[RF_PATH_A] != 0 ||
696 cali_info->power_index_offset[RF_PATH_B] != 0 ||
697 cali_info->power_index_offset[RF_PATH_C] != 0 ||
698 cali_info->power_index_offset[RF_PATH_D] != 0)) {
699 #if 0
700 /* 4 7.2 Configure the Swing Table to adjust Tx Power. */
701 /*Always true after Tx Power is adjusted by power tracking.*/
702
703 cali_info->is_tx_power_changed = true;
704 /* 2012/04/23 MH According to Luke's suggestion, we can not write BB digital
705 * to increase TX power. Otherwise, EVM will be bad.
706 *
707 * 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E.
708 */
709 if (thermal_value > cali_info->thermal_value) {
710 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
711 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
712 "Temperature Increasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
713 p, cali_info->power_index_offset[p],
714 delta, thermal_value, rf->eeprom_thermal,
715 cali_info->thermal_value);
716 }
717 } else if (thermal_value < cali_info->thermal_value) { /*Low temperature*/
718 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
719 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
720 "Temperature Decreasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
721 p, cali_info->power_index_offset[p],
722 delta, thermal_value, rf->eeprom_thermal,
723 cali_info->thermal_value);
724 }
725 }
726 #endif
727
728 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
729 if (thermal_value > rf->eeprom_thermal) {
730 #else
731 if (thermal_value > dm->priv->pmib->dot11RFEntry.ther) {
732 #endif
733 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
734 "Temperature(%d) higher than PG value(%d)\n",
735 thermal_value, rf->eeprom_thermal);
736
737 odm_pwrtrk_method(dm);
738 } else {
739 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
740 "Temperature(%d) lower than PG value(%d)\n",
741 thermal_value, rf->eeprom_thermal);
742
743 odm_pwrtrk_method(dm);
744 }
745
746 #if 0
747 /*Record last time Power Tracking result as base.*/
748 cali_info->bb_swing_idx_cck_base = cali_info->bb_swing_idx_cck;
749 for (p = RF_PATH_A; p < c.rf_path_count; p++)
750 cali_info->bb_swing_idx_ofdm_base[p] = cali_info->bb_swing_idx_ofdm[p];
751 #endif
752 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
753 "cali_info->thermal_value = %d thermal_value= %d\n",
754 cali_info->thermal_value, thermal_value);
755 }
756 /*Record last Power Tracking Thermal value*/
757 cali_info->thermal_value = thermal_value;
758
759 if (dm->support_ic_type &
760 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8192F | ODM_RTL8710B)) {
761 if (cali_info->xtal_offset_eanble != 0 &&
762 cali_info->txpowertrack_control &&
763 rf->eeprom_thermal != 0xff) {
764 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
765 "**********Enter Xtal Tracking**********\n");
766
767 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
768 if (thermal_value > rf->eeprom_thermal) {
769 #else
770 if (thermal_value > dm->priv->pmib->dot11RFEntry.ther) {
771 #endif
772 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
773 "Temperature(%d) higher than PG (%d)\n",
774 thermal_value, rf->eeprom_thermal);
775 (*c.odm_txxtaltrack_set_xtal)(dm);
776 } else {
777 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
778 "Temperature(%d) lower than PG (%d)\n",
779 thermal_value, rf->eeprom_thermal);
780 (*c.odm_txxtaltrack_set_xtal)(dm);
781 }
782 }
783 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
784 "**********End Xtal Tracking**********\n");
785 }
786
787 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
788
789 /* Wait sacn to do IQK by RF Jenyu*/
790 if (!(*dm->is_scan_in_process) && !iqk_info->rfk_forbidden &&
791 !cali_info->is_iqk_in_progress && dm->is_linked) {
792 if (!(dm->support_ic_type & ODM_RTL8723B)) {
793 /*Delta temperature is equal or larger than 20 Celsius*/
794 /*When threshold is 8*/
795 if (delta_iqk >= c.threshold_iqk) {
796 cali_info->thermal_value_iqk = thermal_value;
797 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
798 "delta_iqk(%d) >= threshold_iqk(%d)\n",
799 delta_iqk, c.threshold_iqk);
800 (*c.do_iqk)(dm, delta_iqk, thermal_value, 8);
801 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
802 "do pwrtrk iqk\n");
803 }
804 }
805 }
806
807 #if 0
808 if (cali_info->dpk_thermal[RF_PATH_A] != 0) {
809 if (diff_DPK[RF_PATH_A] >= c.threshold_dpk) {
810 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
811 odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), (diff_DPK[RF_PATH_A] / c.threshold_dpk));
812 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
813 } else if ((diff_DPK[RF_PATH_A] <= -1 * c.threshold_dpk)) {
814 s32 value = 0x20 + (diff_DPK[RF_PATH_A] / c.threshold_dpk);
815
816 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
817 odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value);
818 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
819 } else {
820 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
821 odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0);
822 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
823 }
824 }
825 if (cali_info->dpk_thermal[RF_PATH_B] != 0) {
826 if (diff_DPK[RF_PATH_B] >= c.threshold_dpk) {
827 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
828 odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), (diff_DPK[RF_PATH_B] / c.threshold_dpk));
829 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
830 } else if ((diff_DPK[RF_PATH_B] <= -1 * c.threshold_dpk)) {
831 s32 value = 0x20 + (diff_DPK[RF_PATH_B] / c.threshold_dpk);
832
833 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
834 odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value);
835 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
836 } else {
837 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
838 odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0);
839 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
840 }
841 }
842 #endif
843
844 #endif
845
846 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "<===%s\n", __func__);
847
848 cali_info->tx_powercount = 0;
849 }
850
851 #if (RTL8822C_SUPPORT == 1 || RTL8814B_SUPPORT == 1)
852 void
853 odm_txpowertracking_new_callback_thermal_meter(void *dm_void)
854 {
855 struct dm_struct *dm = (struct dm_struct *)dm_void;
856 struct dm_rf_calibration_struct *cali_info = &(dm->rf_calibrate_info);
857 struct dm_iqk_info *iqk_info = &dm->IQK_info;
858 struct _hal_rf_ *rf = &dm->rf_table;
859 struct _halrf_tssi_data *tssi = &rf->halrf_tssi_data;
860 u8 thermal_value[MAX_RF_PATH] = {0}, delta[MAX_RF_PATH] = {0};
861 u8 delta_swing_table_idx_tup[DELTA_SWINGIDX_SIZE] = {0};
862 u8 delta_swing_table_idx_tdown[DELTA_SWINGIDX_SIZE] = {0};
863 u8 delta_LCK = 0, delta_IQK = 0, i = 0, j = 0, p;
864 u8 thermal_value_avg_count[MAX_RF_PATH] = {0};
865 u32 thermal_value_avg[MAX_RF_PATH] = {0};
866 s8 thermal_value_temp[MAX_RF_PATH] = {0};
867 u8 tracking_method = MIX_MODE;
868
869 struct txpwrtrack_cfg c;
870
871 u8 *delta_swing_table_idx_tup_a = NULL;
872 u8 *delta_swing_table_idx_tdown_a = NULL;
873 u8 *delta_swing_table_idx_tup_b = NULL;
874 u8 *delta_swing_table_idx_tdown_b = NULL;
875 u8 *delta_swing_table_idx_tup_c = NULL;
876 u8 *delta_swing_table_idx_tdown_c = NULL;
877 u8 *delta_swing_table_idx_tup_d = NULL;
878 u8 *delta_swing_table_idx_tdown_d = NULL;
879
880 configure_txpower_track(dm, &c);
881
882 (*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_a, (u8 **)&delta_swing_table_idx_tdown_a,
883 (u8 **)&delta_swing_table_idx_tup_b, (u8 **)&delta_swing_table_idx_tdown_b);
884
885 if (dm->support_ic_type == ODM_RTL8814B) {
886 (*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_c, (u8 **)&delta_swing_table_idx_tdown_c,
887 (u8 **)&delta_swing_table_idx_tup_d, (u8 **)&delta_swing_table_idx_tdown_d);
888 }
889
890 cali_info->txpowertracking_callback_cnt++;
891 cali_info->is_txpowertracking_init = true;
892
893 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
894 "===>odm_txpowertracking_callback_thermal_meter\n cali_info->bb_swing_idx_cck_base: %d, cali_info->bb_swing_idx_ofdm_base[A]: %d, cali_info->default_ofdm_index: %d\n",
895 cali_info->bb_swing_idx_cck_base, cali_info->bb_swing_idx_ofdm_base[RF_PATH_A], cali_info->default_ofdm_index);
896
897 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
898 "cali_info->txpowertrack_control=%d, tssi->thermal[RF_PATH_A]=%d tssi->thermal[RF_PATH_B]=%d\n",
899 cali_info->txpowertrack_control, tssi->thermal[RF_PATH_A], tssi->thermal[RF_PATH_B]);
900
901 if (dm->support_ic_type == ODM_RTL8822C) {
902 for (i = 0; i < c.rf_path_count; i++)
903 thermal_value[i] = (u8)odm_get_rf_reg(dm, i, c.thermal_reg_addr, 0x7e); /* 0x42: RF Reg[6:1] Thermal Trim*/
904 } else {
905 for (i = 0; i < c.rf_path_count; i++) {
906 thermal_value[i] = (u8)odm_get_rf_reg(dm, i, c.thermal_reg_addr, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
907
908 if (dm->support_ic_type == ODM_RTL8814B) {
909 thermal_value_temp[i] = (s8)thermal_value[i] + phydm_get_multi_thermal_offset(dm, i);
910 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
911 "thermal_value_temp[%d](%d) = thermal_value[%d](%d) + multi_thermal_trim(%d)\n", i, thermal_value_temp[i], i, thermal_value[i], phydm_get_multi_thermal_offset(dm, i));
912 } else {
913 thermal_value_temp[i] = (s8)thermal_value[i] + phydm_get_thermal_offset(dm);
914 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
915 "thermal_value_temp[%d](%d) = thermal_value[%d](%d) + thermal_trim(%d)\n", i, thermal_value_temp[i], i, thermal_value[i], phydm_get_thermal_offset(dm));
916 }
917
918 if (thermal_value_temp[i] > 63)
919 thermal_value[i] = 63;
920 else if (thermal_value_temp[i] < 0)
921 thermal_value[i] = 0;
922 else
923 thermal_value[i] = thermal_value_temp[i];
924 }
925 }
926
927 if ((tssi->thermal[RF_PATH_A] == 0xff || tssi->thermal[RF_PATH_B] == 0xff) &&
928 cali_info->txpowertrack_control != 3) {
929 for (i = 0; i < c.rf_path_count; i++)
930 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no pg, tssi->thermal[%d] = 0x%x\n",
931 i, tssi->thermal[i]);
932 return;
933 }
934
935 for (j = 0; j < c.rf_path_count; j++) {
936 cali_info->thermal_value_avg_path[j][cali_info->thermal_value_avg_index_path[j]] = thermal_value[j];
937 cali_info->thermal_value_avg_index_path[j]++;
938 if (cali_info->thermal_value_avg_index_path[j] == c.average_thermal_num) /*Average times = c.average_thermal_num*/
939 cali_info->thermal_value_avg_index_path[j] = 0;
940
941
942 for (i = 0; i < c.average_thermal_num; i++) {
943 if (cali_info->thermal_value_avg_path[j][i]) {
944 thermal_value_avg[j] += cali_info->thermal_value_avg_path[j][i];
945 thermal_value_avg_count[j]++;
946 }
947 }
948
949 if (thermal_value_avg_count[j]) { /* Calculate Average thermal_value after average enough times */
950 thermal_value[j] = (u8)(thermal_value_avg[j] / thermal_value_avg_count[j]);
951 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
952 "AVG Thermal Meter = 0x%X, tssi->thermal[%d] = 0x%x\n",
953 thermal_value[j], j, tssi->thermal[j]);
954 }
955 /* 4 5. Calculate delta, delta_LCK, delta_IQK. */
956
957 /* "delta" here is used to determine whether thermal value changes or not. */
958 delta[j] = (thermal_value[j] > cali_info->thermal_value_path[j]) ? (thermal_value[j] - cali_info->thermal_value_path[j]) : (cali_info->thermal_value_path[j] - thermal_value[j]);
959 delta_LCK = (thermal_value[0] > cali_info->thermal_value_lck) ? (thermal_value[0] - cali_info->thermal_value_lck) : (cali_info->thermal_value_lck - thermal_value[0]);
960 delta_IQK = (thermal_value[0] > cali_info->thermal_value_iqk) ? (thermal_value[0] - cali_info->thermal_value_iqk) : (cali_info->thermal_value_iqk - thermal_value[0]);
961 }
962
963 /*4 6. If necessary, do LCK.*/
964
965 for (i = 0; i < c.rf_path_count; i++)
966 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "(delta[%d], delta_LCK, delta_IQK) = (%d, %d, %d)\n", i, delta[i], delta_LCK, delta_IQK);
967
968 /* Wait sacn to do LCK by RF Jenyu*/
969 if( (*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden)) {
970 /* Delta temperature is equal to or larger than 20 centigrade.*/
971 if (delta_LCK >= c.threshold_iqk) {
972 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_LCK(%d) >= threshold_iqk(%d)\n", delta_LCK, c.threshold_iqk);
973 cali_info->thermal_value_lck = thermal_value[RF_PATH_A];
974
975 /*Use RTLCK, so close power tracking driver LCK*/
976 if ((!(dm->support_ic_type & ODM_RTL8814A)) && (!(dm->support_ic_type & ODM_RTL8822B))) {
977 if (c.phy_lc_calibrate)
978 (*c.phy_lc_calibrate)(dm);
979 } else
980 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "Do not do LCK\n");
981 }
982 }
983
984 /*3 7. If necessary, move the index of swing table to adjust Tx power.*/
985 for (i = 0; i < c.rf_path_count; i++) {
986 if (i == RF_PATH_B) {
987 odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_b, DELTA_SWINGIDX_SIZE);
988 odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_b, DELTA_SWINGIDX_SIZE);
989 } else if (i == RF_PATH_C) {
990 odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_c, DELTA_SWINGIDX_SIZE);
991 odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_c, DELTA_SWINGIDX_SIZE);
992 } else if (i == RF_PATH_D) {
993 odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_d, DELTA_SWINGIDX_SIZE);
994 odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_d, DELTA_SWINGIDX_SIZE);
995 } else {
996 odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_a, DELTA_SWINGIDX_SIZE);
997 odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_a, DELTA_SWINGIDX_SIZE);
998 }
999
1000 cali_info->delta_power_index_last[i] = cali_info->delta_power_index[i]; /*recording poer index offset*/
1001 delta[i] = thermal_value[i] > tssi->thermal[i] ? (thermal_value[i] - tssi->thermal[i]) : (tssi->thermal[i] - thermal_value[i]);
1002
1003 if (delta[i] >= TXPWR_TRACK_TABLE_SIZE)
1004 delta[i] = TXPWR_TRACK_TABLE_SIZE - 1;
1005
1006 if (thermal_value[i] > tssi->thermal[i]) {
1007 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
1008 "delta_swing_table_idx_tup[%d]=%d Path=%d\n", delta[i], delta_swing_table_idx_tup[delta[i]], i);
1009
1010 cali_info->delta_power_index[i] = delta_swing_table_idx_tup[delta[i]];
1011 cali_info->absolute_ofdm_swing_idx[i] = delta_swing_table_idx_tup[delta[i]]; /*Record delta swing for mix mode power tracking*/
1012 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
1013 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[%d]=%d Path=%d\n", delta[i], cali_info->absolute_ofdm_swing_idx[i], i);
1014 } else {
1015 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
1016 "delta_swing_table_idx_tdown[%d]=%d Path=%d\n", delta[i], delta_swing_table_idx_tdown[delta[i]], i);
1017 cali_info->delta_power_index[i] = -1 * delta_swing_table_idx_tdown[delta[i]];
1018 cali_info->absolute_ofdm_swing_idx[i] = -1 * delta_swing_table_idx_tdown[delta[i]]; /*Record delta swing for mix mode power tracking*/
1019 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
1020 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[%d]=%d Path=%d\n", delta[i], cali_info->absolute_ofdm_swing_idx[i], i);
1021 }
1022 }
1023
1024 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
1025 if (cali_info->delta_power_index[p] == cali_info->delta_power_index_last[p]) /*If Thermal value changes but lookup table value still the same*/
1026 cali_info->power_index_offset[p] = 0;
1027 else
1028 cali_info->power_index_offset[p] = cali_info->delta_power_index[p] - cali_info->delta_power_index_last[p]; /*Power index diff between 2 times Power Tracking*/
1029 }
1030
1031 #if 0
1032 if (dm->support_ic_type == ODM_RTL8822C) {
1033 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
1034 for (p = RF_PATH_A; p < c.rf_path_count; p++)
1035 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
1036 } else {
1037 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking BBSWING_MODE**********\n");
1038 for (p = RF_PATH_A; p < c.rf_path_count; p++)
1039 (*c.odm_tx_pwr_track_set_pwr)(dm, BBSWING, p, 0);
1040 }
1041 #endif
1042 if (*dm->mp_mode == 1) {
1043 if (cali_info->txpowertrack_control == 1) {
1044 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
1045 tracking_method = MIX_MODE;
1046 } else if (cali_info->txpowertrack_control == 3) {
1047 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking TSSI_MODE**********\n");
1048 tracking_method = TSSI_MODE;
1049 }
1050 } else {
1051 if (rf->power_track_type >= 0 && rf->power_track_type <= 3) {
1052 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
1053 tracking_method = MIX_MODE;
1054 } else if (rf->power_track_type >= 4 && rf->power_track_type <= 7) {
1055 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking TSSI_MODE**********\n");
1056 tracking_method = TSSI_MODE;
1057 }
1058 }
1059
1060 if (dm->support_ic_type == ODM_RTL8822C || dm->support_ic_type == ODM_RTL8814B)
1061 for (p = RF_PATH_A; p < c.rf_path_count; p++)
1062 (*c.odm_tx_pwr_track_set_pwr)(dm, tracking_method, p, 0);
1063
1064 /* Wait sacn to do IQK by RF Jenyu*/
1065 if ((*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden) && (dm->is_linked || *dm->mp_mode)) {
1066 /*Delta temperature is equal to or larger than 20 centigrade (When threshold is 8).*/
1067 if (delta_IQK >= c.threshold_iqk) {
1068 cali_info->thermal_value_iqk = thermal_value[RF_PATH_A];
1069 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_IQK(%d) >= threshold_iqk(%d)\n", delta_IQK, c.threshold_iqk);
1070 /*if (!cali_info->is_iqk_in_progress)*/
1071 /* (*c.do_iqk)(dm, delta_IQK, thermal_value[RF_PATH_A], 8);*/
1072 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "Do IQK\n");
1073
1074 /*if (!cali_info->is_iqk_in_progress)*/
1075 /* (*c.do_tssi_dck)(dm, true);*/
1076 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "Do TSSI DCK\n");
1077 }
1078 }
1079
1080 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "<===%s\n", __func__);
1081
1082 cali_info->tx_powercount = 0;
1083 }
1084 #endif
1085
1086 /*@3============================================================
1087 * 3 IQ Calibration
1088 * 3============================================================
1089 */
1090
1091 void odm_reset_iqk_result(void *dm_void)
1092 {
1093 }
1094
1095 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
1096 u8 odm_get_right_chnl_place_for_iqk(u8 chnl)
1097 {
1098 u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
1099 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1100 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
1101 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
1102 124, 126, 128, 130, 132, 134, 136, 138, 140,
1103 149, 151, 153, 155, 157, 159, 161, 163, 165};
1104 u8 place = chnl;
1105
1106 if (chnl > 14) {
1107 for (place = 14; place < sizeof(channel_all); place++) {
1108 if (channel_all[place] == chnl)
1109 return place - 13;
1110 }
1111 }
1112 return 0;
1113 }
1114 #endif
1115
1116 void odm_iq_calibrate(struct dm_struct *dm)
1117 {
1118 void *adapter = dm->adapter;
1119 struct dm_iqk_info *iqk_info = &dm->IQK_info;
1120
1121 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
1122 if (*dm->is_fcs_mode_enable)
1123 return;
1124 #endif
1125
1126 #if (DM_ODM_SUPPORT_TYPE & (ODM_CE))
1127 if (IS_HARDWARE_TYPE_8812AU(adapter))
1128 return;
1129 #endif
1130
1131 if (dm->is_linked && !iqk_info->rfk_forbidden) {
1132 if ((*dm->channel != dm->pre_channel) &&
1133 (!*dm->is_scan_in_process)) {
1134 dm->pre_channel = *dm->channel;
1135 dm->linked_interval = 0;
1136 }
1137
1138 if (dm->linked_interval < 3)
1139 dm->linked_interval++;
1140
1141 if (dm->linked_interval == 2)
1142 halrf_iqk_trigger(dm, false);
1143 } else {
1144 dm->linked_interval = 0;
1145 }
1146 }
1147
1148 void phydm_rf_init(void *dm_void)
1149 {
1150 struct dm_struct *dm = (struct dm_struct *)dm_void;
1151
1152 odm_txpowertracking_init(dm);
1153
1154 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
1155 odm_clear_txpowertracking_state(dm);
1156 #endif
1157 #if (DM_ODM_SUPPORT_TYPE & (ODM_AP))
1158 #if (RTL8814A_SUPPORT == 1)
1159 if (dm->support_ic_type & ODM_RTL8814A)
1160 phy_iq_calibrate_8814a_init(dm);
1161 #endif
1162 #endif
1163 }
1164
1165 void phydm_rf_watchdog(void *dm_void)
1166 {
1167 struct dm_struct *dm = (struct dm_struct *)dm_void;
1168
1169 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
1170 odm_txpowertracking_check(dm);
1171 #if 0
1172 /*if (dm->support_ic_type & ODM_IC_11AC_SERIES)*/
1173 /*odm_iq_calibrate(dm);*/
1174 #endif
1175 #endif
1176 }
1177