GNU Linux-libre 4.14.251-gnu1
[releases.git] / drivers / staging / rtlwifi / phydm / halphyrf_ce.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2016  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25
26 #include "mp_precomp.h"
27 #include "phydm_precomp.h"
28
29 #define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size,                \
30                                     _delta_thermal)                            \
31         do {                                                                   \
32                 for (_offset = 0; _offset < _size; _offset++) {                \
33                         if (_delta_thermal <                                   \
34                             thermal_threshold[_direction][_offset]) {          \
35                                 if (_offset != 0)                              \
36                                         _offset--;                             \
37                                 break;                                         \
38                         }                                                      \
39                 }                                                              \
40                 if (_offset >= _size)                                          \
41                         _offset = _size - 1;                                   \
42         } while (0)
43
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)
49 {
50         u8 p = 0;
51
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*/
56                 switch (p) {
57                 case ODM_RF_PATH_B:
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]);
61
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];
67                         ODM_RT_TRACE(
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]);
71                         break;
72
73                 case ODM_RF_PATH_C:
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]);
77
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];
83                         ODM_RT_TRACE(
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]);
87                         break;
88
89                 case ODM_RF_PATH_D:
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]);
93
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];
99                         ODM_RT_TRACE(
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]);
103                         break;
104
105                 default:
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]);
109
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];
115                         ODM_RT_TRACE(
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]);
119                         break;
120                 }
121         }
122 }
123
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)
129 {
130         u8 p = 0;
131
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*/
136
137                 switch (p) {
138                 case ODM_RF_PATH_B:
139                         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
140                                      "delta_swing_table_idx_tdown_b[%d] = %d\n",
141                                      delta,
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];
148                         ODM_RT_TRACE(
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]);
152                         break;
153
154                 case ODM_RF_PATH_C:
155                         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
156                                      "delta_swing_table_idx_tdown_c[%d] = %d\n",
157                                      delta,
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];
164                         ODM_RT_TRACE(
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]);
168                         break;
169
170                 case ODM_RF_PATH_D:
171                         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
172                                      "delta_swing_table_idx_tdown_d[%d] = %d\n",
173                                      delta,
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];
180                         ODM_RT_TRACE(
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]);
184                         break;
185
186                 default:
187                         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
188                                      "delta_swing_table_idx_tdown_a[%d] = %d\n",
189                                      delta,
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];
196                         ODM_RT_TRACE(
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]);
200                         break;
201                 }
202         }
203 }
204
205 static inline void phydm_odm_tx_power_set(struct phy_dm_struct *dm,
206                                           struct txpwrtrack_cfg *c,
207                                           u8 indexforchannel, u8 flag)
208 {
209         u8 p = 0;
210
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 */
223
224                 ODM_RT_TRACE(
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++) {
228                         if (flag == 0)
229                                 (*c->odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
230                                                                0);
231                         else
232                                 (*c->odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p,
233                                                                indexforchannel);
234                 }
235         } else {
236                 ODM_RT_TRACE(
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,
241                                                        indexforchannel);
242         }
243 }
244
245 void configure_txpower_track(void *dm_void, struct txpwrtrack_cfg *config)
246 {
247         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
248
249         /* JJ ADD 20161014 */
250
251         if (dm->support_ic_type == ODM_RTL8822B)
252                 configure_txpower_track_8822b(config);
253 }
254
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.
259  *
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)
264 {
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);
268         u8 p = 0;
269         struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
270
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;
274
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;
280
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;
284
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;
289         }
290
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;
301
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 */
304 }
305
306 void odm_txpowertracking_callback_thermal_meter(void *dm_void)
307 {
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;
312
313         struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
314
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;
319
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;
326
327         struct txpwrtrack_cfg c;
328
329         /* 4 1. The following TWO tables decide the final index of
330          *      OFDM/CCK swing table.
331          */
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;
344
345         /* 4 2. Initialization ( 7 steps in total ) */
346
347         configure_txpower_track(dm, &c);
348
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);
353
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);
366
367         cali_info->txpowertracking_callback_cnt++; /*cosa add for debug*/
368         cali_info->is_txpowertracking_init = true;
369
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.
374          */
375         if (dm->mp_mode)
376                 cali_info->rega24 = 0x090e1317;
377
378         ODM_RT_TRACE(
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);
384
385         ODM_RT_TRACE(
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);
389
390         thermal_value =
391                 (u8)odm_get_rf_reg(dm, ODM_RF_PATH_A, c.thermal_reg_addr,
392                                    0xfc00); /* 0x42: RF Reg[15:10] 88E */
393
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);
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         /* 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);
411                 ODM_RT_TRACE(
412                         dm, ODM_COMP_CALIBRATION,
413                         "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n",
414                         regc80, regcd0, regcd4, regab4);
415         }
416
417         if (!cali_info->txpowertrack_control)
418                 return;
419
420         /*4 3. Initialize ThermalValues of rf_calibrate_info*/
421
422         if (cali_info->is_reloadtxpowerindex)
423                 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
424                              "reload ofdm index for band switch\n");
425
426         /*4 4. Calculate average thermal meter*/
427
428         cali_info->thermal_value_avg[cali_info->thermal_value_avg_index] =
429                 thermal_value;
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;
434
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++;
439                 }
440         }
441
442         if (thermal_value_avg_count) {
443                 /* Calculate Average thermal_value after average enough times */
444                 thermal_value =
445                         (u8)(thermal_value_avg / thermal_value_avg_count);
446                 cali_info->thermal_value_delta =
447                         thermal_value - rtlefu->eeprom_thermalmeter;
448                 ODM_RT_TRACE(
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);
452         }
453
454         /* 4 5. Calculate delta, delta_LCK, delta_IQK. */
455
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);
466
467         if (cali_info->thermal_value_iqk ==
468             0xff) { /*no PG, use thermal value for IQK*/
469                 cali_info->thermal_value_iqk = thermal_value;
470                 delta_IQK =
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");
476         }
477
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];
480
481         /*4 6. If necessary, do LCK.*/
482
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,
487                                      "no PG, do LCK\n");
488                         cali_info->thermal_value_lck = thermal_value;
489
490                         /*Use RTLCK, so close power tracking driver LCK*/
491                         if (!(dm->support_ic_type & ODM_RTL8814A) &&
492                             c.phy_lc_calibrate)
493                                 (*c.phy_lc_calibrate)(dm);
494
495                         delta_LCK =
496                                 (thermal_value > cali_info->thermal_value_lck) ?
497                                         (thermal_value -
498                                          cali_info->thermal_value_lck) :
499                                         (cali_info->thermal_value_lck -
500                                          thermal_value);
501                 }
502
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);
506
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;
513
514                         /*Use RTLCK, so close power tracking driver LCK*/
515                         if (!(dm->support_ic_type & ODM_RTL8814A) &&
516                             c.phy_lc_calibrate)
517                                 (*c.phy_lc_calibrate)(dm);
518                 }
519         }
520
521         /*3 7. If necessary, move the index of swing table to adjust Tx power.*/
522
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;
530
531                 /*4 7.1 The Final Power index = BaseIndex + power_index_offset*/
532
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*/
544
545                                 /*recording last Xtal offset*/
546                                 cali_info->xtal_offset_last =
547                                         cali_info->xtal_offset;
548                                 ODM_RT_TRACE(
549                                         dm, ODM_COMP_TX_PWR_TRACK,
550                                         "[Xtal] delta_swing_table_xtal_up[%d] = %d\n",
551                                         delta,
552                                         delta_swing_table_xtal_up[delta]);
553                                 cali_info->xtal_offset =
554                                         delta_swing_table_xtal_up[delta];
555                                 xtal_offset_eanble =
556                                         (cali_info->xtal_offset_last ==
557                                          cali_info->xtal_offset) ?
558                                                 0 :
559                                                 1;
560                         }
561
562                 } else {
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*/
573
574                                 /*recording last Xtal offset*/
575                                 cali_info->xtal_offset_last =
576                                         cali_info->xtal_offset;
577                                 ODM_RT_TRACE(
578                                         dm, ODM_COMP_TX_PWR_TRACK,
579                                         "[Xtal] delta_swing_table_xtal_down[%d] = %d\n",
580                                         delta,
581                                         delta_swing_table_xtal_down[delta]);
582                                 cali_info->xtal_offset =
583                                         delta_swing_table_xtal_down[delta];
584                                 xtal_offset_eanble =
585                                         (cali_info->xtal_offset_last ==
586                                          cali_info->xtal_offset) ?
587                                                 0 :
588                                                 1;
589                         }
590                 }
591
592                 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) {
593                         ODM_RT_TRACE(
594                                 dm, ODM_COMP_TX_PWR_TRACK,
595                                 "\n\n=========================== [path-%d] Calculating power_index_offset===========================\n",
596                                 p);
597
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
602                                  */
603                                 cali_info->power_index_offset[p] = 0;
604                         } else {
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];
609                         }
610
611                         ODM_RT_TRACE(
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]);
617
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];
624
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];
628
629                         /*******Print BB Swing base and index Offset**********/
630
631                         ODM_RT_TRACE(
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]);
637                         ODM_RT_TRACE(
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]);
643
644                         /*4 7.1 Handle boundary conditions of index.*/
645
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;
652                 }
653
654                 ODM_RT_TRACE(
655                         dm, ODM_COMP_TX_PWR_TRACK,
656                         "\n\n========================================================================================================\n");
657
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;
662         } else {
663                 ODM_RT_TRACE(
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);
668
669                 for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
670                         cali_info->power_index_offset[p] = 0;
671         }
672
673         /*Print Swing base & current*/
674         ODM_RT_TRACE(
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);
678
679         for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++)
680                 ODM_RT_TRACE(
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]);
685
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);
689
690                 if (power_tracking_type == 0) {
691                         ODM_RT_TRACE(
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,
696                                                               0);
697                 } else if (power_tracking_type == 1) {
698                         ODM_RT_TRACE(
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) {
705                         ODM_RT_TRACE(
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) {
712                         ODM_RT_TRACE(
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,
717                                                               0);
718                 }
719                 /*Record last Power Tracking Thermal value*/
720                 cali_info->thermal_value = thermal_value;
721
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. */
729
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
734                  * be bad.
735                  */
736                 /* 2012/04/25 MH Add for tx power tracking to set tx power in
737                  * tx agc for 88E.
738                  */
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 */
742                                 ODM_RT_TRACE(
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);
749                         }
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 */
754                                 ODM_RT_TRACE(
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);
761                         }
762                 }
763
764                 if (thermal_value > rtlefu->eeprom_thermalmeter) {
765                         ODM_RT_TRACE(
766                                 dm, ODM_COMP_TX_PWR_TRACK,
767                                 "Temperature(%d) higher than PG value(%d)\n",
768                                 thermal_value, rtlefu->eeprom_thermalmeter);
769
770                         phydm_odm_tx_power_set(dm, &c, indexforchannel, 0);
771                 } else {
772                         ODM_RT_TRACE(
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);
777                 }
778
779                 /*Record last time Power Tracking result as base.*/
780                 cali_info->bb_swing_idx_cck_base = cali_info->bb_swing_idx_cck;
781
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];
785
786                 ODM_RT_TRACE(
787                         dm, ODM_COMP_TX_PWR_TRACK,
788                         "cali_info->thermal_value = %d thermal_value= %d\n",
789                         cali_info->thermal_value, thermal_value);
790
791                 /*Record last Power Tracking Thermal value*/
792                 cali_info->thermal_value = thermal_value;
793         }
794
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 */
798
799                 if (xtal_offset_eanble != 0 &&
800                     cali_info->txpowertrack_control &&
801                     (rtlefu->eeprom_thermalmeter != 0xff)) {
802                         ODM_RT_TRACE(
803                                 dm, ODM_COMP_TX_PWR_TRACK,
804                                 "**********Enter Xtal Tracking**********\n");
805
806                         if (thermal_value > rtlefu->eeprom_thermalmeter) {
807                                 ODM_RT_TRACE(
808                                         dm, ODM_COMP_TX_PWR_TRACK,
809                                         "Temperature(%d) higher than PG value(%d)\n",
810                                         thermal_value,
811                                         rtlefu->eeprom_thermalmeter);
812                                 (*c.odm_txxtaltrack_set_xtal)(dm);
813                         } else {
814                                 ODM_RT_TRACE(
815                                         dm, ODM_COMP_TX_PWR_TRACK,
816                                         "Temperature(%d) lower than PG value(%d)\n",
817                                         thermal_value,
818                                         rtlefu->eeprom_thermalmeter);
819                                 (*c.odm_txxtaltrack_set_xtal)(dm);
820                         }
821                 }
822                 ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
823                              "**********End Xtal Tracking**********\n");
824         }
825
826         if (!IS_HARDWARE_TYPE_8723B(adapter)) {
827                 /* Delta temperature is equal to or larger than 20 centigrade
828                  * (When threshold is 8).
829                  */
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);
836                 }
837         }
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);
841                         odm_set_bb_reg(
842                                 dm, 0xcc4,
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)) {
847                         s32 value = 0x20 +
848                                     (diff_DPK[ODM_RF_PATH_A] / c.threshold_dpk);
849
850                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
851                         odm_set_bb_reg(dm, 0xcc4, BIT(14) | BIT(13) | BIT(12) |
852                                                           BIT(11) | BIT(10),
853                                        value);
854                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
855                 } else {
856                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
857                         odm_set_bb_reg(dm, 0xcc4, BIT(14) | BIT(13) | BIT(12) |
858                                                           BIT(11) | BIT(10),
859                                        0);
860                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
861                 }
862         }
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);
866                         odm_set_bb_reg(
867                                 dm, 0xec4,
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)) {
872                         s32 value = 0x20 +
873                                     (diff_DPK[ODM_RF_PATH_B] / c.threshold_dpk);
874
875                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
876                         odm_set_bb_reg(dm, 0xec4, BIT(14) | BIT(13) | BIT(12) |
877                                                           BIT(11) | BIT(10),
878                                        value);
879                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
880                 } else {
881                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x1);
882                         odm_set_bb_reg(dm, 0xec4, BIT(14) | BIT(13) | BIT(12) |
883                                                           BIT(11) | BIT(10),
884                                        0);
885                         odm_set_bb_reg(dm, 0x82c, BIT(31), 0x0);
886                 }
887         }
888
889         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK, "<===%s\n", __func__);
890
891         cali_info->tx_powercount = 0;
892 }
893
894 /* 3============================================================
895  * 3 IQ Calibration
896  * 3============================================================
897  */
898
899 void odm_reset_iqk_result(void *dm_void) { return; }
900
901 u8 odm_get_right_chnl_place_for_iqk(u8 chnl)
902 {
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};
909         u8 place = chnl;
910
911         if (chnl > 14) {
912                 for (place = 14; place < sizeof(channel_all); place++) {
913                         if (channel_all[place] == chnl)
914                                 return place - 13;
915                 }
916         }
917         return 0;
918 }
919
920 static void odm_iq_calibrate(struct phy_dm_struct *dm)
921 {
922         void *adapter = dm->adapter;
923
924         if (IS_HARDWARE_TYPE_8812AU(adapter))
925                 return;
926
927         if (dm->is_linked) {
928                 if ((*dm->channel != dm->pre_channel) &&
929                     (!*dm->is_scan_in_process)) {
930                         dm->pre_channel = *dm->channel;
931                         dm->linked_interval = 0;
932                 }
933
934                 if (dm->linked_interval < 3)
935                         dm->linked_interval++;
936
937                 if (dm->linked_interval == 2) {
938                         if (IS_HARDWARE_TYPE_8814A(adapter))
939                                 ;
940
941                         else if (IS_HARDWARE_TYPE_8822B(adapter))
942                                 phy_iq_calibrate_8822b(dm, false);
943                 }
944         } else {
945                 dm->linked_interval = 0;
946         }
947 }
948
949 void phydm_rf_init(void *dm_void)
950 {
951         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
952
953         odm_txpowertracking_init(dm);
954
955         odm_clear_txpowertracking_state(dm);
956 }
957
958 void phydm_rf_watchdog(void *dm_void)
959 {
960         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
961
962         odm_txpowertracking_check(dm);
963         if (dm->support_ic_type & ODM_IC_11AC_SERIES)
964                 odm_iq_calibrate(dm);
965 }