GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / staging / rtlwifi / phydm / halphyrf_ce.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2016  Realtek Corporation.
5  *
6  * Contact Information:
7  * wlanfae <wlanfae@realtek.com>
8  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
9  * Hsinchu 300, Taiwan.
10  *
11  * Larry Finger <Larry.Finger@lwfinger.net>
12  *
13  *****************************************************************************/
14
15 #include "mp_precomp.h"
16 #include "phydm_precomp.h"
17
18 #define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size,                \
19                                     _delta_thermal)                            \
20         do {                                                                   \
21                 for (_offset = 0; _offset < _size; _offset++) {                \
22                         if (_delta_thermal <                                   \
23                             thermal_threshold[_direction][_offset]) {          \
24                                 if (_offset != 0)                              \
25                                         _offset--;                             \
26                                 break;                                         \
27                         }                                                      \
28                 }                                                              \
29                 if (_offset >= _size)                                          \
30                         _offset = _size - 1;                                   \
31         } while (0)
32
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)
38 {
39         u8 p = 0;
40
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*/
45                 switch (p) {
46                 case ODM_RF_PATH_B:
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]);
50
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];
56                         ODM_RT_TRACE(
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]);
60                         break;
61
62                 case ODM_RF_PATH_C:
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]);
66
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];
72                         ODM_RT_TRACE(
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]);
76                         break;
77
78                 case ODM_RF_PATH_D:
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]);
82
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];
88                         ODM_RT_TRACE(
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]);
92                         break;
93
94                 default:
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]);
98
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];
104                         ODM_RT_TRACE(
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]);
108                         break;
109                 }
110         }
111 }
112
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)
118 {
119         u8 p = 0;
120
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*/
125
126                 switch (p) {
127                 case ODM_RF_PATH_B:
128                         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
129                                      "delta_swing_table_idx_tdown_b[%d] = %d\n",
130                                      delta,
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];
137                         ODM_RT_TRACE(
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]);
141                         break;
142
143                 case ODM_RF_PATH_C:
144                         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
145                                      "delta_swing_table_idx_tdown_c[%d] = %d\n",
146                                      delta,
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];
153                         ODM_RT_TRACE(
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]);
157                         break;
158
159                 case ODM_RF_PATH_D:
160                         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
161                                      "delta_swing_table_idx_tdown_d[%d] = %d\n",
162                                      delta,
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];
169                         ODM_RT_TRACE(
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]);
173                         break;
174
175                 default:
176                         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
177                                      "delta_swing_table_idx_tdown_a[%d] = %d\n",
178                                      delta,
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];
185                         ODM_RT_TRACE(
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]);
189                         break;
190                 }
191         }
192 }
193
194 static inline void phydm_odm_tx_power_set(struct phy_dm_struct *dm,
195                                           struct txpwrtrack_cfg *c,
196                                           u8 indexforchannel, u8 flag)
197 {
198         u8 p = 0;
199
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 */
212
213                 ODM_RT_TRACE(
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++) {
217                         if (flag == 0)
218                                 (*c->odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
219                                                                0);
220                         else
221                                 (*c->odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
222                                                                indexforchannel);
223                 }
224         } else {
225                 ODM_RT_TRACE(
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,
230                                                        indexforchannel);
231         }
232 }
233
234 void configure_txpower_track(void *dm_void, struct txpwrtrack_cfg *config)
235 {
236         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
237
238         /* JJ ADD 20161014 */
239
240         if (dm->support_ic_type == ODM_RTL8822B)
241                 configure_txpower_track_8822b(config);
242 }
243
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.
248  *
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)
253 {
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);
257         u8 p = 0;
258         struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
259
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;
263
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;
269
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;
273
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;
278         }
279
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;
290
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 */
293 }
294
295 void odm_txpowertracking_callback_thermal_meter(void *dm_void)
296 {
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;
301
302         struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
303
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;
308
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;
315
316         struct txpwrtrack_cfg c;
317
318         /* 4 1. The following TWO tables decide the final index of
319          *      OFDM/CCK swing table.
320          */
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;
333
334         /* 4 2. Initialization ( 7 steps in total ) */
335
336         configure_txpower_track(dm, &c);
337
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);
342
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);
355
356         cali_info->txpowertracking_callback_cnt++; /*cosa add for debug*/
357         cali_info->is_txpowertracking_init = true;
358
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.
363          */
364         if (dm->mp_mode)
365                 cali_info->rega24 = 0x090e1317;
366
367         ODM_RT_TRACE(
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);
373
374         ODM_RT_TRACE(
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);
378
379         thermal_value =
380                 (u8)odm_get_rf_reg(dm, ODM_RF_PATH_A, c.thermal_reg_addr,
381                                    0xfc00); /* 0x42: RF Reg[15:10] 88E */
382
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);
389                 ODM_RT_TRACE(
390                         dm, ODM_COMP_CALIBRATION,
391                         "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n",
392                         regc80, regcd0, regcd4, regab4);
393         }
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);
400                 ODM_RT_TRACE(
401                         dm, ODM_COMP_CALIBRATION,
402                         "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n",
403                         regc80, regcd0, regcd4, regab4);
404         }
405
406         if (!cali_info->txpowertrack_control)
407                 return;
408
409         /*4 3. Initialize ThermalValues of rf_calibrate_info*/
410
411         if (cali_info->is_reloadtxpowerindex)
412                 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
413                              "reload ofdm index for band switch\n");
414
415         /*4 4. Calculate average thermal meter*/
416
417         cali_info->thermal_value_avg[cali_info->thermal_value_avg_index] =
418                 thermal_value;
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;
423
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++;
428                 }
429         }
430
431         if (thermal_value_avg_count) {
432                 /* Calculate Average thermal_value after average enough times */
433                 thermal_value =
434                         (u8)(thermal_value_avg / thermal_value_avg_count);
435                 cali_info->thermal_value_delta =
436                         thermal_value - rtlefu->eeprom_thermalmeter;
437                 ODM_RT_TRACE(
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);
441         }
442
443         /* 4 5. Calculate delta, delta_LCK, delta_IQK. */
444
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);
455
456         if (cali_info->thermal_value_iqk ==
457             0xff) { /*no PG, use thermal value for IQK*/
458                 cali_info->thermal_value_iqk = thermal_value;
459                 delta_IQK =
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");
465         }
466
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];
469
470         /*4 6. If necessary, do LCK.*/
471
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,
476                                      "no PG, do LCK\n");
477                         cali_info->thermal_value_lck = thermal_value;
478
479                         /*Use RTLCK, so close power tracking driver LCK*/
480                         if (!(dm->support_ic_type & ODM_RTL8814A) &&
481                             c.phy_lc_calibrate)
482                                 (*c.phy_lc_calibrate)(dm);
483
484                         delta_LCK =
485                                 (thermal_value > cali_info->thermal_value_lck) ?
486                                         (thermal_value -
487                                          cali_info->thermal_value_lck) :
488                                         (cali_info->thermal_value_lck -
489                                          thermal_value);
490                 }
491
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);
495
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;
502
503                         /*Use RTLCK, so close power tracking driver LCK*/
504                         if (!(dm->support_ic_type & ODM_RTL8814A) &&
505                             c.phy_lc_calibrate)
506                                 (*c.phy_lc_calibrate)(dm);
507                 }
508         }
509
510         /*3 7. If necessary, move the index of swing table to adjust Tx power.*/
511
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;
519
520                 /*4 7.1 The Final Power index = BaseIndex + power_index_offset*/
521
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*/
533
534                                 /*recording last Xtal offset*/
535                                 cali_info->xtal_offset_last =
536                                         cali_info->xtal_offset;
537                                 ODM_RT_TRACE(
538                                         dm, ODM_COMP_TX_PWR_TRACK,
539                                         "[Xtal] delta_swing_table_xtal_up[%d] = %d\n",
540                                         delta,
541                                         delta_swing_table_xtal_up[delta]);
542                                 cali_info->xtal_offset =
543                                         delta_swing_table_xtal_up[delta];
544                                 xtal_offset_eanble =
545                                         (cali_info->xtal_offset_last ==
546                                          cali_info->xtal_offset) ?
547                                                 0 :
548                                                 1;
549                         }
550
551                 } else {
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*/
562
563                                 /*recording last Xtal offset*/
564                                 cali_info->xtal_offset_last =
565                                         cali_info->xtal_offset;
566                                 ODM_RT_TRACE(
567                                         dm, ODM_COMP_TX_PWR_TRACK,
568                                         "[Xtal] delta_swing_table_xtal_down[%d] = %d\n",
569                                         delta,
570                                         delta_swing_table_xtal_down[delta]);
571                                 cali_info->xtal_offset =
572                                         delta_swing_table_xtal_down[delta];
573                                 xtal_offset_eanble =
574                                         (cali_info->xtal_offset_last ==
575                                          cali_info->xtal_offset) ?
576                                                 0 :
577                                                 1;
578                         }
579                 }
580
581                 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) {
582                         ODM_RT_TRACE(
583                                 dm, ODM_COMP_TX_PWR_TRACK,
584                                 "\n\n=========================== [path-%d] Calculating power_index_offset===========================\n",
585                                 p);
586
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
591                                  */
592                                 cali_info->power_index_offset[p] = 0;
593                         } else {
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];
598                         }
599
600                         ODM_RT_TRACE(
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]);
606
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];
613
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];
617
618                         /*******Print BB Swing base and index Offset**********/
619
620                         ODM_RT_TRACE(
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]);
626                         ODM_RT_TRACE(
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]);
632
633                         /*4 7.1 Handle boundary conditions of index.*/
634
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;
641                 }
642
643                 ODM_RT_TRACE(
644                         dm, ODM_COMP_TX_PWR_TRACK,
645                         "\n\n========================================================================================================\n");
646
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;
651         } else {
652                 ODM_RT_TRACE(
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);
657
658                 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
659                         cali_info->power_index_offset[p] = 0;
660         }
661
662         /*Print Swing base & current*/
663         ODM_RT_TRACE(
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);
667
668         for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
669                 ODM_RT_TRACE(
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]);
674
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);
678
679                 if (power_tracking_type == 0) {
680                         ODM_RT_TRACE(
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,
685                                                               0);
686                 } else if (power_tracking_type == 1) {
687                         ODM_RT_TRACE(
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) {
694                         ODM_RT_TRACE(
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) {
701                         ODM_RT_TRACE(
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,
706                                                               0);
707                 }
708                 /*Record last Power Tracking Thermal value*/
709                 cali_info->thermal_value = thermal_value;
710
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. */
718
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
723                  * be bad.
724                  */
725                 /* 2012/04/25 MH Add for tx power tracking to set tx power in
726                  * tx agc for 88E.
727                  */
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 */
731                                 ODM_RT_TRACE(
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);
738                         }
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 */
743                                 ODM_RT_TRACE(
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);
750                         }
751                 }
752
753                 if (thermal_value > rtlefu->eeprom_thermalmeter) {
754                         ODM_RT_TRACE(
755                                 dm, ODM_COMP_TX_PWR_TRACK,
756                                 "Temperature(%d) higher than PG value(%d)\n",
757                                 thermal_value, rtlefu->eeprom_thermalmeter);
758
759                         phydm_odm_tx_power_set(dm, &c, indexforchannel, 0);
760                 } else {
761                         ODM_RT_TRACE(
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);
766                 }
767
768                 /*Record last time Power Tracking result as base.*/
769                 cali_info->bb_swing_idx_cck_base = cali_info->bb_swing_idx_cck;
770
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];
774
775                 ODM_RT_TRACE(
776                         dm, ODM_COMP_TX_PWR_TRACK,
777                         "cali_info->thermal_value = %d thermal_value= %d\n",
778                         cali_info->thermal_value, thermal_value);
779
780                 /*Record last Power Tracking Thermal value*/
781                 cali_info->thermal_value = thermal_value;
782         }
783
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 */
787
788                 if (xtal_offset_eanble != 0 &&
789                     cali_info->txpowertrack_control &&
790                     rtlefu->eeprom_thermalmeter != 0xff) {
791                         ODM_RT_TRACE(
792                                 dm, ODM_COMP_TX_PWR_TRACK,
793                                 "**********Enter Xtal Tracking**********\n");
794
795                         if (thermal_value > rtlefu->eeprom_thermalmeter) {
796                                 ODM_RT_TRACE(
797                                         dm, ODM_COMP_TX_PWR_TRACK,
798                                         "Temperature(%d) higher than PG value(%d)\n",
799                                         thermal_value,
800                                         rtlefu->eeprom_thermalmeter);
801                                 (*c.odm_txxtaltrack_set_xtal)(dm);
802                         } else {
803                                 ODM_RT_TRACE(
804                                         dm, ODM_COMP_TX_PWR_TRACK,
805                                         "Temperature(%d) lower than PG value(%d)\n",
806                                         thermal_value,
807                                         rtlefu->eeprom_thermalmeter);
808                                 (*c.odm_txxtaltrack_set_xtal)(dm);
809                         }
810                 }
811                 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
812                              "**********End Xtal Tracking**********\n");
813         }
814
815         if (!IS_HARDWARE_TYPE_8723B(adapter)) {
816                 /* Delta temperature is equal to or larger than 20 centigrade
817                  * (When threshold is 8).
818                  */
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);
825                 }
826         }
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);
830                         odm_set_bb_reg(
831                                 dm, 0xcc4,
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)) {
836                         s32 value = 0x20 +
837                                     (diff_DPK[ODM_RF_PATH_A] / c.threshold_dpk);
838
839                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
840                         odm_set_bb_reg(dm, 0xcc4, BIT(14) | BIT(13) | BIT(12) |
841                                                           BIT(11) | BIT(10),
842                                        value);
843                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
844                 } else {
845                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
846                         odm_set_bb_reg(dm, 0xcc4, BIT(14) | BIT(13) | BIT(12) |
847                                                           BIT(11) | BIT(10),
848                                        0);
849                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
850                 }
851         }
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);
855                         odm_set_bb_reg(
856                                 dm, 0xec4,
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)) {
861                         s32 value = 0x20 +
862                                     (diff_DPK[ODM_RF_PATH_B] / c.threshold_dpk);
863
864                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
865                         odm_set_bb_reg(dm, 0xec4, BIT(14) | BIT(13) | BIT(12) |
866                                                           BIT(11) | BIT(10),
867                                        value);
868                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
869                 } else {
870                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
871                         odm_set_bb_reg(dm, 0xec4, BIT(14) | BIT(13) | BIT(12) |
872                                                           BIT(11) | BIT(10),
873                                        0);
874                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
875                 }
876         }
877
878         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK, "<===%s\n", __func__);
879
880         cali_info->tx_powercount = 0;
881 }
882
883 /* 3============================================================
884  * 3 IQ Calibration
885  * 3============================================================
886  */
887
888 void odm_reset_iqk_result(void *dm_void) { return; }
889
890 u8 odm_get_right_chnl_place_for_iqk(u8 chnl)
891 {
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};
898         u8 place = chnl;
899
900         if (chnl > 14) {
901                 for (place = 14; place < sizeof(channel_all); place++) {
902                         if (channel_all[place] == chnl)
903                                 return place - 13;
904                 }
905         }
906         return 0;
907 }
908
909 static void odm_iq_calibrate(struct phy_dm_struct *dm)
910 {
911         void *adapter = dm->adapter;
912
913         if (IS_HARDWARE_TYPE_8812AU(adapter))
914                 return;
915
916         if (dm->is_linked) {
917                 if ((*dm->channel != dm->pre_channel) &&
918                     (!*dm->is_scan_in_process)) {
919                         dm->pre_channel = *dm->channel;
920                         dm->linked_interval = 0;
921                 }
922
923                 if (dm->linked_interval < 3)
924                         dm->linked_interval++;
925
926                 if (dm->linked_interval == 2) {
927                         if (IS_HARDWARE_TYPE_8814A(adapter))
928                                 ;
929
930                         else if (IS_HARDWARE_TYPE_8822B(adapter))
931                                 phy_iq_calibrate_8822b(dm, false);
932                 }
933         } else {
934                 dm->linked_interval = 0;
935         }
936 }
937
938 void phydm_rf_init(void *dm_void)
939 {
940         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
941
942         odm_txpowertracking_init(dm);
943
944         odm_clear_txpowertracking_state(dm);
945 }
946
947 void phydm_rf_watchdog(void *dm_void)
948 {
949         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
950
951         odm_txpowertracking_check(dm);
952         if (dm->support_ic_type & ODM_IC_11AC_SERIES)
953                 odm_iq_calibrate(dm);
954 }