1 /******************************************************************************
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
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.
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
14 *****************************************************************************/
16 #include "mp_precomp.h"
17 #include "phydm_precomp.h"
19 #define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, _delta_thermal) \
21 for (_offset = 0; _offset < _size; _offset++) { \
23 if (_delta_thermal < thermal_threshold[_direction][_offset]) { \
30 if (_offset >= _size)\
34 void configure_txpower_track(
36 struct txpwrtrack_cfg *config
40 if (dm->support_ic_type == ODM_RTL8192E)
41 configure_txpower_track_8192e(config);
44 if (dm->support_ic_type == ODM_RTL8821)
45 configure_txpower_track_8821a(config);
48 if (dm->support_ic_type == ODM_RTL8812)
49 configure_txpower_track_8812a(config);
52 if (dm->support_ic_type == ODM_RTL8188E)
53 configure_txpower_track_8188e(config);
57 if (dm->support_ic_type == ODM_RTL8188F)
58 configure_txpower_track_8188f(config);
62 if (dm->support_ic_type == ODM_RTL8723B)
63 configure_txpower_track_8723b(config);
67 if (dm->support_ic_type == ODM_RTL8814A)
68 configure_txpower_track_8814a(config);
72 if (dm->support_ic_type == ODM_RTL8703B)
73 configure_txpower_track_8703b(config);
77 if (dm->support_ic_type == ODM_RTL8822B)
78 configure_txpower_track_8822b(config);
82 if (dm->support_ic_type == ODM_RTL8723D)
83 configure_txpower_track_8723d(config);
88 if (dm->support_ic_type == ODM_RTL8710B)
89 configure_txpower_track_8710b(config);
93 if (dm->support_ic_type == ODM_RTL8821C)
94 configure_txpower_track_8821c(config);
98 if (dm->support_ic_type == ODM_RTL8192F)
99 configure_txpower_track_8192f(config);
104 /* **********************************************************************
105 * <20121113, Kordan> This function should be called when tx_agc changed.
106 * Otherwise the previous compensation is gone, because we record the
107 * delta of temperature between two TxPowerTracking watch dogs.
109 * NOTE: If Tx BB swing or Tx scaling is varified during run-time, still
110 * need to call this function.
111 * ********************************************************************** */
113 odm_clear_txpowertracking_state(
117 PHAL_DATA_TYPE hal_data = GET_HAL_DATA((PADAPTER)(dm->adapter));
119 struct dm_rf_calibration_struct *cali_info = &(dm->rf_calibrate_info);
121 cali_info->bb_swing_idx_cck_base = cali_info->default_cck_index;
122 cali_info->bb_swing_idx_cck = cali_info->default_cck_index;
123 cali_info->CCK_index = 0;
125 for (p = RF_PATH_A; p < MAX_RF_PATH; ++p) {
126 cali_info->bb_swing_idx_ofdm_base[p] = cali_info->default_ofdm_index;
127 cali_info->bb_swing_idx_ofdm[p] = cali_info->default_ofdm_index;
128 cali_info->OFDM_index[p] = cali_info->default_ofdm_index;
130 cali_info->power_index_offset[p] = 0;
131 cali_info->delta_power_index[p] = 0;
132 cali_info->delta_power_index_last[p] = 0;
134 cali_info->absolute_ofdm_swing_idx[p] = 0; /* Initial Mix mode power tracking*/
135 cali_info->remnant_ofdm_swing_idx[p] = 0;
136 cali_info->kfree_offset[p] = 0;
139 cali_info->modify_tx_agc_flag_path_a = false; /*Initial at Modify Tx Scaling mode*/
140 cali_info->modify_tx_agc_flag_path_b = false; /*Initial at Modify Tx Scaling mode*/
141 cali_info->modify_tx_agc_flag_path_c = false; /*Initial at Modify Tx Scaling mode*/
142 cali_info->modify_tx_agc_flag_path_d = false; /*Initial at Modify Tx Scaling mode*/
143 cali_info->remnant_cck_swing_idx = 0;
144 cali_info->thermal_value = hal_data->eeprom_thermal_meter;
146 cali_info->modify_tx_agc_value_cck = 0; /* modify by Mingzhi.Guo */
147 cali_info->modify_tx_agc_value_ofdm = 0; /* modify by Mingzhi.Guo */
152 odm_txpowertracking_callback_thermal_meter(
153 #if (DM_ODM_SUPPORT_TYPE & ODM_AP)
160 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
161 HAL_DATA_TYPE *hal_data = GET_HAL_DATA(((PADAPTER)adapter));
162 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
163 struct dm_struct *dm = &hal_data->DM_OutSrc;
164 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
165 struct dm_struct *dm = &hal_data->odmpriv;
169 struct dm_rf_calibration_struct *cali_info = &(dm->rf_calibrate_info);
170 struct dm_iqk_info *iqk_info = &dm->IQK_info;
171 u8 thermal_value = 0, delta, delta_LCK, delta_IQK, p = 0, i = 0;
172 s8 diff_DPK[4] = {0};
173 u8 thermal_value_avg_count = 0;
174 u32 thermal_value_avg = 0, regc80, regcd0, regcd4, regab4, regc88, rege14, reg848,reg838, reg86c;
176 u8 OFDM_min_index = 0; /* OFDM BB Swing should be less than +3.0dB, which is required by Arthur */
177 u8 indexforchannel = 0; /* get_right_chnl_place_for_iqk(hal_data->current_channel) */
178 u8 power_tracking_type = hal_data->RfPowerTrackingType;
179 u8 xtal_offset_eanble = 0;
180 s8 thermal_value_temp = 0;
182 struct txpwrtrack_cfg c;
184 /* 4 1. The following TWO tables decide the final index of OFDM/CCK swing table. */
185 u8 *delta_swing_table_idx_tup_a = NULL;
186 u8 *delta_swing_table_idx_tdown_a = NULL;
187 u8 *delta_swing_table_idx_tup_b = NULL;
188 u8 *delta_swing_table_idx_tdown_b = NULL;
189 /*for 8814 add by Yu Chen*/
190 u8 *delta_swing_table_idx_tup_c = NULL;
191 u8 *delta_swing_table_idx_tdown_c = NULL;
192 u8 *delta_swing_table_idx_tup_d = NULL;
193 u8 *delta_swing_table_idx_tdown_d = NULL;
194 /*for Xtal Offset by James.Tung*/
195 s8 *delta_swing_table_xtal_up = NULL;
196 s8 *delta_swing_table_xtal_down = NULL;
198 /* 4 2. Initilization ( 7 steps in total ) */
200 configure_txpower_track(dm, &c);
202 (*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_a, (u8 **)&delta_swing_table_idx_tdown_a,
203 (u8 **)&delta_swing_table_idx_tup_b, (u8 **)&delta_swing_table_idx_tdown_b);
205 if (dm->support_ic_type & ODM_RTL8814A) /*for 8814 path C & D*/
206 (*c.get_delta_swing_table8814only)(dm, (u8 **)&delta_swing_table_idx_tup_c, (u8 **)&delta_swing_table_idx_tdown_c,
207 (u8 **)&delta_swing_table_idx_tup_d, (u8 **)&delta_swing_table_idx_tdown_d);
208 /* JJ ADD 20161014 */
209 if (dm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F)) /*for Xtal Offset*/
210 (*c.get_delta_swing_xtal_table)(dm, (s8 **)&delta_swing_table_xtal_up, (s8 **)&delta_swing_table_xtal_down);
213 cali_info->txpowertracking_callback_cnt++; /*cosa add for debug*/
214 cali_info->is_txpowertracking_init = true;
216 /*cali_info->txpowertrack_control = hal_data->txpowertrack_control;
217 <Kordan> We should keep updating the control variable according to HalData.
218 <Kordan> rf_calibrate_info.rega24 will be initialized when ODM HW configuring, but MP configures with para files. */
219 #if (DM_ODM_SUPPORT_TYPE & ODM_WIN)
221 cali_info->rega24 = 0x090e1317;
223 #elif (DM_ODM_SUPPORT_TYPE & ODM_CE)
224 if (*(dm->mp_mode) == true)
225 cali_info->rega24 = 0x090e1317;
228 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
229 "===>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",
230 cali_info->bb_swing_idx_cck_base, cali_info->bb_swing_idx_ofdm_base[RF_PATH_A], cali_info->default_ofdm_index);
232 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
233 "cali_info->txpowertrack_control=%d, hal_data->eeprom_thermal_meter %d\n", cali_info->txpowertrack_control, hal_data->eeprom_thermal_meter);
234 thermal_value = (u8)odm_get_rf_reg(dm, RF_PATH_A, c.thermal_reg_addr, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
236 thermal_value_temp = thermal_value + phydm_get_thermal_offset(dm);
238 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
239 "thermal_value_temp(%d) = thermal_value(%d) + power_time_thermal(%d)\n", thermal_value_temp, thermal_value, phydm_get_thermal_offset(dm));
241 if (thermal_value_temp > 63)
243 else if (thermal_value_temp < 0)
246 thermal_value = thermal_value_temp;
248 /*add log by zhao he, check c80/c94/c14/ca0 value*/
249 if (dm->support_ic_type == ODM_RTL8723D) {
250 regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
251 regcd0 = odm_get_bb_reg(dm, R_0xcd0, MASKDWORD);
252 regcd4 = odm_get_bb_reg(dm, R_0xcd4, MASKDWORD);
253 regab4 = odm_get_bb_reg(dm, R_0xab4, 0x000007FF);
254 RF_DBG(dm, DBG_RF_IQK, "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n", regc80, regcd0, regcd4, regab4);
257 /* JJ ADD 20161014 */
258 if (dm->support_ic_type == ODM_RTL8710B) {
259 regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
260 regcd0 = odm_get_bb_reg(dm, R_0xcd0, MASKDWORD);
261 regcd4 = odm_get_bb_reg(dm, R_0xcd4, MASKDWORD);
262 regab4 = odm_get_bb_reg(dm, R_0xab4, 0x000007FF);
263 RF_DBG(dm, DBG_RF_IQK, "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n", regc80, regcd0, regcd4, regab4);
265 /* Winnita add 20171205 */
266 if (dm->support_ic_type == ODM_RTL8192F) {
267 regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
268 regc88 = odm_get_bb_reg(dm, R_0xc88, MASKDWORD);
269 regab4 = odm_get_bb_reg(dm, R_0xab4, MASKDWORD);
270 rege14 = odm_get_bb_reg(dm, R_0xe14, MASKDWORD);
271 reg848 = odm_get_bb_reg(dm, R_0x848, MASKDWORD);
272 reg838 = odm_get_bb_reg(dm, R_0x838, MASKDWORD);
273 reg86c = odm_get_bb_reg(dm, R_0x86c, MASKDWORD);
274 RF_DBG(dm, DBG_RF_IQK, "0xc80 = 0x%x 0xc88 = 0x%x 0xab4 = 0x%x 0xe14 = 0x%x\n", regc80, regc88, regab4, rege14);
275 RF_DBG(dm, DBG_RF_IQK, "0x848 = 0x%x 0x838 = 0x%x 0x86c = 0x%x\n", reg848, reg838, reg86c);
278 if (!cali_info->txpowertrack_control)
281 if (hal_data->eeprom_thermal_meter == 0xff) {
282 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no pg, hal_data->eeprom_thermal_meter = 0x%x\n", hal_data->eeprom_thermal_meter);
286 /*4 3. Initialize ThermalValues of rf_calibrate_info*/
288 if (cali_info->is_reloadtxpowerindex)
289 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "reload ofdm index for band switch\n");
291 /*4 4. Calculate average thermal meter*/
293 cali_info->thermal_value_avg[cali_info->thermal_value_avg_index] = thermal_value;
294 cali_info->thermal_value_avg_index++;
295 if (cali_info->thermal_value_avg_index == c.average_thermal_num) /*Average times = c.average_thermal_num*/
296 cali_info->thermal_value_avg_index = 0;
298 for (i = 0; i < c.average_thermal_num; i++) {
299 if (cali_info->thermal_value_avg[i]) {
300 thermal_value_avg += cali_info->thermal_value_avg[i];
301 thermal_value_avg_count++;
305 if (thermal_value_avg_count) { /* Calculate Average thermal_value after average enough times */
306 thermal_value = (u8)(thermal_value_avg / thermal_value_avg_count);
307 cali_info->thermal_value_delta = thermal_value - hal_data->eeprom_thermal_meter;
308 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
309 "AVG Thermal Meter = 0x%X, EFUSE Thermal base = 0x%X\n", thermal_value, hal_data->eeprom_thermal_meter);
312 /* 4 5. Calculate delta, delta_LCK, delta_IQK. */
314 /* "delta" here is used to determine whether thermal value changes or not. */
315 delta = (thermal_value > cali_info->thermal_value) ? (thermal_value - cali_info->thermal_value) : (cali_info->thermal_value - thermal_value);
316 delta_LCK = (thermal_value > cali_info->thermal_value_lck) ? (thermal_value - cali_info->thermal_value_lck) : (cali_info->thermal_value_lck - thermal_value);
317 delta_IQK = (thermal_value > cali_info->thermal_value_iqk) ? (thermal_value - cali_info->thermal_value_iqk) : (cali_info->thermal_value_iqk - thermal_value);
319 if (cali_info->thermal_value_iqk == 0xff) { /*no PG, use thermal value for IQK*/
320 cali_info->thermal_value_iqk = thermal_value;
321 delta_IQK = (thermal_value > cali_info->thermal_value_iqk) ? (thermal_value - cali_info->thermal_value_iqk) : (cali_info->thermal_value_iqk - thermal_value);
322 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no PG, use thermal_value for IQK\n");
325 for (p = RF_PATH_A; p < c.rf_path_count; p++)
326 diff_DPK[p] = (s8)thermal_value - (s8)cali_info->dpk_thermal[p];
328 /*4 6. If necessary, do LCK.*/
330 if (!(dm->support_ic_type & ODM_RTL8821)) { /*no PG, do LCK at initial status*/
331 if (cali_info->thermal_value_lck == 0xff) {
332 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no PG, do LCK\n");
333 cali_info->thermal_value_lck = thermal_value;
335 /*Use RTLCK, so close power tracking driver LCK*/
336 if ((!(dm->support_ic_type & ODM_RTL8814A)) && (!(dm->support_ic_type & ODM_RTL8822B))) {
337 if (c.phy_lc_calibrate)
338 (*c.phy_lc_calibrate)(dm);
341 delta_LCK = (thermal_value > cali_info->thermal_value_lck) ? (thermal_value - cali_info->thermal_value_lck) : (cali_info->thermal_value_lck - thermal_value);
344 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", delta, delta_LCK, delta_IQK);
346 /* Wait sacn to do LCK by RF Jenyu*/
347 if( (*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden)) {
348 /* Delta temperature is equal to or larger than 20 centigrade.*/
349 if (delta_LCK >= c.threshold_iqk) {
350 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_LCK(%d) >= threshold_iqk(%d)\n", delta_LCK, c.threshold_iqk);
351 cali_info->thermal_value_lck = thermal_value;
353 /*Use RTLCK, so close power tracking driver LCK*/
354 if ((!(dm->support_ic_type & ODM_RTL8814A)) && (!(dm->support_ic_type & ODM_RTL8822B))) {
355 if (c.phy_lc_calibrate)
356 (*c.phy_lc_calibrate)(dm);
362 /*3 7. If necessary, move the index of swing table to adjust Tx power.*/
364 if (delta > 0 && cali_info->txpowertrack_control) {
365 /* "delta" here is used to record the absolute value of differrence. */
366 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
367 delta = thermal_value > hal_data->eeprom_thermal_meter ? (thermal_value - hal_data->eeprom_thermal_meter) : (hal_data->eeprom_thermal_meter - thermal_value);
369 delta = (thermal_value > dm->priv->pmib->dot11RFEntry.ther) ? (thermal_value - dm->priv->pmib->dot11RFEntry.ther) : (dm->priv->pmib->dot11RFEntry.ther - thermal_value);
371 if (delta >= TXPWR_TRACK_TABLE_SIZE)
372 delta = TXPWR_TRACK_TABLE_SIZE - 1;
374 /*4 7.1 The Final Power index = BaseIndex + power_index_offset*/
376 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
377 if (thermal_value > hal_data->eeprom_thermal_meter) {
379 if (thermal_value > dm->priv->pmib->dot11RFEntry.ther) {
382 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
383 cali_info->delta_power_index_last[p] = cali_info->delta_power_index[p]; /*recording poer index offset*/
386 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
387 "delta_swing_table_idx_tup_b[%d] = %d\n", delta, delta_swing_table_idx_tup_b[delta]);
389 cali_info->delta_power_index[p] = delta_swing_table_idx_tup_b[delta];
390 cali_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_b[delta]; /*Record delta swing for mix mode power tracking*/
391 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
392 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_B] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
396 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
397 "delta_swing_table_idx_tup_c[%d] = %d\n", delta, delta_swing_table_idx_tup_c[delta]);
399 cali_info->delta_power_index[p] = delta_swing_table_idx_tup_c[delta];
400 cali_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_c[delta]; /*Record delta swing for mix mode power tracking*/
401 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
402 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_C] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
406 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
407 "delta_swing_table_idx_tup_d[%d] = %d\n", delta, delta_swing_table_idx_tup_d[delta]);
409 cali_info->delta_power_index[p] = delta_swing_table_idx_tup_d[delta];
410 cali_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_d[delta]; /*Record delta swing for mix mode power tracking*/
411 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
412 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_D] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
416 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
417 "delta_swing_table_idx_tup_a[%d] = %d\n", delta, delta_swing_table_idx_tup_a[delta]);
419 cali_info->delta_power_index[p] = delta_swing_table_idx_tup_a[delta];
420 cali_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_a[delta]; /*Record delta swing for mix mode power tracking*/
421 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
422 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_A] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
426 /* JJ ADD 20161014 */
427 if (dm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F)) {
428 /*Save xtal_offset from Xtal table*/
429 cali_info->xtal_offset_last = cali_info->xtal_offset; /*recording last Xtal offset*/
430 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
431 "[Xtal] delta_swing_table_xtal_up[%d] = %d\n", delta, delta_swing_table_xtal_up[delta]);
432 cali_info->xtal_offset = delta_swing_table_xtal_up[delta];
434 if (cali_info->xtal_offset_last == cali_info->xtal_offset)
435 xtal_offset_eanble = 0;
437 xtal_offset_eanble = 1;
441 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
442 cali_info->delta_power_index_last[p] = cali_info->delta_power_index[p]; /*recording poer index offset*/
446 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
447 "delta_swing_table_idx_tdown_b[%d] = %d\n", delta, delta_swing_table_idx_tdown_b[delta]);
448 cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_b[delta];
449 cali_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_b[delta]; /*Record delta swing for mix mode power tracking*/
450 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
451 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_B] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
455 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
456 "delta_swing_table_idx_tdown_c[%d] = %d\n", delta, delta_swing_table_idx_tdown_c[delta]);
457 cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_c[delta];
458 cali_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_c[delta]; /*Record delta swing for mix mode power tracking*/
459 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
460 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_C] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
464 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
465 "delta_swing_table_idx_tdown_d[%d] = %d\n", delta, delta_swing_table_idx_tdown_d[delta]);
466 cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_d[delta];
467 cali_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_d[delta]; /*Record delta swing for mix mode power tracking*/
468 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
469 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_D] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
473 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
474 "delta_swing_table_idx_tdown_a[%d] = %d\n", delta, delta_swing_table_idx_tdown_a[delta]);
475 cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_a[delta];
476 cali_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_a[delta]; /*Record delta swing for mix mode power tracking*/
477 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
478 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_A] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
482 /* JJ ADD 20161014 */
483 if (dm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F)) {
484 /*Save xtal_offset from Xtal table*/
485 cali_info->xtal_offset_last = cali_info->xtal_offset; /*recording last Xtal offset*/
486 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
487 "[Xtal] delta_swing_table_xtal_down[%d] = %d\n", delta, delta_swing_table_xtal_down[delta]);
488 cali_info->xtal_offset = delta_swing_table_xtal_down[delta];
490 if (cali_info->xtal_offset_last == cali_info->xtal_offset)
491 xtal_offset_eanble = 0;
493 xtal_offset_eanble = 1;
498 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
499 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
500 "\n\n=========================== [path-%d] Calculating power_index_offset===========================\n", p);
502 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*/
503 cali_info->power_index_offset[p] = 0;
505 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*/
507 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
508 "[path-%d] power_index_offset(%d) = delta_power_index(%d) - delta_power_index_last(%d)\n", p, cali_info->power_index_offset[p], cali_info->delta_power_index[p], cali_info->delta_power_index_last[p]);
510 cali_info->OFDM_index[p] = cali_info->bb_swing_idx_ofdm_base[p] + cali_info->power_index_offset[p];
511 cali_info->CCK_index = cali_info->bb_swing_idx_cck_base + cali_info->power_index_offset[p];
513 cali_info->bb_swing_idx_cck = cali_info->CCK_index;
514 cali_info->bb_swing_idx_ofdm[p] = cali_info->OFDM_index[p];
516 /*************Print BB Swing base and index Offset*************/
518 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
519 "The 'CCK' final index(%d) = BaseIndex(%d) + power_index_offset(%d)\n", cali_info->bb_swing_idx_cck, cali_info->bb_swing_idx_cck_base, cali_info->power_index_offset[p]);
520 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
521 "The 'OFDM' final index(%d) = BaseIndex[%d](%d) + power_index_offset(%d)\n", cali_info->bb_swing_idx_ofdm[p], p, cali_info->bb_swing_idx_ofdm_base[p], cali_info->power_index_offset[p]);
523 /*4 7.1 Handle boundary conditions of index.*/
525 if (cali_info->OFDM_index[p] > c.swing_table_size_ofdm - 1)
526 cali_info->OFDM_index[p] = c.swing_table_size_ofdm - 1;
527 else if (cali_info->OFDM_index[p] <= OFDM_min_index)
528 cali_info->OFDM_index[p] = OFDM_min_index;
531 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
532 "\n\n========================================================================================================\n");
534 if (cali_info->CCK_index > c.swing_table_size_cck - 1)
535 cali_info->CCK_index = c.swing_table_size_cck - 1;
536 else if (cali_info->CCK_index <= 0)
537 cali_info->CCK_index = 0;
539 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
540 "The thermal meter is unchanged or TxPowerTracking OFF(%d): thermal_value: %d, cali_info->thermal_value: %d\n",
541 cali_info->txpowertrack_control, thermal_value, cali_info->thermal_value);
543 for (p = RF_PATH_A; p < c.rf_path_count; p++)
544 cali_info->power_index_offset[p] = 0;
547 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
548 "TxPowerTracking: [CCK] Swing Current index: %d, Swing base index: %d\n",
549 cali_info->CCK_index, cali_info->bb_swing_idx_cck_base); /*Print Swing base & current*/
551 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
552 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
553 "TxPowerTracking: [OFDM] Swing Current index: %d, Swing base index[%d]: %d\n",
554 cali_info->OFDM_index[p], p, cali_info->bb_swing_idx_ofdm_base[p]);
557 if ((dm->support_ic_type & ODM_RTL8814A)) {
558 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "power_tracking_type=%d\n", power_tracking_type);
560 if (power_tracking_type == 0) {
561 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
562 for (p = RF_PATH_A; p < c.rf_path_count; p++)
563 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
564 } else if (power_tracking_type == 1) {
565 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX(2G) TSSI(5G) MODE**********\n");
566 for (p = RF_PATH_A; p < c.rf_path_count; p++)
567 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_2G_TSSI_5G_MODE, p, 0);
568 } else if (power_tracking_type == 2) {
569 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX(5G) TSSI(2G)MODE**********\n");
570 for (p = RF_PATH_A; p < c.rf_path_count; p++)
571 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_5G_TSSI_2G_MODE, p, 0);
572 } else if (power_tracking_type == 3) {
573 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking TSSI MODE**********\n");
574 for (p = RF_PATH_A; p < c.rf_path_count; p++)
575 (*c.odm_tx_pwr_track_set_pwr)(dm, TSSI_MODE, p, 0);
577 cali_info->thermal_value = thermal_value; /*Record last Power Tracking Thermal value*/
579 } else if ((cali_info->power_index_offset[RF_PATH_A] != 0 ||
580 cali_info->power_index_offset[RF_PATH_B] != 0 ||
581 cali_info->power_index_offset[RF_PATH_C] != 0 ||
582 cali_info->power_index_offset[RF_PATH_D] != 0) &&
583 cali_info->txpowertrack_control && (hal_data->eeprom_thermal_meter != 0xff)) {
584 /* 4 7.2 Configure the Swing Table to adjust Tx Power. */
586 cali_info->is_tx_power_changed = true; /*Always true after Tx Power is adjusted by power tracking.*/
588 /* 2012/04/23 MH According to Luke's suggestion, we can not write BB digital */
589 /* to increase TX power. Otherwise, EVM will be bad. */
591 /* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
592 if (thermal_value > cali_info->thermal_value) {
593 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
594 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
595 "Temperature Increasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
596 p, cali_info->power_index_offset[p], delta, thermal_value, hal_data->eeprom_thermal_meter, cali_info->thermal_value);
598 } else if (thermal_value < cali_info->thermal_value) { /*Low temperature*/
599 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
600 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
601 "Temperature Decreasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
602 p, cali_info->power_index_offset[p], delta, thermal_value, hal_data->eeprom_thermal_meter, cali_info->thermal_value);
606 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
607 if (thermal_value > hal_data->eeprom_thermal_meter)
609 if (thermal_value > dm->priv->pmib->dot11RFEntry.ther)
612 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
613 "Temperature(%d) higher than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
615 if (dm->support_ic_type == ODM_RTL8188E || dm->support_ic_type == ODM_RTL8192E || dm->support_ic_type == ODM_RTL8821 ||
616 dm->support_ic_type == ODM_RTL8812 || dm->support_ic_type == ODM_RTL8723B || dm->support_ic_type == ODM_RTL8814A ||
617 dm->support_ic_type == ODM_RTL8703B || dm->support_ic_type == ODM_RTL8188F || dm->support_ic_type == ODM_RTL8822B ||
618 dm->support_ic_type == ODM_RTL8723D || dm->support_ic_type == ODM_RTL8821C || dm->support_ic_type == ODM_RTL8710B ||
619 dm->support_ic_type == ODM_RTL8192F) {
621 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
622 for (p = RF_PATH_A; p < c.rf_path_count; p++)
623 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
625 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking BBSWING_MODE**********\n");
626 for (p = RF_PATH_A; p < c.rf_path_count; p++)
627 (*c.odm_tx_pwr_track_set_pwr)(dm, BBSWING, p, indexforchannel);
630 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
631 "Temperature(%d) lower than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
633 if (dm->support_ic_type == ODM_RTL8188E || dm->support_ic_type == ODM_RTL8192E || dm->support_ic_type == ODM_RTL8821 ||
634 dm->support_ic_type == ODM_RTL8812 || dm->support_ic_type == ODM_RTL8723B || dm->support_ic_type == ODM_RTL8814A ||
635 dm->support_ic_type == ODM_RTL8703B || dm->support_ic_type == ODM_RTL8188F || dm->support_ic_type == ODM_RTL8822B ||
636 dm->support_ic_type == ODM_RTL8723D || dm->support_ic_type == ODM_RTL8821C || dm->support_ic_type == ODM_RTL8710B ||
637 dm->support_ic_type == ODM_RTL8192F) {
638 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
639 for (p = RF_PATH_A; p < c.rf_path_count; p++)
640 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, indexforchannel);
642 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking BBSWING_MODE**********\n");
643 for (p = RF_PATH_A; p < c.rf_path_count; p++)
644 (*c.odm_tx_pwr_track_set_pwr)(dm, BBSWING, p, indexforchannel);
649 cali_info->bb_swing_idx_cck_base = cali_info->bb_swing_idx_cck; /*Record last time Power Tracking result as base.*/
650 for (p = RF_PATH_A; p < c.rf_path_count; p++)
651 cali_info->bb_swing_idx_ofdm_base[p] = cali_info->bb_swing_idx_ofdm[p];
653 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
654 "cali_info->thermal_value = %d thermal_value= %d\n", cali_info->thermal_value, thermal_value);
656 cali_info->thermal_value = thermal_value; /*Record last Power Tracking Thermal value*/
661 if (dm->support_ic_type == ODM_RTL8703B || dm->support_ic_type == ODM_RTL8723D ||
662 dm->support_ic_type == ODM_RTL8192F || dm->support_ic_type == ODM_RTL8710B) {/* JJ ADD 20161014 */
664 if (xtal_offset_eanble != 0 && cali_info->txpowertrack_control && (hal_data->eeprom_thermal_meter != 0xff)) {
666 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter Xtal Tracking**********\n");
668 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
669 if (thermal_value > hal_data->eeprom_thermal_meter) {
671 if (thermal_value > dm->priv->pmib->dot11RFEntry.ther) {
673 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
674 "Temperature(%d) higher than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
675 (*c.odm_txxtaltrack_set_xtal)(dm);
677 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
678 "Temperature(%d) lower than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
679 (*c.odm_txxtaltrack_set_xtal)(dm);
682 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********End Xtal Tracking**********\n");
685 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
687 /* Wait sacn to do IQK by RF Jenyu*/
688 if ((*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden)) {
689 if (!IS_HARDWARE_TYPE_8723B(adapter)) {
690 /*Delta temperature is equal to or larger than 20 centigrade (When threshold is 8).*/
691 if (delta_IQK >= c.threshold_iqk) {
692 cali_info->thermal_value_iqk = thermal_value;
693 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_IQK(%d) >= threshold_iqk(%d)\n", delta_IQK, c.threshold_iqk);
694 if (!cali_info->is_iqk_in_progress)
695 (*c.do_iqk)(dm, delta_IQK, thermal_value, 8);
699 if (cali_info->dpk_thermal[RF_PATH_A] != 0) {
700 if (diff_DPK[RF_PATH_A] >= c.threshold_dpk) {
701 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
702 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));
703 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
704 } else if ((diff_DPK[RF_PATH_A] <= -1 * c.threshold_dpk)) {
705 s32 value = 0x20 + (diff_DPK[RF_PATH_A] / c.threshold_dpk);
707 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
708 odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value);
709 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
711 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
712 odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0);
713 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
716 if (cali_info->dpk_thermal[RF_PATH_B] != 0) {
717 if (diff_DPK[RF_PATH_B] >= c.threshold_dpk) {
718 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
719 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));
720 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
721 } else if ((diff_DPK[RF_PATH_B] <= -1 * c.threshold_dpk)) {
722 s32 value = 0x20 + (diff_DPK[RF_PATH_B] / c.threshold_dpk);
724 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
725 odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value);
726 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
728 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
729 odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0);
730 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
736 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "<===odm_txpowertracking_callback_thermal_meter\n");
738 cali_info->tx_powercount = 0;
743 /* 3============================================================
745 * 3============================================================ */
748 odm_reset_iqk_result(
754 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
755 u8 odm_get_right_chnl_place_for_iqk(u8 chnl)
757 u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
758 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, 161, 163, 165
764 for (place = 14; place < sizeof(channel_all); place++) {
765 if (channel_all[place] == chnl)
779 void *adapter = dm->adapter;
780 struct dm_iqk_info *iqk_info = &dm->IQK_info;
782 RF_DBG(dm, DBG_RF_IQK, "=>%s\n",__FUNCTION__);
784 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
785 if (*dm->is_fcs_mode_enable)
789 if ((dm->is_linked) && (!iqk_info->rfk_forbidden)) {
790 RF_DBG(dm, DBG_RF_IQK, "interval=%d ch=%d prech=%d scan=%s\n", dm->linked_interval,
791 *dm->channel, dm->pre_channel, *dm->is_scan_in_process == TRUE ? "TRUE":"FALSE");
793 if (*dm->channel != dm->pre_channel) {
794 dm->pre_channel = *dm->channel;
795 dm->linked_interval = 0;
798 if ((dm->linked_interval < 3) && (!*dm->is_scan_in_process))
799 dm->linked_interval++;
801 if (dm->linked_interval == 2)
802 PHY_IQCalibrate(adapter, false);
804 dm->linked_interval = 0;
806 RF_DBG(dm, DBG_RF_IQK, "<=%s interval=%d ch=%d prech=%d scan=%s\n", __FUNCTION__, dm->linked_interval,
807 *dm->channel, dm->pre_channel, *dm->is_scan_in_process == TRUE?"TRUE":"FALSE");
810 void phydm_rf_init(struct dm_struct *dm)
813 odm_txpowertracking_init(dm);
815 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
816 odm_clear_txpowertracking_state(dm);
819 #if (DM_ODM_SUPPORT_TYPE & (ODM_AP))
820 #if (RTL8814A_SUPPORT == 1)
821 if (dm->support_ic_type & ODM_RTL8814A)
822 phy_iq_calibrate_8814a_init(dm);
828 void phydm_rf_watchdog(struct dm_struct *dm)
831 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
832 odm_txpowertracking_check(dm);
833 if (dm->support_ic_type & ODM_IC_11AC_SERIES)
834 odm_iq_calibrate(dm);