1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
4 * Copyright(c) 2007 - 2016 Realtek Corporation.
7 * wlanfae <wlanfae@realtek.com>
8 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
11 * Larry Finger <Larry.Finger@lwfinger.net>
13 *****************************************************************************/
15 #include "mp_precomp.h"
16 #include "phydm_precomp.h"
18 #define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, \
21 for (_offset = 0; _offset < _size; _offset++) { \
22 if (_delta_thermal < \
23 thermal_threshold[_direction][_offset]) { \
29 if (_offset >= _size) \
30 _offset = _size - 1; \
33 static inline void phydm_set_calibrate_info_up(
34 struct phy_dm_struct *dm, struct txpwrtrack_cfg *c, u8 delta,
35 struct dm_rf_calibration_struct *cali_info,
36 u8 *delta_swing_table_idx_tup_a, u8 *delta_swing_table_idx_tup_b,
37 u8 *delta_swing_table_idx_tup_c, u8 *delta_swing_table_idx_tup_d)
41 for (p = ODM_RF_PATH_A; p < c->rf_path_count; p++) {
42 cali_info->delta_power_index_last[p] =
43 cali_info->delta_power_index
44 [p]; /*recording poer index offset*/
47 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
48 "delta_swing_table_idx_tup_b[%d] = %d\n",
49 delta, delta_swing_table_idx_tup_b[delta]);
51 cali_info->delta_power_index[p] =
52 delta_swing_table_idx_tup_b[delta];
53 /*Record delta swing for mix mode pwr tracking*/
54 cali_info->absolute_ofdm_swing_idx[p] =
55 delta_swing_table_idx_tup_b[delta];
57 dm, ODM_COMP_TX_PWR_TRACK,
58 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_B] = %d\n",
59 cali_info->absolute_ofdm_swing_idx[p]);
63 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
64 "delta_swing_table_idx_tup_c[%d] = %d\n",
65 delta, delta_swing_table_idx_tup_c[delta]);
67 cali_info->delta_power_index[p] =
68 delta_swing_table_idx_tup_c[delta];
69 /*Record delta swing for mix mode pwr tracking*/
70 cali_info->absolute_ofdm_swing_idx[p] =
71 delta_swing_table_idx_tup_c[delta];
73 dm, ODM_COMP_TX_PWR_TRACK,
74 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_C] = %d\n",
75 cali_info->absolute_ofdm_swing_idx[p]);
79 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
80 "delta_swing_table_idx_tup_d[%d] = %d\n",
81 delta, delta_swing_table_idx_tup_d[delta]);
83 cali_info->delta_power_index[p] =
84 delta_swing_table_idx_tup_d[delta];
85 /*Record delta swing for mix mode pwr tracking*/
86 cali_info->absolute_ofdm_swing_idx[p] =
87 delta_swing_table_idx_tup_d[delta];
89 dm, ODM_COMP_TX_PWR_TRACK,
90 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_D] = %d\n",
91 cali_info->absolute_ofdm_swing_idx[p]);
95 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
96 "delta_swing_table_idx_tup_a[%d] = %d\n",
97 delta, delta_swing_table_idx_tup_a[delta]);
99 cali_info->delta_power_index[p] =
100 delta_swing_table_idx_tup_a[delta];
101 /*Record delta swing for mix mode pwr tracking*/
102 cali_info->absolute_ofdm_swing_idx[p] =
103 delta_swing_table_idx_tup_a[delta];
105 dm, ODM_COMP_TX_PWR_TRACK,
106 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_A] = %d\n",
107 cali_info->absolute_ofdm_swing_idx[p]);
113 static inline void phydm_set_calibrate_info_down(
114 struct phy_dm_struct *dm, struct txpwrtrack_cfg *c, u8 delta,
115 struct dm_rf_calibration_struct *cali_info,
116 u8 *delta_swing_table_idx_tdown_a, u8 *delta_swing_table_idx_tdown_b,
117 u8 *delta_swing_table_idx_tdown_c, u8 *delta_swing_table_idx_tdown_d)
121 for (p = ODM_RF_PATH_A; p < c->rf_path_count; p++) {
122 cali_info->delta_power_index_last[p] =
123 cali_info->delta_power_index
124 [p]; /*recording poer index offset*/
128 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
129 "delta_swing_table_idx_tdown_b[%d] = %d\n",
131 delta_swing_table_idx_tdown_b[delta]);
132 cali_info->delta_power_index[p] =
133 -1 * delta_swing_table_idx_tdown_b[delta];
134 /*Record delta swing for mix mode pwr tracking*/
135 cali_info->absolute_ofdm_swing_idx[p] =
136 -1 * delta_swing_table_idx_tdown_b[delta];
138 dm, ODM_COMP_TX_PWR_TRACK,
139 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_B] = %d\n",
140 cali_info->absolute_ofdm_swing_idx[p]);
144 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
145 "delta_swing_table_idx_tdown_c[%d] = %d\n",
147 delta_swing_table_idx_tdown_c[delta]);
148 cali_info->delta_power_index[p] =
149 -1 * delta_swing_table_idx_tdown_c[delta];
150 /*Record delta swing for mix mode pwr tracking*/
151 cali_info->absolute_ofdm_swing_idx[p] =
152 -1 * delta_swing_table_idx_tdown_c[delta];
154 dm, ODM_COMP_TX_PWR_TRACK,
155 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_C] = %d\n",
156 cali_info->absolute_ofdm_swing_idx[p]);
160 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
161 "delta_swing_table_idx_tdown_d[%d] = %d\n",
163 delta_swing_table_idx_tdown_d[delta]);
164 cali_info->delta_power_index[p] =
165 -1 * delta_swing_table_idx_tdown_d[delta];
166 /*Record delta swing for mix mode pwr tracking*/
167 cali_info->absolute_ofdm_swing_idx[p] =
168 -1 * delta_swing_table_idx_tdown_d[delta];
170 dm, ODM_COMP_TX_PWR_TRACK,
171 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_D] = %d\n",
172 cali_info->absolute_ofdm_swing_idx[p]);
176 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
177 "delta_swing_table_idx_tdown_a[%d] = %d\n",
179 delta_swing_table_idx_tdown_a[delta]);
180 cali_info->delta_power_index[p] =
181 -1 * delta_swing_table_idx_tdown_a[delta];
182 /*Record delta swing for mix mode pwr tracking*/
183 cali_info->absolute_ofdm_swing_idx[p] =
184 -1 * delta_swing_table_idx_tdown_a[delta];
186 dm, ODM_COMP_TX_PWR_TRACK,
187 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_A] = %d\n",
188 cali_info->absolute_ofdm_swing_idx[p]);
194 static inline void phydm_odm_tx_power_set(struct phy_dm_struct *dm,
195 struct txpwrtrack_cfg *c,
196 u8 indexforchannel, u8 flag)
200 if (dm->support_ic_type == ODM_RTL8188E ||
201 dm->support_ic_type == ODM_RTL8192E ||
202 dm->support_ic_type == ODM_RTL8821 ||
203 dm->support_ic_type == ODM_RTL8812 ||
204 dm->support_ic_type == ODM_RTL8723B ||
205 dm->support_ic_type == ODM_RTL8814A ||
206 dm->support_ic_type == ODM_RTL8703B ||
207 dm->support_ic_type == ODM_RTL8188F ||
208 dm->support_ic_type == ODM_RTL8822B ||
209 dm->support_ic_type == ODM_RTL8723D ||
210 dm->support_ic_type == ODM_RTL8821C ||
211 dm->support_ic_type == ODM_RTL8710B) { /* JJ ADD 20161014 */
214 dm, ODM_COMP_TX_PWR_TRACK,
215 "**********Enter POWER Tracking MIX_MODE**********\n");
216 for (p = ODM_RF_PATH_A; p < c->rf_path_count; p++) {
218 (*c->odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
221 (*c->odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
226 dm, ODM_COMP_TX_PWR_TRACK,
227 "**********Enter POWER Tracking BBSWING_MODE**********\n");
228 for (p = ODM_RF_PATH_A; p < c->rf_path_count; p++)
229 (*c->odm_tx_pwr_track_set_pwr)(dm, BBSWING, p,
234 void configure_txpower_track(void *dm_void, struct txpwrtrack_cfg *config)
236 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
238 /* JJ ADD 20161014 */
240 if (dm->support_ic_type == ODM_RTL8822B)
241 configure_txpower_track_8822b(config);
244 /* **********************************************************************
245 * <20121113, Kordan> This function should be called when tx_agc changed.
246 * Otherwise the previous compensation is gone, because we record the
247 * delta of temperature between two TxPowerTracking watch dogs.
249 * NOTE: If Tx BB swing or Tx scaling is varified during run-time, still
250 * need to call this function.
251 * ***********************************************************************/
252 void odm_clear_txpowertracking_state(void *dm_void)
254 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
255 struct rtl_priv *rtlpriv = (struct rtl_priv *)dm->adapter;
256 struct rtl_efuse *rtlefu = rtl_efuse(rtlpriv);
258 struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
260 cali_info->bb_swing_idx_cck_base = cali_info->default_cck_index;
261 cali_info->bb_swing_idx_cck = cali_info->default_cck_index;
262 dm->rf_calibrate_info.CCK_index = 0;
264 for (p = ODM_RF_PATH_A; p < MAX_RF_PATH; ++p) {
265 cali_info->bb_swing_idx_ofdm_base[p] =
266 cali_info->default_ofdm_index;
267 cali_info->bb_swing_idx_ofdm[p] = cali_info->default_ofdm_index;
268 cali_info->OFDM_index[p] = cali_info->default_ofdm_index;
270 cali_info->power_index_offset[p] = 0;
271 cali_info->delta_power_index[p] = 0;
272 cali_info->delta_power_index_last[p] = 0;
274 cali_info->absolute_ofdm_swing_idx[p] =
275 0; /* Initial Mix mode power tracking*/
276 cali_info->remnant_ofdm_swing_idx[p] = 0;
277 cali_info->kfree_offset[p] = 0;
280 cali_info->modify_tx_agc_flag_path_a =
281 false; /*Initial at Modify Tx Scaling mode*/
282 cali_info->modify_tx_agc_flag_path_b =
283 false; /*Initial at Modify Tx Scaling mode*/
284 cali_info->modify_tx_agc_flag_path_c =
285 false; /*Initial at Modify Tx Scaling mode*/
286 cali_info->modify_tx_agc_flag_path_d =
287 false; /*Initial at Modify Tx Scaling mode*/
288 cali_info->remnant_cck_swing_idx = 0;
289 cali_info->thermal_value = rtlefu->eeprom_thermalmeter;
291 cali_info->modify_tx_agc_value_cck = 0; /* modify by Mingzhi.Guo */
292 cali_info->modify_tx_agc_value_ofdm = 0; /* modify by Mingzhi.Guo */
295 void odm_txpowertracking_callback_thermal_meter(void *dm_void)
297 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
298 struct rtl_priv *rtlpriv = (struct rtl_priv *)dm->adapter;
299 struct rtl_efuse *rtlefu = rtl_efuse(rtlpriv);
300 void *adapter = dm->adapter;
302 struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
304 u8 thermal_value = 0, delta, delta_LCK, delta_IQK, p = 0, i = 0;
305 s8 diff_DPK[4]; /* use 'for..loop' to initialize */
306 u8 thermal_value_avg_count = 0;
307 u32 thermal_value_avg = 0, regc80, regcd0, regcd4, regab4;
309 /* OFDM BB Swing should be less than +3.0dB (required by Arthur) */
310 u8 OFDM_min_index = 0;
311 /* get_right_chnl_place_for_iqk(hal_data->current_channel) */
312 u8 indexforchannel = 0;
313 u8 power_tracking_type = 0; /* no specify type */
314 u8 xtal_offset_eanble = 0;
316 struct txpwrtrack_cfg c;
318 /* 4 1. The following TWO tables decide the final index of
319 * OFDM/CCK swing table.
321 u8 *delta_swing_table_idx_tup_a = NULL;
322 u8 *delta_swing_table_idx_tdown_a = NULL;
323 u8 *delta_swing_table_idx_tup_b = NULL;
324 u8 *delta_swing_table_idx_tdown_b = NULL;
325 /*for 8814 add by Yu Chen*/
326 u8 *delta_swing_table_idx_tup_c = NULL;
327 u8 *delta_swing_table_idx_tdown_c = NULL;
328 u8 *delta_swing_table_idx_tup_d = NULL;
329 u8 *delta_swing_table_idx_tdown_d = NULL;
330 /*for Xtal Offset by James.Tung*/
331 s8 *delta_swing_table_xtal_up = NULL;
332 s8 *delta_swing_table_xtal_down = NULL;
334 /* 4 2. Initialization ( 7 steps in total ) */
336 configure_txpower_track(dm, &c);
338 (*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_a,
339 (u8 **)&delta_swing_table_idx_tdown_a,
340 (u8 **)&delta_swing_table_idx_tup_b,
341 (u8 **)&delta_swing_table_idx_tdown_b);
343 if (dm->support_ic_type & ODM_RTL8814A) /*for 8814 path C & D*/
344 (*c.get_delta_swing_table8814only)(
345 dm, (u8 **)&delta_swing_table_idx_tup_c,
346 (u8 **)&delta_swing_table_idx_tdown_c,
347 (u8 **)&delta_swing_table_idx_tup_d,
348 (u8 **)&delta_swing_table_idx_tdown_d);
349 /* JJ ADD 20161014 */
350 if (dm->support_ic_type &
351 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B)) /*for Xtal Offset*/
352 (*c.get_delta_swing_xtal_table)(
353 dm, (s8 **)&delta_swing_table_xtal_up,
354 (s8 **)&delta_swing_table_xtal_down);
356 cali_info->txpowertracking_callback_cnt++; /*cosa add for debug*/
357 cali_info->is_txpowertracking_init = true;
359 /*cali_info->txpowertrack_control = hal_data->txpowertrack_control;
360 *<Kordan> We should keep updating ctrl variable according to HalData.
361 *<Kordan> rf_calibrate_info.rega24 will be initialized when
362 *ODM HW configuring, but MP configures with para files.
365 cali_info->rega24 = 0x090e1317;
368 dm, ODM_COMP_TX_PWR_TRACK,
369 "===>%s\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",
370 __func__, cali_info->bb_swing_idx_cck_base,
371 cali_info->bb_swing_idx_ofdm_base[ODM_RF_PATH_A],
372 cali_info->default_ofdm_index);
375 dm, ODM_COMP_TX_PWR_TRACK,
376 "cali_info->txpowertrack_control=%d, rtlefu->eeprom_thermalmeter %d\n",
377 cali_info->txpowertrack_control, rtlefu->eeprom_thermalmeter);
380 (u8)odm_get_rf_reg(dm, ODM_RF_PATH_A, c.thermal_reg_addr,
381 0xfc00); /* 0x42: RF Reg[15:10] 88E */
383 /*add log by zhao he, check c80/c94/c14/ca0 value*/
384 if (dm->support_ic_type == ODM_RTL8723D) {
385 regc80 = odm_get_bb_reg(dm, 0xc80, MASKDWORD);
386 regcd0 = odm_get_bb_reg(dm, 0xcd0, MASKDWORD);
387 regcd4 = odm_get_bb_reg(dm, 0xcd4, MASKDWORD);
388 regab4 = odm_get_bb_reg(dm, 0xab4, 0x000007FF);
390 dm, ODM_COMP_CALIBRATION,
391 "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n",
392 regc80, regcd0, regcd4, regab4);
394 /* JJ ADD 20161014 */
395 if (dm->support_ic_type == ODM_RTL8710B) {
396 regc80 = odm_get_bb_reg(dm, 0xc80, MASKDWORD);
397 regcd0 = odm_get_bb_reg(dm, 0xcd0, MASKDWORD);
398 regcd4 = odm_get_bb_reg(dm, 0xcd4, MASKDWORD);
399 regab4 = odm_get_bb_reg(dm, 0xab4, 0x000007FF);
401 dm, ODM_COMP_CALIBRATION,
402 "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n",
403 regc80, regcd0, regcd4, regab4);
406 if (!cali_info->txpowertrack_control)
409 /*4 3. Initialize ThermalValues of rf_calibrate_info*/
411 if (cali_info->is_reloadtxpowerindex)
412 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
413 "reload ofdm index for band switch\n");
415 /*4 4. Calculate average thermal meter*/
417 cali_info->thermal_value_avg[cali_info->thermal_value_avg_index] =
419 cali_info->thermal_value_avg_index++;
420 if (cali_info->thermal_value_avg_index ==
421 c.average_thermal_num) /*Average times = c.average_thermal_num*/
422 cali_info->thermal_value_avg_index = 0;
424 for (i = 0; i < c.average_thermal_num; i++) {
425 if (cali_info->thermal_value_avg[i]) {
426 thermal_value_avg += cali_info->thermal_value_avg[i];
427 thermal_value_avg_count++;
431 if (thermal_value_avg_count) {
432 /* Calculate Average thermal_value after average enough times */
434 (u8)(thermal_value_avg / thermal_value_avg_count);
435 cali_info->thermal_value_delta =
436 thermal_value - rtlefu->eeprom_thermalmeter;
438 dm, ODM_COMP_TX_PWR_TRACK,
439 "AVG Thermal Meter = 0x%X, EFUSE Thermal base = 0x%X\n",
440 thermal_value, rtlefu->eeprom_thermalmeter);
443 /* 4 5. Calculate delta, delta_LCK, delta_IQK. */
445 /* "delta" is used to determine whether thermal value changes or not*/
446 delta = (thermal_value > cali_info->thermal_value) ?
447 (thermal_value - cali_info->thermal_value) :
448 (cali_info->thermal_value - thermal_value);
449 delta_LCK = (thermal_value > cali_info->thermal_value_lck) ?
450 (thermal_value - cali_info->thermal_value_lck) :
451 (cali_info->thermal_value_lck - thermal_value);
452 delta_IQK = (thermal_value > cali_info->thermal_value_iqk) ?
453 (thermal_value - cali_info->thermal_value_iqk) :
454 (cali_info->thermal_value_iqk - thermal_value);
456 if (cali_info->thermal_value_iqk ==
457 0xff) { /*no PG, use thermal value for IQK*/
458 cali_info->thermal_value_iqk = thermal_value;
460 (thermal_value > cali_info->thermal_value_iqk) ?
461 (thermal_value - cali_info->thermal_value_iqk) :
462 (cali_info->thermal_value_iqk - thermal_value);
463 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
464 "no PG, use thermal_value for IQK\n");
467 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
468 diff_DPK[p] = (s8)thermal_value - (s8)cali_info->dpk_thermal[p];
470 /*4 6. If necessary, do LCK.*/
472 if (!(dm->support_ic_type &
473 ODM_RTL8821)) { /*no PG, do LCK at initial status*/
474 if (cali_info->thermal_value_lck == 0xff) {
475 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
477 cali_info->thermal_value_lck = thermal_value;
479 /*Use RTLCK, so close power tracking driver LCK*/
480 if (!(dm->support_ic_type & ODM_RTL8814A) &&
482 (*c.phy_lc_calibrate)(dm);
485 (thermal_value > cali_info->thermal_value_lck) ?
487 cali_info->thermal_value_lck) :
488 (cali_info->thermal_value_lck -
492 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
493 "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
494 delta, delta_LCK, delta_IQK);
496 /*Delta temperature is equal to or larger than 20 centigrade.*/
497 if (delta_LCK >= c.threshold_iqk) {
498 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
499 "delta_LCK(%d) >= threshold_iqk(%d)\n",
500 delta_LCK, c.threshold_iqk);
501 cali_info->thermal_value_lck = thermal_value;
503 /*Use RTLCK, so close power tracking driver LCK*/
504 if (!(dm->support_ic_type & ODM_RTL8814A) &&
506 (*c.phy_lc_calibrate)(dm);
510 /*3 7. If necessary, move the index of swing table to adjust Tx power.*/
512 if (delta > 0 && cali_info->txpowertrack_control) {
513 /* "delta" here is used to record the abs value of difference.*/
514 delta = thermal_value > rtlefu->eeprom_thermalmeter ?
515 (thermal_value - rtlefu->eeprom_thermalmeter) :
516 (rtlefu->eeprom_thermalmeter - thermal_value);
517 if (delta >= TXPWR_TRACK_TABLE_SIZE)
518 delta = TXPWR_TRACK_TABLE_SIZE - 1;
520 /*4 7.1 The Final Power index = BaseIndex + power_index_offset*/
522 if (thermal_value > rtlefu->eeprom_thermalmeter) {
523 phydm_set_calibrate_info_up(
524 dm, &c, delta, cali_info,
525 delta_swing_table_idx_tup_a,
526 delta_swing_table_idx_tup_b,
527 delta_swing_table_idx_tup_c,
528 delta_swing_table_idx_tup_d);
529 /* JJ ADD 20161014 */
530 if (dm->support_ic_type &
531 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B)) {
532 /*Save xtal_offset from Xtal table*/
534 /*recording last Xtal offset*/
535 cali_info->xtal_offset_last =
536 cali_info->xtal_offset;
538 dm, ODM_COMP_TX_PWR_TRACK,
539 "[Xtal] delta_swing_table_xtal_up[%d] = %d\n",
541 delta_swing_table_xtal_up[delta]);
542 cali_info->xtal_offset =
543 delta_swing_table_xtal_up[delta];
545 (cali_info->xtal_offset_last ==
546 cali_info->xtal_offset) ?
552 phydm_set_calibrate_info_down(
553 dm, &c, delta, cali_info,
554 delta_swing_table_idx_tdown_a,
555 delta_swing_table_idx_tdown_b,
556 delta_swing_table_idx_tdown_c,
557 delta_swing_table_idx_tdown_d);
558 /* JJ ADD 20161014 */
559 if (dm->support_ic_type &
560 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B)) {
561 /*Save xtal_offset from Xtal table*/
563 /*recording last Xtal offset*/
564 cali_info->xtal_offset_last =
565 cali_info->xtal_offset;
567 dm, ODM_COMP_TX_PWR_TRACK,
568 "[Xtal] delta_swing_table_xtal_down[%d] = %d\n",
570 delta_swing_table_xtal_down[delta]);
571 cali_info->xtal_offset =
572 delta_swing_table_xtal_down[delta];
574 (cali_info->xtal_offset_last ==
575 cali_info->xtal_offset) ?
581 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) {
583 dm, ODM_COMP_TX_PWR_TRACK,
584 "\n\n=========================== [path-%d] Calculating power_index_offset===========================\n",
587 if (cali_info->delta_power_index[p] ==
588 cali_info->delta_power_index_last[p]) {
589 /* If Thermal value changes but lookup table
590 * value still the same
592 cali_info->power_index_offset[p] = 0;
594 /*Power idx diff between 2 times Pwr Tracking*/
595 cali_info->power_index_offset[p] =
596 cali_info->delta_power_index[p] -
597 cali_info->delta_power_index_last[p];
601 dm, ODM_COMP_TX_PWR_TRACK,
602 "[path-%d] power_index_offset(%d) = delta_power_index(%d) - delta_power_index_last(%d)\n",
603 p, cali_info->power_index_offset[p],
604 cali_info->delta_power_index[p],
605 cali_info->delta_power_index_last[p]);
607 cali_info->OFDM_index[p] =
608 cali_info->bb_swing_idx_ofdm_base[p] +
609 cali_info->power_index_offset[p];
610 cali_info->CCK_index =
611 cali_info->bb_swing_idx_cck_base +
612 cali_info->power_index_offset[p];
614 cali_info->bb_swing_idx_cck = cali_info->CCK_index;
615 cali_info->bb_swing_idx_ofdm[p] =
616 cali_info->OFDM_index[p];
618 /*******Print BB Swing base and index Offset**********/
621 dm, ODM_COMP_TX_PWR_TRACK,
622 "The 'CCK' final index(%d) = BaseIndex(%d) + power_index_offset(%d)\n",
623 cali_info->bb_swing_idx_cck,
624 cali_info->bb_swing_idx_cck_base,
625 cali_info->power_index_offset[p]);
627 dm, ODM_COMP_TX_PWR_TRACK,
628 "The 'OFDM' final index(%d) = BaseIndex[%d](%d) + power_index_offset(%d)\n",
629 cali_info->bb_swing_idx_ofdm[p], p,
630 cali_info->bb_swing_idx_ofdm_base[p],
631 cali_info->power_index_offset[p]);
633 /*4 7.1 Handle boundary conditions of index.*/
635 if (cali_info->OFDM_index[p] >
636 c.swing_table_size_ofdm - 1)
637 cali_info->OFDM_index[p] =
638 c.swing_table_size_ofdm - 1;
639 else if (cali_info->OFDM_index[p] <= OFDM_min_index)
640 cali_info->OFDM_index[p] = OFDM_min_index;
644 dm, ODM_COMP_TX_PWR_TRACK,
645 "\n\n========================================================================================================\n");
647 if (cali_info->CCK_index > c.swing_table_size_cck - 1)
648 cali_info->CCK_index = c.swing_table_size_cck - 1;
649 else if (cali_info->CCK_index <= 0)
650 cali_info->CCK_index = 0;
653 dm, ODM_COMP_TX_PWR_TRACK,
654 "The thermal meter is unchanged or TxPowerTracking OFF(%d): thermal_value: %d, cali_info->thermal_value: %d\n",
655 cali_info->txpowertrack_control, thermal_value,
656 cali_info->thermal_value);
658 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
659 cali_info->power_index_offset[p] = 0;
662 /*Print Swing base & current*/
664 dm, ODM_COMP_TX_PWR_TRACK,
665 "TxPowerTracking: [CCK] Swing Current index: %d, Swing base index: %d\n",
666 cali_info->CCK_index, cali_info->bb_swing_idx_cck_base);
668 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
670 dm, ODM_COMP_TX_PWR_TRACK,
671 "TxPowerTracking: [OFDM] Swing Current index: %d, Swing base index[%d]: %d\n",
672 cali_info->OFDM_index[p], p,
673 cali_info->bb_swing_idx_ofdm_base[p]);
675 if ((dm->support_ic_type & ODM_RTL8814A)) {
676 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
677 "power_tracking_type=%d\n", power_tracking_type);
679 if (power_tracking_type == 0) {
681 dm, ODM_COMP_TX_PWR_TRACK,
682 "**********Enter POWER Tracking MIX_MODE**********\n");
683 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
684 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
686 } else if (power_tracking_type == 1) {
688 dm, ODM_COMP_TX_PWR_TRACK,
689 "**********Enter POWER Tracking MIX(2G) TSSI(5G) MODE**********\n");
690 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
691 (*c.odm_tx_pwr_track_set_pwr)(
692 dm, MIX_2G_TSSI_5G_MODE, p, 0);
693 } else if (power_tracking_type == 2) {
695 dm, ODM_COMP_TX_PWR_TRACK,
696 "**********Enter POWER Tracking MIX(5G) TSSI(2G)MODE**********\n");
697 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
698 (*c.odm_tx_pwr_track_set_pwr)(
699 dm, MIX_5G_TSSI_2G_MODE, p, 0);
700 } else if (power_tracking_type == 3) {
702 dm, ODM_COMP_TX_PWR_TRACK,
703 "**********Enter POWER Tracking TSSI MODE**********\n");
704 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
705 (*c.odm_tx_pwr_track_set_pwr)(dm, TSSI_MODE, p,
708 /*Record last Power Tracking Thermal value*/
709 cali_info->thermal_value = thermal_value;
711 } else if ((cali_info->power_index_offset[ODM_RF_PATH_A] != 0 ||
712 cali_info->power_index_offset[ODM_RF_PATH_B] != 0 ||
713 cali_info->power_index_offset[ODM_RF_PATH_C] != 0 ||
714 cali_info->power_index_offset[ODM_RF_PATH_D] != 0) &&
715 cali_info->txpowertrack_control &&
716 (rtlefu->eeprom_thermalmeter != 0xff)) {
717 /* 4 7.2 Configure the Swing Table to adjust Tx Power. */
719 /*Always true after Tx Power is adjusted by power tracking.*/
720 cali_info->is_tx_power_changed = true;
721 /* 2012/04/23 MH According to Luke's suggestion, we can not
722 * write BB digital to increase TX power. Otherwise, EVM will
725 /* 2012/04/25 MH Add for tx power tracking to set tx power in
728 if (thermal_value > cali_info->thermal_value) {
729 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) {
730 /* print temperature increasing */
732 dm, ODM_COMP_TX_PWR_TRACK,
733 "Temperature Increasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
734 p, cali_info->power_index_offset[p],
735 delta, thermal_value,
736 rtlefu->eeprom_thermalmeter,
737 cali_info->thermal_value);
739 } else if (thermal_value <
740 cali_info->thermal_value) { /*Low temperature*/
741 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) {
742 /* print temperature decreasing */
744 dm, ODM_COMP_TX_PWR_TRACK,
745 "Temperature Decreasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
746 p, cali_info->power_index_offset[p],
747 delta, thermal_value,
748 rtlefu->eeprom_thermalmeter,
749 cali_info->thermal_value);
753 if (thermal_value > rtlefu->eeprom_thermalmeter) {
755 dm, ODM_COMP_TX_PWR_TRACK,
756 "Temperature(%d) higher than PG value(%d)\n",
757 thermal_value, rtlefu->eeprom_thermalmeter);
759 phydm_odm_tx_power_set(dm, &c, indexforchannel, 0);
762 dm, ODM_COMP_TX_PWR_TRACK,
763 "Temperature(%d) lower than PG value(%d)\n",
764 thermal_value, rtlefu->eeprom_thermalmeter);
765 phydm_odm_tx_power_set(dm, &c, indexforchannel, 1);
768 /*Record last time Power Tracking result as base.*/
769 cali_info->bb_swing_idx_cck_base = cali_info->bb_swing_idx_cck;
771 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
772 cali_info->bb_swing_idx_ofdm_base[p] =
773 cali_info->bb_swing_idx_ofdm[p];
776 dm, ODM_COMP_TX_PWR_TRACK,
777 "cali_info->thermal_value = %d thermal_value= %d\n",
778 cali_info->thermal_value, thermal_value);
780 /*Record last Power Tracking Thermal value*/
781 cali_info->thermal_value = thermal_value;
784 if (dm->support_ic_type == ODM_RTL8703B ||
785 dm->support_ic_type == ODM_RTL8723D ||
786 dm->support_ic_type == ODM_RTL8710B) { /* JJ ADD 20161014 */
788 if (xtal_offset_eanble != 0 &&
789 cali_info->txpowertrack_control &&
790 rtlefu->eeprom_thermalmeter != 0xff) {
792 dm, ODM_COMP_TX_PWR_TRACK,
793 "**********Enter Xtal Tracking**********\n");
795 if (thermal_value > rtlefu->eeprom_thermalmeter) {
797 dm, ODM_COMP_TX_PWR_TRACK,
798 "Temperature(%d) higher than PG value(%d)\n",
800 rtlefu->eeprom_thermalmeter);
801 (*c.odm_txxtaltrack_set_xtal)(dm);
804 dm, ODM_COMP_TX_PWR_TRACK,
805 "Temperature(%d) lower than PG value(%d)\n",
807 rtlefu->eeprom_thermalmeter);
808 (*c.odm_txxtaltrack_set_xtal)(dm);
811 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
812 "**********End Xtal Tracking**********\n");
815 if (!IS_HARDWARE_TYPE_8723B(adapter)) {
816 /* Delta temperature is equal to or larger than 20 centigrade
817 * (When threshold is 8).
819 if (delta_IQK >= c.threshold_iqk) {
820 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
821 "delta_IQK(%d) >= threshold_iqk(%d)\n",
822 delta_IQK, c.threshold_iqk);
823 if (!cali_info->is_iqk_in_progress)
824 (*c.do_iqk)(dm, delta_IQK, thermal_value, 8);
827 if (cali_info->dpk_thermal[ODM_RF_PATH_A] != 0) {
828 if (diff_DPK[ODM_RF_PATH_A] >= c.threshold_dpk) {
829 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
832 BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10),
833 (diff_DPK[ODM_RF_PATH_A] / c.threshold_dpk));
834 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
835 } else if ((diff_DPK[ODM_RF_PATH_A] <= -1 * c.threshold_dpk)) {
837 (diff_DPK[ODM_RF_PATH_A] / c.threshold_dpk);
839 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
840 odm_set_bb_reg(dm, 0xcc4, BIT(14) | BIT(13) | BIT(12) |
843 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
845 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
846 odm_set_bb_reg(dm, 0xcc4, BIT(14) | BIT(13) | BIT(12) |
849 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
852 if (cali_info->dpk_thermal[ODM_RF_PATH_B] != 0) {
853 if (diff_DPK[ODM_RF_PATH_B] >= c.threshold_dpk) {
854 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
857 BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10),
858 (diff_DPK[ODM_RF_PATH_B] / c.threshold_dpk));
859 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
860 } else if ((diff_DPK[ODM_RF_PATH_B] <= -1 * c.threshold_dpk)) {
862 (diff_DPK[ODM_RF_PATH_B] / c.threshold_dpk);
864 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
865 odm_set_bb_reg(dm, 0xec4, BIT(14) | BIT(13) | BIT(12) |
868 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
870 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
871 odm_set_bb_reg(dm, 0xec4, BIT(14) | BIT(13) | BIT(12) |
874 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
878 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK, "<===%s\n", __func__);
880 cali_info->tx_powercount = 0;
883 /* 3============================================================
885 * 3============================================================
888 void odm_reset_iqk_result(void *dm_void) { return; }
890 u8 odm_get_right_chnl_place_for_iqk(u8 chnl)
892 u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
893 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
894 13, 14, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54,
895 56, 58, 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
896 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136,
897 138, 140, 149, 151, 153, 155, 157, 159, 161, 163, 165};
901 for (place = 14; place < sizeof(channel_all); place++) {
902 if (channel_all[place] == chnl)
909 static void odm_iq_calibrate(struct phy_dm_struct *dm)
911 void *adapter = dm->adapter;
913 if (IS_HARDWARE_TYPE_8812AU(adapter))
917 if ((*dm->channel != dm->pre_channel) &&
918 (!*dm->is_scan_in_process)) {
919 dm->pre_channel = *dm->channel;
920 dm->linked_interval = 0;
923 if (dm->linked_interval < 3)
924 dm->linked_interval++;
926 if (dm->linked_interval == 2) {
927 if (IS_HARDWARE_TYPE_8814A(adapter))
930 else if (IS_HARDWARE_TYPE_8822B(adapter))
931 phy_iq_calibrate_8822b(dm, false);
934 dm->linked_interval = 0;
938 void phydm_rf_init(void *dm_void)
940 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
942 odm_txpowertracking_init(dm);
944 odm_clear_txpowertracking_state(dm);
947 void phydm_rf_watchdog(void *dm_void)
949 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
951 odm_txpowertracking_check(dm);
952 if (dm->support_ic_type & ODM_IC_11AC_SERIES)
953 odm_iq_calibrate(dm);