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