1 /******************************************************************************
3 * Copyright(c) 2007 - 2016 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 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
26 #include "mp_precomp.h"
27 #include "phydm_precomp.h"
29 #define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, \
32 for (_offset = 0; _offset < _size; _offset++) { \
33 if (_delta_thermal < \
34 thermal_threshold[_direction][_offset]) { \
40 if (_offset >= _size) \
41 _offset = _size - 1; \
44 static inline void phydm_set_calibrate_info_up(
45 struct phy_dm_struct *dm, struct txpwrtrack_cfg *c, u8 delta,
46 struct dm_rf_calibration_struct *cali_info,
47 u8 *delta_swing_table_idx_tup_a, u8 *delta_swing_table_idx_tup_b,
48 u8 *delta_swing_table_idx_tup_c, u8 *delta_swing_table_idx_tup_d)
52 for (p = ODM_RF_PATH_A; p < c->rf_path_count; p++) {
53 cali_info->delta_power_index_last[p] =
54 cali_info->delta_power_index
55 [p]; /*recording poer index offset*/
58 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
59 "delta_swing_table_idx_tup_b[%d] = %d\n",
60 delta, delta_swing_table_idx_tup_b[delta]);
62 cali_info->delta_power_index[p] =
63 delta_swing_table_idx_tup_b[delta];
64 /*Record delta swing for mix mode pwr tracking*/
65 cali_info->absolute_ofdm_swing_idx[p] =
66 delta_swing_table_idx_tup_b[delta];
68 dm, ODM_COMP_TX_PWR_TRACK,
69 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_B] = %d\n",
70 cali_info->absolute_ofdm_swing_idx[p]);
74 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
75 "delta_swing_table_idx_tup_c[%d] = %d\n",
76 delta, delta_swing_table_idx_tup_c[delta]);
78 cali_info->delta_power_index[p] =
79 delta_swing_table_idx_tup_c[delta];
80 /*Record delta swing for mix mode pwr tracking*/
81 cali_info->absolute_ofdm_swing_idx[p] =
82 delta_swing_table_idx_tup_c[delta];
84 dm, ODM_COMP_TX_PWR_TRACK,
85 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_C] = %d\n",
86 cali_info->absolute_ofdm_swing_idx[p]);
90 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
91 "delta_swing_table_idx_tup_d[%d] = %d\n",
92 delta, delta_swing_table_idx_tup_d[delta]);
94 cali_info->delta_power_index[p] =
95 delta_swing_table_idx_tup_d[delta];
96 /*Record delta swing for mix mode pwr tracking*/
97 cali_info->absolute_ofdm_swing_idx[p] =
98 delta_swing_table_idx_tup_d[delta];
100 dm, ODM_COMP_TX_PWR_TRACK,
101 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_D] = %d\n",
102 cali_info->absolute_ofdm_swing_idx[p]);
106 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
107 "delta_swing_table_idx_tup_a[%d] = %d\n",
108 delta, delta_swing_table_idx_tup_a[delta]);
110 cali_info->delta_power_index[p] =
111 delta_swing_table_idx_tup_a[delta];
112 /*Record delta swing for mix mode pwr tracking*/
113 cali_info->absolute_ofdm_swing_idx[p] =
114 delta_swing_table_idx_tup_a[delta];
116 dm, ODM_COMP_TX_PWR_TRACK,
117 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_A] = %d\n",
118 cali_info->absolute_ofdm_swing_idx[p]);
124 static inline void phydm_set_calibrate_info_down(
125 struct phy_dm_struct *dm, struct txpwrtrack_cfg *c, u8 delta,
126 struct dm_rf_calibration_struct *cali_info,
127 u8 *delta_swing_table_idx_tdown_a, u8 *delta_swing_table_idx_tdown_b,
128 u8 *delta_swing_table_idx_tdown_c, u8 *delta_swing_table_idx_tdown_d)
132 for (p = ODM_RF_PATH_A; p < c->rf_path_count; p++) {
133 cali_info->delta_power_index_last[p] =
134 cali_info->delta_power_index
135 [p]; /*recording poer index offset*/
139 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
140 "delta_swing_table_idx_tdown_b[%d] = %d\n",
142 delta_swing_table_idx_tdown_b[delta]);
143 cali_info->delta_power_index[p] =
144 -1 * delta_swing_table_idx_tdown_b[delta];
145 /*Record delta swing for mix mode pwr tracking*/
146 cali_info->absolute_ofdm_swing_idx[p] =
147 -1 * delta_swing_table_idx_tdown_b[delta];
149 dm, ODM_COMP_TX_PWR_TRACK,
150 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_B] = %d\n",
151 cali_info->absolute_ofdm_swing_idx[p]);
155 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
156 "delta_swing_table_idx_tdown_c[%d] = %d\n",
158 delta_swing_table_idx_tdown_c[delta]);
159 cali_info->delta_power_index[p] =
160 -1 * delta_swing_table_idx_tdown_c[delta];
161 /*Record delta swing for mix mode pwr tracking*/
162 cali_info->absolute_ofdm_swing_idx[p] =
163 -1 * delta_swing_table_idx_tdown_c[delta];
165 dm, ODM_COMP_TX_PWR_TRACK,
166 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_C] = %d\n",
167 cali_info->absolute_ofdm_swing_idx[p]);
171 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
172 "delta_swing_table_idx_tdown_d[%d] = %d\n",
174 delta_swing_table_idx_tdown_d[delta]);
175 cali_info->delta_power_index[p] =
176 -1 * delta_swing_table_idx_tdown_d[delta];
177 /*Record delta swing for mix mode pwr tracking*/
178 cali_info->absolute_ofdm_swing_idx[p] =
179 -1 * delta_swing_table_idx_tdown_d[delta];
181 dm, ODM_COMP_TX_PWR_TRACK,
182 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_D] = %d\n",
183 cali_info->absolute_ofdm_swing_idx[p]);
187 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
188 "delta_swing_table_idx_tdown_a[%d] = %d\n",
190 delta_swing_table_idx_tdown_a[delta]);
191 cali_info->delta_power_index[p] =
192 -1 * delta_swing_table_idx_tdown_a[delta];
193 /*Record delta swing for mix mode pwr tracking*/
194 cali_info->absolute_ofdm_swing_idx[p] =
195 -1 * delta_swing_table_idx_tdown_a[delta];
197 dm, ODM_COMP_TX_PWR_TRACK,
198 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[ODM_RF_PATH_A] = %d\n",
199 cali_info->absolute_ofdm_swing_idx[p]);
205 static inline void phydm_odm_tx_power_set(struct phy_dm_struct *dm,
206 struct txpwrtrack_cfg *c,
207 u8 indexforchannel, u8 flag)
211 if (dm->support_ic_type == ODM_RTL8188E ||
212 dm->support_ic_type == ODM_RTL8192E ||
213 dm->support_ic_type == ODM_RTL8821 ||
214 dm->support_ic_type == ODM_RTL8812 ||
215 dm->support_ic_type == ODM_RTL8723B ||
216 dm->support_ic_type == ODM_RTL8814A ||
217 dm->support_ic_type == ODM_RTL8703B ||
218 dm->support_ic_type == ODM_RTL8188F ||
219 dm->support_ic_type == ODM_RTL8822B ||
220 dm->support_ic_type == ODM_RTL8723D ||
221 dm->support_ic_type == ODM_RTL8821C ||
222 dm->support_ic_type == ODM_RTL8710B) { /* JJ ADD 20161014 */
225 dm, ODM_COMP_TX_PWR_TRACK,
226 "**********Enter POWER Tracking MIX_MODE**********\n");
227 for (p = ODM_RF_PATH_A; p < c->rf_path_count; p++) {
229 (*c->odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
232 (*c->odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
237 dm, ODM_COMP_TX_PWR_TRACK,
238 "**********Enter POWER Tracking BBSWING_MODE**********\n");
239 for (p = ODM_RF_PATH_A; p < c->rf_path_count; p++)
240 (*c->odm_tx_pwr_track_set_pwr)(dm, BBSWING, p,
245 void configure_txpower_track(void *dm_void, struct txpwrtrack_cfg *config)
247 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
249 /* JJ ADD 20161014 */
251 if (dm->support_ic_type == ODM_RTL8822B)
252 configure_txpower_track_8822b(config);
255 /* **********************************************************************
256 * <20121113, Kordan> This function should be called when tx_agc changed.
257 * Otherwise the previous compensation is gone, because we record the
258 * delta of temperature between two TxPowerTracking watch dogs.
260 * NOTE: If Tx BB swing or Tx scaling is varified during run-time, still
261 * need to call this function.
262 * ***********************************************************************/
263 void odm_clear_txpowertracking_state(void *dm_void)
265 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
266 struct rtl_priv *rtlpriv = (struct rtl_priv *)dm->adapter;
267 struct rtl_efuse *rtlefu = rtl_efuse(rtlpriv);
269 struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
271 cali_info->bb_swing_idx_cck_base = cali_info->default_cck_index;
272 cali_info->bb_swing_idx_cck = cali_info->default_cck_index;
273 dm->rf_calibrate_info.CCK_index = 0;
275 for (p = ODM_RF_PATH_A; p < MAX_RF_PATH; ++p) {
276 cali_info->bb_swing_idx_ofdm_base[p] =
277 cali_info->default_ofdm_index;
278 cali_info->bb_swing_idx_ofdm[p] = cali_info->default_ofdm_index;
279 cali_info->OFDM_index[p] = cali_info->default_ofdm_index;
281 cali_info->power_index_offset[p] = 0;
282 cali_info->delta_power_index[p] = 0;
283 cali_info->delta_power_index_last[p] = 0;
285 cali_info->absolute_ofdm_swing_idx[p] =
286 0; /* Initial Mix mode power tracking*/
287 cali_info->remnant_ofdm_swing_idx[p] = 0;
288 cali_info->kfree_offset[p] = 0;
291 cali_info->modify_tx_agc_flag_path_a =
292 false; /*Initial at Modify Tx Scaling mode*/
293 cali_info->modify_tx_agc_flag_path_b =
294 false; /*Initial at Modify Tx Scaling mode*/
295 cali_info->modify_tx_agc_flag_path_c =
296 false; /*Initial at Modify Tx Scaling mode*/
297 cali_info->modify_tx_agc_flag_path_d =
298 false; /*Initial at Modify Tx Scaling mode*/
299 cali_info->remnant_cck_swing_idx = 0;
300 cali_info->thermal_value = rtlefu->eeprom_thermalmeter;
302 cali_info->modify_tx_agc_value_cck = 0; /* modify by Mingzhi.Guo */
303 cali_info->modify_tx_agc_value_ofdm = 0; /* modify by Mingzhi.Guo */
306 void odm_txpowertracking_callback_thermal_meter(void *dm_void)
308 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
309 struct rtl_priv *rtlpriv = (struct rtl_priv *)dm->adapter;
310 struct rtl_efuse *rtlefu = rtl_efuse(rtlpriv);
311 void *adapter = dm->adapter;
313 struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
315 u8 thermal_value = 0, delta, delta_LCK, delta_IQK, p = 0, i = 0;
316 s8 diff_DPK[4]; /* use 'for..loop' to initialize */
317 u8 thermal_value_avg_count = 0;
318 u32 thermal_value_avg = 0, regc80, regcd0, regcd4, regab4;
320 /* OFDM BB Swing should be less than +3.0dB (required by Arthur) */
321 u8 OFDM_min_index = 0;
322 /* get_right_chnl_place_for_iqk(hal_data->current_channel) */
323 u8 indexforchannel = 0;
324 u8 power_tracking_type = 0; /* no specify type */
325 u8 xtal_offset_eanble = 0;
327 struct txpwrtrack_cfg c;
329 /* 4 1. The following TWO tables decide the final index of
330 * OFDM/CCK swing table.
332 u8 *delta_swing_table_idx_tup_a = NULL;
333 u8 *delta_swing_table_idx_tdown_a = NULL;
334 u8 *delta_swing_table_idx_tup_b = NULL;
335 u8 *delta_swing_table_idx_tdown_b = NULL;
336 /*for 8814 add by Yu Chen*/
337 u8 *delta_swing_table_idx_tup_c = NULL;
338 u8 *delta_swing_table_idx_tdown_c = NULL;
339 u8 *delta_swing_table_idx_tup_d = NULL;
340 u8 *delta_swing_table_idx_tdown_d = NULL;
341 /*for Xtal Offset by James.Tung*/
342 s8 *delta_swing_table_xtal_up = NULL;
343 s8 *delta_swing_table_xtal_down = NULL;
345 /* 4 2. Initialization ( 7 steps in total ) */
347 configure_txpower_track(dm, &c);
349 (*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_a,
350 (u8 **)&delta_swing_table_idx_tdown_a,
351 (u8 **)&delta_swing_table_idx_tup_b,
352 (u8 **)&delta_swing_table_idx_tdown_b);
354 if (dm->support_ic_type & ODM_RTL8814A) /*for 8814 path C & D*/
355 (*c.get_delta_swing_table8814only)(
356 dm, (u8 **)&delta_swing_table_idx_tup_c,
357 (u8 **)&delta_swing_table_idx_tdown_c,
358 (u8 **)&delta_swing_table_idx_tup_d,
359 (u8 **)&delta_swing_table_idx_tdown_d);
360 /* JJ ADD 20161014 */
361 if (dm->support_ic_type &
362 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B)) /*for Xtal Offset*/
363 (*c.get_delta_swing_xtal_table)(
364 dm, (s8 **)&delta_swing_table_xtal_up,
365 (s8 **)&delta_swing_table_xtal_down);
367 cali_info->txpowertracking_callback_cnt++; /*cosa add for debug*/
368 cali_info->is_txpowertracking_init = true;
370 /*cali_info->txpowertrack_control = hal_data->txpowertrack_control;
371 *<Kordan> We should keep updating ctrl variable according to HalData.
372 *<Kordan> rf_calibrate_info.rega24 will be initialized when
373 *ODM HW configuring, but MP configures with para files.
376 cali_info->rega24 = 0x090e1317;
379 dm, ODM_COMP_TX_PWR_TRACK,
380 "===>%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",
381 __func__, cali_info->bb_swing_idx_cck_base,
382 cali_info->bb_swing_idx_ofdm_base[ODM_RF_PATH_A],
383 cali_info->default_ofdm_index);
386 dm, ODM_COMP_TX_PWR_TRACK,
387 "cali_info->txpowertrack_control=%d, rtlefu->eeprom_thermalmeter %d\n",
388 cali_info->txpowertrack_control, rtlefu->eeprom_thermalmeter);
391 (u8)odm_get_rf_reg(dm, ODM_RF_PATH_A, c.thermal_reg_addr,
392 0xfc00); /* 0x42: RF Reg[15:10] 88E */
394 /*add log by zhao he, check c80/c94/c14/ca0 value*/
395 if (dm->support_ic_type == ODM_RTL8723D) {
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);
405 /* JJ ADD 20161014 */
406 if (dm->support_ic_type == ODM_RTL8710B) {
407 regc80 = odm_get_bb_reg(dm, 0xc80, MASKDWORD);
408 regcd0 = odm_get_bb_reg(dm, 0xcd0, MASKDWORD);
409 regcd4 = odm_get_bb_reg(dm, 0xcd4, MASKDWORD);
410 regab4 = odm_get_bb_reg(dm, 0xab4, 0x000007FF);
412 dm, ODM_COMP_CALIBRATION,
413 "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n",
414 regc80, regcd0, regcd4, regab4);
417 if (!cali_info->txpowertrack_control)
420 /*4 3. Initialize ThermalValues of rf_calibrate_info*/
422 if (cali_info->is_reloadtxpowerindex)
423 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
424 "reload ofdm index for band switch\n");
426 /*4 4. Calculate average thermal meter*/
428 cali_info->thermal_value_avg[cali_info->thermal_value_avg_index] =
430 cali_info->thermal_value_avg_index++;
431 if (cali_info->thermal_value_avg_index ==
432 c.average_thermal_num) /*Average times = c.average_thermal_num*/
433 cali_info->thermal_value_avg_index = 0;
435 for (i = 0; i < c.average_thermal_num; i++) {
436 if (cali_info->thermal_value_avg[i]) {
437 thermal_value_avg += cali_info->thermal_value_avg[i];
438 thermal_value_avg_count++;
442 if (thermal_value_avg_count) {
443 /* Calculate Average thermal_value after average enough times */
445 (u8)(thermal_value_avg / thermal_value_avg_count);
446 cali_info->thermal_value_delta =
447 thermal_value - rtlefu->eeprom_thermalmeter;
449 dm, ODM_COMP_TX_PWR_TRACK,
450 "AVG Thermal Meter = 0x%X, EFUSE Thermal base = 0x%X\n",
451 thermal_value, rtlefu->eeprom_thermalmeter);
454 /* 4 5. Calculate delta, delta_LCK, delta_IQK. */
456 /* "delta" is used to determine whether thermal value changes or not*/
457 delta = (thermal_value > cali_info->thermal_value) ?
458 (thermal_value - cali_info->thermal_value) :
459 (cali_info->thermal_value - thermal_value);
460 delta_LCK = (thermal_value > cali_info->thermal_value_lck) ?
461 (thermal_value - cali_info->thermal_value_lck) :
462 (cali_info->thermal_value_lck - thermal_value);
463 delta_IQK = (thermal_value > cali_info->thermal_value_iqk) ?
464 (thermal_value - cali_info->thermal_value_iqk) :
465 (cali_info->thermal_value_iqk - thermal_value);
467 if (cali_info->thermal_value_iqk ==
468 0xff) { /*no PG, use thermal value for IQK*/
469 cali_info->thermal_value_iqk = thermal_value;
471 (thermal_value > cali_info->thermal_value_iqk) ?
472 (thermal_value - cali_info->thermal_value_iqk) :
473 (cali_info->thermal_value_iqk - thermal_value);
474 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
475 "no PG, use thermal_value for IQK\n");
478 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
479 diff_DPK[p] = (s8)thermal_value - (s8)cali_info->dpk_thermal[p];
481 /*4 6. If necessary, do LCK.*/
483 if (!(dm->support_ic_type &
484 ODM_RTL8821)) { /*no PG, do LCK at initial status*/
485 if (cali_info->thermal_value_lck == 0xff) {
486 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
488 cali_info->thermal_value_lck = thermal_value;
490 /*Use RTLCK, so close power tracking driver LCK*/
491 if (!(dm->support_ic_type & ODM_RTL8814A) &&
493 (*c.phy_lc_calibrate)(dm);
496 (thermal_value > cali_info->thermal_value_lck) ?
498 cali_info->thermal_value_lck) :
499 (cali_info->thermal_value_lck -
503 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
504 "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
505 delta, delta_LCK, delta_IQK);
507 /*Delta temperature is equal to or larger than 20 centigrade.*/
508 if (delta_LCK >= c.threshold_iqk) {
509 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
510 "delta_LCK(%d) >= threshold_iqk(%d)\n",
511 delta_LCK, c.threshold_iqk);
512 cali_info->thermal_value_lck = thermal_value;
514 /*Use RTLCK, so close power tracking driver LCK*/
515 if (!(dm->support_ic_type & ODM_RTL8814A) &&
517 (*c.phy_lc_calibrate)(dm);
521 /*3 7. If necessary, move the index of swing table to adjust Tx power.*/
523 if (delta > 0 && cali_info->txpowertrack_control) {
524 /* "delta" here is used to record the abs value of difference.*/
525 delta = thermal_value > rtlefu->eeprom_thermalmeter ?
526 (thermal_value - rtlefu->eeprom_thermalmeter) :
527 (rtlefu->eeprom_thermalmeter - thermal_value);
528 if (delta >= TXPWR_TRACK_TABLE_SIZE)
529 delta = TXPWR_TRACK_TABLE_SIZE - 1;
531 /*4 7.1 The Final Power index = BaseIndex + power_index_offset*/
533 if (thermal_value > rtlefu->eeprom_thermalmeter) {
534 phydm_set_calibrate_info_up(
535 dm, &c, delta, cali_info,
536 delta_swing_table_idx_tup_a,
537 delta_swing_table_idx_tup_b,
538 delta_swing_table_idx_tup_c,
539 delta_swing_table_idx_tup_d);
540 /* JJ ADD 20161014 */
541 if (dm->support_ic_type &
542 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B)) {
543 /*Save xtal_offset from Xtal table*/
545 /*recording last Xtal offset*/
546 cali_info->xtal_offset_last =
547 cali_info->xtal_offset;
549 dm, ODM_COMP_TX_PWR_TRACK,
550 "[Xtal] delta_swing_table_xtal_up[%d] = %d\n",
552 delta_swing_table_xtal_up[delta]);
553 cali_info->xtal_offset =
554 delta_swing_table_xtal_up[delta];
556 (cali_info->xtal_offset_last ==
557 cali_info->xtal_offset) ?
563 phydm_set_calibrate_info_down(
564 dm, &c, delta, cali_info,
565 delta_swing_table_idx_tdown_a,
566 delta_swing_table_idx_tdown_b,
567 delta_swing_table_idx_tdown_c,
568 delta_swing_table_idx_tdown_d);
569 /* JJ ADD 20161014 */
570 if (dm->support_ic_type &
571 (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B)) {
572 /*Save xtal_offset from Xtal table*/
574 /*recording last Xtal offset*/
575 cali_info->xtal_offset_last =
576 cali_info->xtal_offset;
578 dm, ODM_COMP_TX_PWR_TRACK,
579 "[Xtal] delta_swing_table_xtal_down[%d] = %d\n",
581 delta_swing_table_xtal_down[delta]);
582 cali_info->xtal_offset =
583 delta_swing_table_xtal_down[delta];
585 (cali_info->xtal_offset_last ==
586 cali_info->xtal_offset) ?
592 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) {
594 dm, ODM_COMP_TX_PWR_TRACK,
595 "\n\n=========================== [path-%d] Calculating power_index_offset===========================\n",
598 if (cali_info->delta_power_index[p] ==
599 cali_info->delta_power_index_last[p]) {
600 /* If Thermal value changes but lookup table
601 * value still the same
603 cali_info->power_index_offset[p] = 0;
605 /*Power idx diff between 2 times Pwr Tracking*/
606 cali_info->power_index_offset[p] =
607 cali_info->delta_power_index[p] -
608 cali_info->delta_power_index_last[p];
612 dm, ODM_COMP_TX_PWR_TRACK,
613 "[path-%d] power_index_offset(%d) = delta_power_index(%d) - delta_power_index_last(%d)\n",
614 p, cali_info->power_index_offset[p],
615 cali_info->delta_power_index[p],
616 cali_info->delta_power_index_last[p]);
618 cali_info->OFDM_index[p] =
619 cali_info->bb_swing_idx_ofdm_base[p] +
620 cali_info->power_index_offset[p];
621 cali_info->CCK_index =
622 cali_info->bb_swing_idx_cck_base +
623 cali_info->power_index_offset[p];
625 cali_info->bb_swing_idx_cck = cali_info->CCK_index;
626 cali_info->bb_swing_idx_ofdm[p] =
627 cali_info->OFDM_index[p];
629 /*******Print BB Swing base and index Offset**********/
632 dm, ODM_COMP_TX_PWR_TRACK,
633 "The 'CCK' final index(%d) = BaseIndex(%d) + power_index_offset(%d)\n",
634 cali_info->bb_swing_idx_cck,
635 cali_info->bb_swing_idx_cck_base,
636 cali_info->power_index_offset[p]);
638 dm, ODM_COMP_TX_PWR_TRACK,
639 "The 'OFDM' final index(%d) = BaseIndex[%d](%d) + power_index_offset(%d)\n",
640 cali_info->bb_swing_idx_ofdm[p], p,
641 cali_info->bb_swing_idx_ofdm_base[p],
642 cali_info->power_index_offset[p]);
644 /*4 7.1 Handle boundary conditions of index.*/
646 if (cali_info->OFDM_index[p] >
647 c.swing_table_size_ofdm - 1)
648 cali_info->OFDM_index[p] =
649 c.swing_table_size_ofdm - 1;
650 else if (cali_info->OFDM_index[p] <= OFDM_min_index)
651 cali_info->OFDM_index[p] = OFDM_min_index;
655 dm, ODM_COMP_TX_PWR_TRACK,
656 "\n\n========================================================================================================\n");
658 if (cali_info->CCK_index > c.swing_table_size_cck - 1)
659 cali_info->CCK_index = c.swing_table_size_cck - 1;
660 else if (cali_info->CCK_index <= 0)
661 cali_info->CCK_index = 0;
664 dm, ODM_COMP_TX_PWR_TRACK,
665 "The thermal meter is unchanged or TxPowerTracking OFF(%d): thermal_value: %d, cali_info->thermal_value: %d\n",
666 cali_info->txpowertrack_control, thermal_value,
667 cali_info->thermal_value);
669 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
670 cali_info->power_index_offset[p] = 0;
673 /*Print Swing base & current*/
675 dm, ODM_COMP_TX_PWR_TRACK,
676 "TxPowerTracking: [CCK] Swing Current index: %d, Swing base index: %d\n",
677 cali_info->CCK_index, cali_info->bb_swing_idx_cck_base);
679 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
681 dm, ODM_COMP_TX_PWR_TRACK,
682 "TxPowerTracking: [OFDM] Swing Current index: %d, Swing base index[%d]: %d\n",
683 cali_info->OFDM_index[p], p,
684 cali_info->bb_swing_idx_ofdm_base[p]);
686 if ((dm->support_ic_type & ODM_RTL8814A)) {
687 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
688 "power_tracking_type=%d\n", power_tracking_type);
690 if (power_tracking_type == 0) {
692 dm, ODM_COMP_TX_PWR_TRACK,
693 "**********Enter POWER Tracking MIX_MODE**********\n");
694 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
695 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
697 } else if (power_tracking_type == 1) {
699 dm, ODM_COMP_TX_PWR_TRACK,
700 "**********Enter POWER Tracking MIX(2G) TSSI(5G) MODE**********\n");
701 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
702 (*c.odm_tx_pwr_track_set_pwr)(
703 dm, MIX_2G_TSSI_5G_MODE, p, 0);
704 } else if (power_tracking_type == 2) {
706 dm, ODM_COMP_TX_PWR_TRACK,
707 "**********Enter POWER Tracking MIX(5G) TSSI(2G)MODE**********\n");
708 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
709 (*c.odm_tx_pwr_track_set_pwr)(
710 dm, MIX_5G_TSSI_2G_MODE, p, 0);
711 } else if (power_tracking_type == 3) {
713 dm, ODM_COMP_TX_PWR_TRACK,
714 "**********Enter POWER Tracking TSSI MODE**********\n");
715 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
716 (*c.odm_tx_pwr_track_set_pwr)(dm, TSSI_MODE, p,
719 /*Record last Power Tracking Thermal value*/
720 cali_info->thermal_value = thermal_value;
722 } else if ((cali_info->power_index_offset[ODM_RF_PATH_A] != 0 ||
723 cali_info->power_index_offset[ODM_RF_PATH_B] != 0 ||
724 cali_info->power_index_offset[ODM_RF_PATH_C] != 0 ||
725 cali_info->power_index_offset[ODM_RF_PATH_D] != 0) &&
726 cali_info->txpowertrack_control &&
727 (rtlefu->eeprom_thermalmeter != 0xff)) {
728 /* 4 7.2 Configure the Swing Table to adjust Tx Power. */
730 /*Always true after Tx Power is adjusted by power tracking.*/
731 cali_info->is_tx_power_changed = true;
732 /* 2012/04/23 MH According to Luke's suggestion, we can not
733 * write BB digital to increase TX power. Otherwise, EVM will
736 /* 2012/04/25 MH Add for tx power tracking to set tx power in
739 if (thermal_value > cali_info->thermal_value) {
740 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) {
741 /* print temperature increasing */
743 dm, ODM_COMP_TX_PWR_TRACK,
744 "Temperature Increasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
745 p, cali_info->power_index_offset[p],
746 delta, thermal_value,
747 rtlefu->eeprom_thermalmeter,
748 cali_info->thermal_value);
750 } else if (thermal_value <
751 cali_info->thermal_value) { /*Low temperature*/
752 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) {
753 /* print temperature decreasing */
755 dm, ODM_COMP_TX_PWR_TRACK,
756 "Temperature Decreasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
757 p, cali_info->power_index_offset[p],
758 delta, thermal_value,
759 rtlefu->eeprom_thermalmeter,
760 cali_info->thermal_value);
764 if (thermal_value > rtlefu->eeprom_thermalmeter) {
766 dm, ODM_COMP_TX_PWR_TRACK,
767 "Temperature(%d) higher than PG value(%d)\n",
768 thermal_value, rtlefu->eeprom_thermalmeter);
770 phydm_odm_tx_power_set(dm, &c, indexforchannel, 0);
773 dm, ODM_COMP_TX_PWR_TRACK,
774 "Temperature(%d) lower than PG value(%d)\n",
775 thermal_value, rtlefu->eeprom_thermalmeter);
776 phydm_odm_tx_power_set(dm, &c, indexforchannel, 1);
779 /*Record last time Power Tracking result as base.*/
780 cali_info->bb_swing_idx_cck_base = cali_info->bb_swing_idx_cck;
782 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
783 cali_info->bb_swing_idx_ofdm_base[p] =
784 cali_info->bb_swing_idx_ofdm[p];
787 dm, ODM_COMP_TX_PWR_TRACK,
788 "cali_info->thermal_value = %d thermal_value= %d\n",
789 cali_info->thermal_value, thermal_value);
791 /*Record last Power Tracking Thermal value*/
792 cali_info->thermal_value = thermal_value;
795 if (dm->support_ic_type == ODM_RTL8703B ||
796 dm->support_ic_type == ODM_RTL8723D ||
797 dm->support_ic_type == ODM_RTL8710B) { /* JJ ADD 20161014 */
799 if (xtal_offset_eanble != 0 &&
800 cali_info->txpowertrack_control &&
801 (rtlefu->eeprom_thermalmeter != 0xff)) {
803 dm, ODM_COMP_TX_PWR_TRACK,
804 "**********Enter Xtal Tracking**********\n");
806 if (thermal_value > rtlefu->eeprom_thermalmeter) {
808 dm, ODM_COMP_TX_PWR_TRACK,
809 "Temperature(%d) higher than PG value(%d)\n",
811 rtlefu->eeprom_thermalmeter);
812 (*c.odm_txxtaltrack_set_xtal)(dm);
815 dm, ODM_COMP_TX_PWR_TRACK,
816 "Temperature(%d) lower than PG value(%d)\n",
818 rtlefu->eeprom_thermalmeter);
819 (*c.odm_txxtaltrack_set_xtal)(dm);
822 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
823 "**********End Xtal Tracking**********\n");
826 if (!IS_HARDWARE_TYPE_8723B(adapter)) {
827 /* Delta temperature is equal to or larger than 20 centigrade
828 * (When threshold is 8).
830 if (delta_IQK >= c.threshold_iqk) {
831 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
832 "delta_IQK(%d) >= threshold_iqk(%d)\n",
833 delta_IQK, c.threshold_iqk);
834 if (!cali_info->is_iqk_in_progress)
835 (*c.do_iqk)(dm, delta_IQK, thermal_value, 8);
838 if (cali_info->dpk_thermal[ODM_RF_PATH_A] != 0) {
839 if (diff_DPK[ODM_RF_PATH_A] >= c.threshold_dpk) {
840 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
843 BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10),
844 (diff_DPK[ODM_RF_PATH_A] / c.threshold_dpk));
845 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
846 } else if ((diff_DPK[ODM_RF_PATH_A] <= -1 * c.threshold_dpk)) {
848 (diff_DPK[ODM_RF_PATH_A] / c.threshold_dpk);
850 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
851 odm_set_bb_reg(dm, 0xcc4, BIT(14) | BIT(13) | BIT(12) |
854 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
856 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
857 odm_set_bb_reg(dm, 0xcc4, BIT(14) | BIT(13) | BIT(12) |
860 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
863 if (cali_info->dpk_thermal[ODM_RF_PATH_B] != 0) {
864 if (diff_DPK[ODM_RF_PATH_B] >= c.threshold_dpk) {
865 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
868 BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10),
869 (diff_DPK[ODM_RF_PATH_B] / c.threshold_dpk));
870 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
871 } else if ((diff_DPK[ODM_RF_PATH_B] <= -1 * c.threshold_dpk)) {
873 (diff_DPK[ODM_RF_PATH_B] / c.threshold_dpk);
875 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
876 odm_set_bb_reg(dm, 0xec4, BIT(14) | BIT(13) | BIT(12) |
879 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
881 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
882 odm_set_bb_reg(dm, 0xec4, BIT(14) | BIT(13) | BIT(12) |
885 odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
889 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK, "<===%s\n", __func__);
891 cali_info->tx_powercount = 0;
894 /* 3============================================================
896 * 3============================================================
899 void odm_reset_iqk_result(void *dm_void) { return; }
901 u8 odm_get_right_chnl_place_for_iqk(u8 chnl)
903 u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
904 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
905 13, 14, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54,
906 56, 58, 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
907 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136,
908 138, 140, 149, 151, 153, 155, 157, 159, 161, 163, 165};
912 for (place = 14; place < sizeof(channel_all); place++) {
913 if (channel_all[place] == chnl)
920 static void odm_iq_calibrate(struct phy_dm_struct *dm)
922 void *adapter = dm->adapter;
924 if (IS_HARDWARE_TYPE_8812AU(adapter))
928 if ((*dm->channel != dm->pre_channel) &&
929 (!*dm->is_scan_in_process)) {
930 dm->pre_channel = *dm->channel;
931 dm->linked_interval = 0;
934 if (dm->linked_interval < 3)
935 dm->linked_interval++;
937 if (dm->linked_interval == 2) {
938 if (IS_HARDWARE_TYPE_8814A(adapter))
941 else if (IS_HARDWARE_TYPE_8822B(adapter))
942 phy_iq_calibrate_8822b(dm, false);
945 dm->linked_interval = 0;
949 void phydm_rf_init(void *dm_void)
951 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
953 odm_txpowertracking_init(dm);
955 odm_clear_txpowertracking_state(dm);
958 void phydm_rf_watchdog(void *dm_void)
960 struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
962 odm_txpowertracking_check(dm);
963 if (dm->support_ic_type & ODM_IC_11AC_SERIES)
964 odm_iq_calibrate(dm);