1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 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 *****************************************************************************/
15
16 #include "mp_precomp.h"
17 #include "phydm_precomp.h"
18
19 #define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, _delta_thermal) \
20 do {\
21 for (_offset = 0; _offset < _size; _offset++) { \
22 \
23 if (_delta_thermal < thermal_threshold[_direction][_offset]) { \
24 \
25 if (_offset != 0)\
26 _offset--;\
27 break;\
28 } \
29 } \
30 if (_offset >= _size)\
31 _offset = _size-1;\
32 } while (0)
33
configure_txpower_track(struct dm_struct * dm,struct txpwrtrack_cfg * config)34 void configure_txpower_track(
35 struct dm_struct *dm,
36 struct txpwrtrack_cfg *config
37 )
38 {
39 #if RTL8192E_SUPPORT
40 if (dm->support_ic_type == ODM_RTL8192E)
41 configure_txpower_track_8192e(config);
42 #endif
43 #if RTL8821A_SUPPORT
44 if (dm->support_ic_type == ODM_RTL8821)
45 configure_txpower_track_8821a(config);
46 #endif
47 #if RTL8812A_SUPPORT
48 if (dm->support_ic_type == ODM_RTL8812)
49 configure_txpower_track_8812a(config);
50 #endif
51 #if RTL8188E_SUPPORT
52 if (dm->support_ic_type == ODM_RTL8188E)
53 configure_txpower_track_8188e(config);
54 #endif
55
56 #if RTL8188F_SUPPORT
57 if (dm->support_ic_type == ODM_RTL8188F)
58 configure_txpower_track_8188f(config);
59 #endif
60
61 #if RTL8723B_SUPPORT
62 if (dm->support_ic_type == ODM_RTL8723B)
63 configure_txpower_track_8723b(config);
64 #endif
65
66 #if RTL8814A_SUPPORT
67 if (dm->support_ic_type == ODM_RTL8814A)
68 configure_txpower_track_8814a(config);
69 #endif
70
71 #if RTL8703B_SUPPORT
72 if (dm->support_ic_type == ODM_RTL8703B)
73 configure_txpower_track_8703b(config);
74 #endif
75
76 #if RTL8822B_SUPPORT
77 if (dm->support_ic_type == ODM_RTL8822B)
78 configure_txpower_track_8822b(config);
79 #endif
80
81 #if RTL8723D_SUPPORT
82 if (dm->support_ic_type == ODM_RTL8723D)
83 configure_txpower_track_8723d(config);
84 #endif
85
86 /* JJ ADD 20161014 */
87 #if RTL8710B_SUPPORT
88 if (dm->support_ic_type == ODM_RTL8710B)
89 configure_txpower_track_8710b(config);
90 #endif
91
92 #if RTL8821C_SUPPORT
93 if (dm->support_ic_type == ODM_RTL8821C)
94 configure_txpower_track_8821c(config);
95 #endif
96
97 #if RTL8192F_SUPPORT
98 if (dm->support_ic_type == ODM_RTL8192F)
99 configure_txpower_track_8192f(config);
100 #endif
101
102 #if RTL8822C_SUPPORT
103 if (dm->support_ic_type == ODM_RTL8822C)
104 configure_txpower_track_8822c(config);
105 #endif
106
107 #if RTL8814B_SUPPORT
108 if (dm->support_ic_type == ODM_RTL8814B)
109 configure_txpower_track_8814b(config);
110 #endif
111
112 #if RTL8723F_SUPPORT
113 if (dm->support_ic_type == ODM_RTL8723F)
114 configure_txpower_track_8723f(config);
115 #endif
116
117 #if RTL8814C_SUPPORT
118 if (dm->support_ic_type == ODM_RTL8814C)
119 configure_txpower_track_8814c(config);
120 #endif
121
122
123 }
124
125 /* **********************************************************************
126 * <20121113, Kordan> This function should be called when tx_agc changed.
127 * Otherwise the previous compensation is gone, because we record the
128 * delta of temperature between two TxPowerTracking watch dogs.
129 *
130 * NOTE: If Tx BB swing or Tx scaling is varified during run-time, still
131 * need to call this function.
132 * ********************************************************************** */
133 void
odm_clear_txpowertracking_state(struct dm_struct * dm)134 odm_clear_txpowertracking_state(
135 struct dm_struct *dm
136 )
137 {
138 PHAL_DATA_TYPE hal_data = GET_HAL_DATA((PADAPTER)(dm->adapter));
139 u8 p = 0;
140 struct dm_rf_calibration_struct *cali_info = &(dm->rf_calibrate_info);
141
142 cali_info->bb_swing_idx_cck_base = cali_info->default_cck_index;
143 cali_info->bb_swing_idx_cck = cali_info->default_cck_index;
144 cali_info->CCK_index = 0;
145
146 for (p = RF_PATH_A; p < MAX_RF_PATH; ++p) {
147 cali_info->bb_swing_idx_ofdm_base[p] = cali_info->default_ofdm_index;
148 cali_info->bb_swing_idx_ofdm[p] = cali_info->default_ofdm_index;
149 cali_info->OFDM_index[p] = cali_info->default_ofdm_index;
150
151 cali_info->power_index_offset[p] = 0;
152 cali_info->delta_power_index[p] = 0;
153 cali_info->delta_power_index_last[p] = 0;
154
155 cali_info->absolute_ofdm_swing_idx[p] = 0; /* Initial Mix mode power tracking*/
156 cali_info->remnant_ofdm_swing_idx[p] = 0;
157 cali_info->kfree_offset[p] = 0;
158 }
159
160 cali_info->modify_tx_agc_flag_path_a = false; /*Initial at Modify Tx Scaling mode*/
161 cali_info->modify_tx_agc_flag_path_b = false; /*Initial at Modify Tx Scaling mode*/
162 cali_info->modify_tx_agc_flag_path_c = false; /*Initial at Modify Tx Scaling mode*/
163 cali_info->modify_tx_agc_flag_path_d = false; /*Initial at Modify Tx Scaling mode*/
164 cali_info->remnant_cck_swing_idx = 0;
165 cali_info->thermal_value = hal_data->eeprom_thermal_meter;
166
167 cali_info->modify_tx_agc_value_cck = 0; /* modify by Mingzhi.Guo */
168 cali_info->modify_tx_agc_value_ofdm = 0; /* modify by Mingzhi.Guo */
169
170 }
171
172 void
odm_txpowertracking_callback_thermal_meter(struct dm_struct * dm)173 odm_txpowertracking_callback_thermal_meter(
174 #if (DM_ODM_SUPPORT_TYPE & ODM_AP)
175 struct dm_struct *dm
176 #else
177 void *adapter
178 #endif
179 )
180 {
181 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
182 HAL_DATA_TYPE *hal_data = GET_HAL_DATA(((PADAPTER)adapter));
183 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
184 struct dm_struct *dm = &hal_data->DM_OutSrc;
185 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
186 struct dm_struct *dm = &hal_data->odmpriv;
187 #endif
188 #endif
189
190 struct dm_rf_calibration_struct *cali_info = &(dm->rf_calibrate_info);
191 struct dm_iqk_info *iqk_info = &dm->IQK_info;
192 struct _hal_rf_ *rf = &(dm->rf_table);
193 u8 thermal_value = 0, delta, delta_LCK, delta_IQK, p = 0, i = 0;
194 s8 diff_DPK[4] = {0};
195 u8 thermal_value_avg_count = 0;
196 u32 thermal_value_avg = 0, regc80, regcd0, regcd4, regab4, regc88, rege14, reg848,reg838, reg86c;
197
198 u8 OFDM_min_index = 0; /* OFDM BB Swing should be less than +3.0dB, which is required by Arthur */
199 u8 indexforchannel = 0; /* get_right_chnl_place_for_iqk(hal_data->current_channel) */
200 u8 power_tracking_type = hal_data->RfPowerTrackingType;
201 u8 xtal_offset_eanble = 0;
202 s8 thermal_value_temp = 0;
203
204 struct txpwrtrack_cfg c;
205
206 /* 4 1. The following TWO tables decide the final index of OFDM/CCK swing table. */
207 u8 *delta_swing_table_idx_tup_a = NULL;
208 u8 *delta_swing_table_idx_tdown_a = NULL;
209 u8 *delta_swing_table_idx_tup_b = NULL;
210 u8 *delta_swing_table_idx_tdown_b = NULL;
211 /*for 8814 add by Yu Chen*/
212 u8 *delta_swing_table_idx_tup_c = NULL;
213 u8 *delta_swing_table_idx_tdown_c = NULL;
214 u8 *delta_swing_table_idx_tup_d = NULL;
215 u8 *delta_swing_table_idx_tdown_d = NULL;
216 /*for Xtal Offset by James.Tung*/
217 s8 *delta_swing_table_xtal_up = NULL;
218 s8 *delta_swing_table_xtal_down = NULL;
219
220 /* 4 2. Initilization ( 7 steps in total ) */
221
222 configure_txpower_track(dm, &c);
223
224 (*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_a, (u8 **)&delta_swing_table_idx_tdown_a,
225 (u8 **)&delta_swing_table_idx_tup_b, (u8 **)&delta_swing_table_idx_tdown_b);
226
227 if (dm->support_ic_type & (ODM_RTL8814A | ODM_RTL8814B)) /*for 8814 path C & D*/
228 (*c.get_delta_swing_table8814only)(dm, (u8 **)&delta_swing_table_idx_tup_c, (u8 **)&delta_swing_table_idx_tdown_c,
229 (u8 **)&delta_swing_table_idx_tup_d, (u8 **)&delta_swing_table_idx_tdown_d);
230 /* JJ ADD 20161014 */
231 if (dm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F)) /*for Xtal Offset*/
232 (*c.get_delta_swing_xtal_table)(dm, (s8 **)&delta_swing_table_xtal_up, (s8 **)&delta_swing_table_xtal_down);
233
234
235 cali_info->txpowertracking_callback_cnt++; /*cosa add for debug*/
236 cali_info->is_txpowertracking_init = true;
237
238 /*cali_info->txpowertrack_control = hal_data->txpowertrack_control;
239 <Kordan> We should keep updating the control variable according to HalData.
240 <Kordan> rf_calibrate_info.rega24 will be initialized when ODM HW configuring, but MP configures with para files. */
241 #if (DM_ODM_SUPPORT_TYPE & ODM_WIN)
242 #if (MP_DRIVER == 1)
243 #ifndef RTL8723F_SUPPORT
244 cali_info->rega24 = 0x090e1317;
245 #endif
246 #endif
247
248 #elif (DM_ODM_SUPPORT_TYPE & ODM_CE)
249 if (*(dm->mp_mode) == true)
250 cali_info->rega24 = 0x090e1317;
251 #endif
252
253 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
254 "===>odm_txpowertracking_callback_thermal_meter\n cali_info->bb_swing_idx_cck_base: %d, cali_info->bb_swing_idx_ofdm_base[A]: %d, cali_info->default_ofdm_index: %d\n",
255 cali_info->bb_swing_idx_cck_base, cali_info->bb_swing_idx_ofdm_base[RF_PATH_A], cali_info->default_ofdm_index);
256
257 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
258 "cali_info->txpowertrack_control=%d, hal_data->eeprom_thermal_meter %d\n", cali_info->txpowertrack_control, hal_data->eeprom_thermal_meter);
259 thermal_value = (u8)odm_get_rf_reg(dm, RF_PATH_A, c.thermal_reg_addr, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
260
261 thermal_value_temp = thermal_value + phydm_get_thermal_offset(dm);
262
263 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
264 "thermal_value_temp(%d) = thermal_value(%d) + power_time_thermal(%d)\n", thermal_value_temp, thermal_value, phydm_get_thermal_offset(dm));
265
266 if (thermal_value_temp > 63)
267 thermal_value = 63;
268 else if (thermal_value_temp < 0)
269 thermal_value = 0;
270 else
271 thermal_value = thermal_value_temp;
272
273 /*add log by zhao he, check c80/c94/c14/ca0 value*/
274 if (dm->support_ic_type == ODM_RTL8723D) {
275 regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
276 regcd0 = odm_get_bb_reg(dm, R_0xcd0, MASKDWORD);
277 regcd4 = odm_get_bb_reg(dm, R_0xcd4, MASKDWORD);
278 regab4 = odm_get_bb_reg(dm, R_0xab4, 0x000007FF);
279 RF_DBG(dm, DBG_RF_IQK, "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n", regc80, regcd0, regcd4, regab4);
280 }
281
282 /* JJ ADD 20161014 */
283 if (dm->support_ic_type == ODM_RTL8710B) {
284 regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
285 regcd0 = odm_get_bb_reg(dm, R_0xcd0, MASKDWORD);
286 regcd4 = odm_get_bb_reg(dm, R_0xcd4, MASKDWORD);
287 regab4 = odm_get_bb_reg(dm, R_0xab4, 0x000007FF);
288 RF_DBG(dm, DBG_RF_IQK, "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n", regc80, regcd0, regcd4, regab4);
289 }
290 /* Winnita add 20171205 */
291 if (dm->support_ic_type == ODM_RTL8192F) {
292 regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
293 regc88 = odm_get_bb_reg(dm, R_0xc88, MASKDWORD);
294 regab4 = odm_get_bb_reg(dm, R_0xab4, MASKDWORD);
295 rege14 = odm_get_bb_reg(dm, R_0xe14, MASKDWORD);
296 reg848 = odm_get_bb_reg(dm, R_0x848, MASKDWORD);
297 reg838 = odm_get_bb_reg(dm, R_0x838, MASKDWORD);
298 reg86c = odm_get_bb_reg(dm, R_0x86c, MASKDWORD);
299 RF_DBG(dm, DBG_RF_IQK, "0xc80 = 0x%x 0xc88 = 0x%x 0xab4 = 0x%x 0xe14 = 0x%x\n", regc80, regc88, regab4, rege14);
300 RF_DBG(dm, DBG_RF_IQK, "0x848 = 0x%x 0x838 = 0x%x 0x86c = 0x%x\n", reg848, reg838, reg86c);
301 }
302
303 if (!cali_info->txpowertrack_control)
304 return;
305
306 if (hal_data->eeprom_thermal_meter == 0xff) {
307 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no pg, hal_data->eeprom_thermal_meter = 0x%x\n", hal_data->eeprom_thermal_meter);
308 return;
309 }
310
311 /*4 3. Initialize ThermalValues of rf_calibrate_info*/
312
313 if (cali_info->is_reloadtxpowerindex)
314 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "reload ofdm index for band switch\n");
315
316 /*4 4. Calculate average thermal meter*/
317
318 cali_info->thermal_value_avg[cali_info->thermal_value_avg_index] = thermal_value;
319 cali_info->thermal_value_avg_index++;
320 if (cali_info->thermal_value_avg_index == c.average_thermal_num) /*Average times = c.average_thermal_num*/
321 cali_info->thermal_value_avg_index = 0;
322
323 for (i = 0; i < c.average_thermal_num; i++) {
324 if (cali_info->thermal_value_avg[i]) {
325 thermal_value_avg += cali_info->thermal_value_avg[i];
326 thermal_value_avg_count++;
327 }
328 }
329
330 if (thermal_value_avg_count) { /* Calculate Average thermal_value after average enough times */
331 thermal_value = (u8)(thermal_value_avg / thermal_value_avg_count);
332 cali_info->thermal_value_delta = thermal_value - hal_data->eeprom_thermal_meter;
333 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
334 "AVG Thermal Meter = 0x%X, EFUSE Thermal base = 0x%X\n", thermal_value, hal_data->eeprom_thermal_meter);
335 }
336
337 /* 4 5. Calculate delta, delta_LCK, delta_IQK. */
338
339 /* "delta" here is used to determine whether thermal value changes or not. */
340 delta = (thermal_value > cali_info->thermal_value) ? (thermal_value - cali_info->thermal_value) : (cali_info->thermal_value - thermal_value);
341 delta_LCK = (thermal_value > cali_info->thermal_value_lck) ? (thermal_value - cali_info->thermal_value_lck) : (cali_info->thermal_value_lck - thermal_value);
342 delta_IQK = (thermal_value > cali_info->thermal_value_iqk) ? (thermal_value - cali_info->thermal_value_iqk) : (cali_info->thermal_value_iqk - thermal_value);
343
344 if (cali_info->thermal_value_iqk == 0xff) { /*no PG, use thermal value for IQK*/
345 cali_info->thermal_value_iqk = thermal_value;
346 delta_IQK = (thermal_value > cali_info->thermal_value_iqk) ? (thermal_value - cali_info->thermal_value_iqk) : (cali_info->thermal_value_iqk - thermal_value);
347 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no PG, use thermal_value for IQK\n");
348 }
349
350 for (p = RF_PATH_A; p < c.rf_path_count; p++)
351 diff_DPK[p] = (s8)thermal_value - (s8)cali_info->dpk_thermal[p];
352
353 /*4 6. If necessary, do LCK.*/
354
355 if (!(dm->support_ic_type & ODM_RTL8821)) { /*no PG, do LCK at initial status*/
356 if (cali_info->thermal_value_lck == 0xff) {
357 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no PG, do LCK\n");
358 cali_info->thermal_value_lck = thermal_value;
359
360 /*Use RTLCK, so close power tracking driver LCK*/
361 if ((!(dm->support_ic_type & ODM_RTL8814A)) && (!(dm->support_ic_type & ODM_RTL8822B))) {
362 if (c.phy_lc_calibrate)
363 (*c.phy_lc_calibrate)(dm);
364 }
365
366 delta_LCK = (thermal_value > cali_info->thermal_value_lck) ? (thermal_value - cali_info->thermal_value_lck) : (cali_info->thermal_value_lck - thermal_value);
367 }
368
369 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", delta, delta_LCK, delta_IQK);
370
371 /* Wait sacn to do LCK by RF Jenyu*/
372 if( (*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden)) {
373 /* Delta temperature is equal to or larger than 20 centigrade.*/
374 if (delta_LCK >= c.threshold_iqk) {
375 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_LCK(%d) >= threshold_iqk(%d)\n", delta_LCK, c.threshold_iqk);
376 cali_info->thermal_value_lck = thermal_value;
377
378 /*Use RTLCK, so close power tracking driver LCK*/
379 if ((!(dm->support_ic_type & ODM_RTL8814A)) && (!(dm->support_ic_type & ODM_RTL8822B))) {
380 if (c.phy_lc_calibrate)
381 (*c.phy_lc_calibrate)(dm);
382 }
383 }
384 }
385 }
386
387 /*3 7. If necessary, move the index of swing table to adjust Tx power.*/
388
389 if (delta > 0 && cali_info->txpowertrack_control) {
390 /* "delta" here is used to record the absolute value of differrence. */
391 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
392 delta = thermal_value > hal_data->eeprom_thermal_meter ? (thermal_value - hal_data->eeprom_thermal_meter) : (hal_data->eeprom_thermal_meter - thermal_value);
393 #else
394 delta = (thermal_value > dm->priv->pmib->dot11RFEntry.ther) ? (thermal_value - dm->priv->pmib->dot11RFEntry.ther) : (dm->priv->pmib->dot11RFEntry.ther - thermal_value);
395 #endif
396 if (delta >= TXPWR_TRACK_TABLE_SIZE)
397 delta = TXPWR_TRACK_TABLE_SIZE - 1;
398
399 /*4 7.1 The Final Power index = BaseIndex + power_index_offset*/
400
401 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
402 if (thermal_value > hal_data->eeprom_thermal_meter) {
403 #else
404 if (thermal_value > dm->priv->pmib->dot11RFEntry.ther) {
405 #endif
406
407 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
408 cali_info->delta_power_index_last[p] = cali_info->delta_power_index[p]; /*recording poer index offset*/
409 switch (p) {
410 case RF_PATH_B:
411 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
412 "delta_swing_table_idx_tup_b[%d] = %d\n", delta, delta_swing_table_idx_tup_b[delta]);
413
414 cali_info->delta_power_index[p] = delta_swing_table_idx_tup_b[delta];
415 cali_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_b[delta]; /*Record delta swing for mix mode power tracking*/
416 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
417 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_B] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
418 break;
419
420 case RF_PATH_C:
421 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
422 "delta_swing_table_idx_tup_c[%d] = %d\n", delta, delta_swing_table_idx_tup_c[delta]);
423
424 cali_info->delta_power_index[p] = delta_swing_table_idx_tup_c[delta];
425 cali_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_c[delta]; /*Record delta swing for mix mode power tracking*/
426 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
427 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_C] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
428 break;
429
430 case RF_PATH_D:
431 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
432 "delta_swing_table_idx_tup_d[%d] = %d\n", delta, delta_swing_table_idx_tup_d[delta]);
433
434 cali_info->delta_power_index[p] = delta_swing_table_idx_tup_d[delta];
435 cali_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_d[delta]; /*Record delta swing for mix mode power tracking*/
436 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
437 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_D] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
438 break;
439
440 default:
441 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
442 "delta_swing_table_idx_tup_a[%d] = %d\n", delta, delta_swing_table_idx_tup_a[delta]);
443
444 cali_info->delta_power_index[p] = delta_swing_table_idx_tup_a[delta];
445 cali_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_a[delta]; /*Record delta swing for mix mode power tracking*/
446 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
447 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_A] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
448 break;
449 }
450 }
451 /* JJ ADD 20161014 */
452 if (dm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F)) {
453 /*Save xtal_offset from Xtal table*/
454 cali_info->xtal_offset_last = cali_info->xtal_offset; /*recording last Xtal offset*/
455 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
456 "[Xtal] delta_swing_table_xtal_up[%d] = %d\n", delta, delta_swing_table_xtal_up[delta]);
457 cali_info->xtal_offset = delta_swing_table_xtal_up[delta];
458
459 if (cali_info->xtal_offset_last == cali_info->xtal_offset)
460 xtal_offset_eanble = 0;
461 else
462 xtal_offset_eanble = 1;
463 }
464
465 } else {
466 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
467 cali_info->delta_power_index_last[p] = cali_info->delta_power_index[p]; /*recording poer index offset*/
468
469 switch (p) {
470 case RF_PATH_B:
471 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
472 "delta_swing_table_idx_tdown_b[%d] = %d\n", delta, delta_swing_table_idx_tdown_b[delta]);
473 cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_b[delta];
474 cali_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_b[delta]; /*Record delta swing for mix mode power tracking*/
475 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
476 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_B] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
477 break;
478
479 case RF_PATH_C:
480 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
481 "delta_swing_table_idx_tdown_c[%d] = %d\n", delta, delta_swing_table_idx_tdown_c[delta]);
482 cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_c[delta];
483 cali_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_c[delta]; /*Record delta swing for mix mode power tracking*/
484 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
485 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_C] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
486 break;
487
488 case RF_PATH_D:
489 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
490 "delta_swing_table_idx_tdown_d[%d] = %d\n", delta, delta_swing_table_idx_tdown_d[delta]);
491 cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_d[delta];
492 cali_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_d[delta]; /*Record delta swing for mix mode power tracking*/
493 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
494 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_D] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
495 break;
496
497 default:
498 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
499 "delta_swing_table_idx_tdown_a[%d] = %d\n", delta, delta_swing_table_idx_tdown_a[delta]);
500 cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_a[delta];
501 cali_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_a[delta]; /*Record delta swing for mix mode power tracking*/
502 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
503 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_A] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
504 break;
505 }
506 }
507 /* JJ ADD 20161014 */
508 if (dm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F)) {
509 /*Save xtal_offset from Xtal table*/
510 cali_info->xtal_offset_last = cali_info->xtal_offset; /*recording last Xtal offset*/
511 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
512 "[Xtal] delta_swing_table_xtal_down[%d] = %d\n", delta, delta_swing_table_xtal_down[delta]);
513 cali_info->xtal_offset = delta_swing_table_xtal_down[delta];
514
515 if (cali_info->xtal_offset_last == cali_info->xtal_offset)
516 xtal_offset_eanble = 0;
517 else
518 xtal_offset_eanble = 1;
519 }
520
521 }
522
523 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
524 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
525 "\n\n=========================== [path-%d] Calculating power_index_offset===========================\n", p);
526
527 if (cali_info->delta_power_index[p] == cali_info->delta_power_index_last[p]) /*If Thermal value changes but lookup table value still the same*/
528 cali_info->power_index_offset[p] = 0;
529 else
530 cali_info->power_index_offset[p] = cali_info->delta_power_index[p] - cali_info->delta_power_index_last[p]; /*Power index diff between 2 times Power Tracking*/
531
532 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
533 "[path-%d] power_index_offset(%d) = delta_power_index(%d) - delta_power_index_last(%d)\n", p, cali_info->power_index_offset[p], cali_info->delta_power_index[p], cali_info->delta_power_index_last[p]);
534
535 cali_info->OFDM_index[p] = cali_info->bb_swing_idx_ofdm_base[p] + cali_info->power_index_offset[p];
536 cali_info->CCK_index = cali_info->bb_swing_idx_cck_base + cali_info->power_index_offset[p];
537
538 cali_info->bb_swing_idx_cck = cali_info->CCK_index;
539 cali_info->bb_swing_idx_ofdm[p] = cali_info->OFDM_index[p];
540
541 /*************Print BB Swing base and index Offset*************/
542
543 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
544 "The 'CCK' final index(%d) = BaseIndex(%d) + power_index_offset(%d)\n", cali_info->bb_swing_idx_cck, cali_info->bb_swing_idx_cck_base, cali_info->power_index_offset[p]);
545 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
546 "The 'OFDM' final index(%d) = BaseIndex[%d](%d) + power_index_offset(%d)\n", cali_info->bb_swing_idx_ofdm[p], p, cali_info->bb_swing_idx_ofdm_base[p], cali_info->power_index_offset[p]);
547
548 /*4 7.1 Handle boundary conditions of index.*/
549
550 if (cali_info->OFDM_index[p] > c.swing_table_size_ofdm - 1)
551 cali_info->OFDM_index[p] = c.swing_table_size_ofdm - 1;
552 else if (cali_info->OFDM_index[p] <= OFDM_min_index)
553 cali_info->OFDM_index[p] = OFDM_min_index;
554 }
555
556 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
557 "\n\n========================================================================================================\n");
558
559 if (cali_info->CCK_index > c.swing_table_size_cck - 1)
560 cali_info->CCK_index = c.swing_table_size_cck - 1;
561 else if (cali_info->CCK_index <= 0)
562 cali_info->CCK_index = 0;
563 } else {
564 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
565 "The thermal meter is unchanged or TxPowerTracking OFF(%d): thermal_value: %d, cali_info->thermal_value: %d\n",
566 cali_info->txpowertrack_control, thermal_value, cali_info->thermal_value);
567
568 for (p = RF_PATH_A; p < c.rf_path_count; p++)
569 cali_info->power_index_offset[p] = 0;
570 }
571
572 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
573 "TxPowerTracking: [CCK] Swing Current index: %d, Swing base index: %d\n",
574 cali_info->CCK_index, cali_info->bb_swing_idx_cck_base); /*Print Swing base & current*/
575
576 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
577 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
578 "TxPowerTracking: [OFDM] Swing Current index: %d, Swing base index[%d]: %d\n",
579 cali_info->OFDM_index[p], p, cali_info->bb_swing_idx_ofdm_base[p]);
580 }
581
582 if (dm->support_ic_type & ODM_RTL8814B)
583 power_tracking_type = TSSI_MODE;
584
585 if (dm->support_ic_type & (ODM_RTL8814A | ODM_RTL8814B)) {
586 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "power_tracking_type=%d\n", power_tracking_type);
587
588 if (power_tracking_type == 0) {
589 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
590 for (p = RF_PATH_A; p < c.rf_path_count; p++)
591 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
592 } else if (power_tracking_type == 1) {
593 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX(2G) TSSI(5G) MODE**********\n");
594 for (p = RF_PATH_A; p < c.rf_path_count; p++)
595 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_2G_TSSI_5G_MODE, p, 0);
596 } else if (power_tracking_type == 2) {
597 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX(5G) TSSI(2G)MODE**********\n");
598 for (p = RF_PATH_A; p < c.rf_path_count; p++)
599 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_5G_TSSI_2G_MODE, p, 0);
600 } else if (power_tracking_type == 3) {
601 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking TSSI MODE**********\n");
602 for (p = RF_PATH_A; p < c.rf_path_count; p++)
603 (*c.odm_tx_pwr_track_set_pwr)(dm, TSSI_MODE, p, 0);
604 }
605 cali_info->thermal_value = thermal_value; /*Record last Power Tracking Thermal value*/
606
607 } else if ((cali_info->power_index_offset[RF_PATH_A] != 0 ||
608 cali_info->power_index_offset[RF_PATH_B] != 0 ||
609 cali_info->power_index_offset[RF_PATH_C] != 0 ||
610 cali_info->power_index_offset[RF_PATH_D] != 0) &&
611 cali_info->txpowertrack_control && (hal_data->eeprom_thermal_meter != 0xff)) {
612 /* 4 7.2 Configure the Swing Table to adjust Tx Power. */
613
614 cali_info->is_tx_power_changed = true; /*Always true after Tx Power is adjusted by power tracking.*/
615 /* */
616 /* 2012/04/23 MH According to Luke's suggestion, we can not write BB digital */
617 /* to increase TX power. Otherwise, EVM will be bad. */
618 /* */
619 /* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
620 if (thermal_value > cali_info->thermal_value) {
621 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
622 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
623 "Temperature Increasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
624 p, cali_info->power_index_offset[p], delta, thermal_value, hal_data->eeprom_thermal_meter, cali_info->thermal_value);
625 }
626 } else if (thermal_value < cali_info->thermal_value) { /*Low temperature*/
627 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
628 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
629 "Temperature Decreasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
630 p, cali_info->power_index_offset[p], delta, thermal_value, hal_data->eeprom_thermal_meter, cali_info->thermal_value);
631 }
632 }
633
634 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
635 if (thermal_value > hal_data->eeprom_thermal_meter)
636 #else
637 if (thermal_value > dm->priv->pmib->dot11RFEntry.ther)
638 #endif
639 {
640 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
641 "Temperature(%d) higher than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
642
643 if (dm->support_ic_type == ODM_RTL8188E || dm->support_ic_type == ODM_RTL8192E || dm->support_ic_type == ODM_RTL8821 ||
644 dm->support_ic_type == ODM_RTL8812 || dm->support_ic_type == ODM_RTL8723B || dm->support_ic_type == ODM_RTL8814A ||
645 dm->support_ic_type == ODM_RTL8703B || dm->support_ic_type == ODM_RTL8188F || dm->support_ic_type == ODM_RTL8822B ||
646 dm->support_ic_type == ODM_RTL8723D || dm->support_ic_type == ODM_RTL8821C || dm->support_ic_type == ODM_RTL8710B ||
647 dm->support_ic_type == ODM_RTL8192F) {
648
649 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
650 for (p = RF_PATH_A; p < c.rf_path_count; p++)
651 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
652 } else {
653 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking BBSWING_MODE**********\n");
654 for (p = RF_PATH_A; p < c.rf_path_count; p++)
655 (*c.odm_tx_pwr_track_set_pwr)(dm, BBSWING, p, indexforchannel);
656 }
657 } else {
658 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
659 "Temperature(%d) lower than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
660
661 if (dm->support_ic_type == ODM_RTL8188E || dm->support_ic_type == ODM_RTL8192E || dm->support_ic_type == ODM_RTL8821 ||
662 dm->support_ic_type == ODM_RTL8812 || dm->support_ic_type == ODM_RTL8723B || dm->support_ic_type == ODM_RTL8814A ||
663 dm->support_ic_type == ODM_RTL8703B || dm->support_ic_type == ODM_RTL8188F || dm->support_ic_type == ODM_RTL8822B ||
664 dm->support_ic_type == ODM_RTL8723D || dm->support_ic_type == ODM_RTL8821C || dm->support_ic_type == ODM_RTL8710B ||
665 dm->support_ic_type == ODM_RTL8192F) {
666 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
667 for (p = RF_PATH_A; p < c.rf_path_count; p++)
668 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, indexforchannel);
669 } else {
670 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking BBSWING_MODE**********\n");
671 for (p = RF_PATH_A; p < c.rf_path_count; p++)
672 (*c.odm_tx_pwr_track_set_pwr)(dm, BBSWING, p, indexforchannel);
673 }
674
675 }
676
677 cali_info->bb_swing_idx_cck_base = cali_info->bb_swing_idx_cck; /*Record last time Power Tracking result as base.*/
678 for (p = RF_PATH_A; p < c.rf_path_count; p++)
679 cali_info->bb_swing_idx_ofdm_base[p] = cali_info->bb_swing_idx_ofdm[p];
680
681 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
682 "cali_info->thermal_value = %d thermal_value= %d\n", cali_info->thermal_value, thermal_value);
683
684 cali_info->thermal_value = thermal_value; /*Record last Power Tracking Thermal value*/
685
686 }
687
688
689 if (dm->support_ic_type == ODM_RTL8703B || dm->support_ic_type == ODM_RTL8723D ||
690 dm->support_ic_type == ODM_RTL8192F || dm->support_ic_type == ODM_RTL8710B) {/* JJ ADD 20161014 */
691
692 if (xtal_offset_eanble != 0 && cali_info->txpowertrack_control && (hal_data->eeprom_thermal_meter != 0xff)) {
693
694 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter Xtal Tracking**********\n");
695
696 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
697 if (thermal_value > hal_data->eeprom_thermal_meter) {
698 #else
699 if (thermal_value > dm->priv->pmib->dot11RFEntry.ther) {
700 #endif
701 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
702 "Temperature(%d) higher than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
703 (*c.odm_txxtaltrack_set_xtal)(dm);
704 } else {
705 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
706 "Temperature(%d) lower than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
707 (*c.odm_txxtaltrack_set_xtal)(dm);
708 }
709 }
710 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********End Xtal Tracking**********\n");
711 }
712
713 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
714
715 /* Wait sacn to do IQK by RF Jenyu*/
716 if ((*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden) && dm->is_linked) {
717 if (!IS_HARDWARE_TYPE_8723B(adapter)) {
718 /*Delta temperature is equal to or larger than 20 centigrade (When threshold is 8).*/
719 if (delta_IQK >= c.threshold_iqk) {
720 cali_info->thermal_value_iqk = thermal_value;
721 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_IQK(%d) >= threshold_iqk(%d)\n", delta_IQK, c.threshold_iqk);
722 if (!cali_info->is_iqk_in_progress)
723 (*c.do_iqk)(dm, delta_IQK, thermal_value, 8);
724 }
725 }
726 }
727 if (cali_info->dpk_thermal[RF_PATH_A] != 0) {
728 if (diff_DPK[RF_PATH_A] >= c.threshold_dpk) {
729 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
730 odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), (diff_DPK[RF_PATH_A] / c.threshold_dpk));
731 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
732 } else if ((diff_DPK[RF_PATH_A] <= -1 * c.threshold_dpk)) {
733 s32 value = 0x20 + (diff_DPK[RF_PATH_A] / c.threshold_dpk);
734
735 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
736 odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value);
737 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
738 } else {
739 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
740 odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0);
741 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
742 }
743 }
744 if (cali_info->dpk_thermal[RF_PATH_B] != 0) {
745 if (diff_DPK[RF_PATH_B] >= c.threshold_dpk) {
746 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
747 odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), (diff_DPK[RF_PATH_B] / c.threshold_dpk));
748 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
749 } else if ((diff_DPK[RF_PATH_B] <= -1 * c.threshold_dpk)) {
750 s32 value = 0x20 + (diff_DPK[RF_PATH_B] / c.threshold_dpk);
751
752 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
753 odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value);
754 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
755 } else {
756 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
757 odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0);
758 odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
759 }
760 }
761
762 #endif
763
764 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "<===odm_txpowertracking_callback_thermal_meter\n");
765
766 cali_info->tx_powercount = 0;
767 }
768
769 #if (RTL8822C_SUPPORT == 1 || RTL8814B_SUPPORT == 1 || RTL8723F_SUPPORT == 1 || RTL8814C_SUPPORT == 1)
770 void
771 odm_txpowertracking_new_callback_thermal_meter(void *dm_void)
772 {
773 struct dm_struct *dm = (struct dm_struct *)dm_void;
774 struct dm_rf_calibration_struct *cali_info = &(dm->rf_calibrate_info);
775 struct dm_iqk_info *iqk_info = &dm->IQK_info;
776 struct _hal_rf_ *rf = &dm->rf_table;
777 struct _halrf_tssi_data *tssi = &rf->halrf_tssi_data;
778 u8 thermal_value[MAX_RF_PATH] = {0}, delta[MAX_RF_PATH] = {0};
779 u8 delta_swing_table_idx_tup[DELTA_SWINGIDX_SIZE] = {0};
780 u8 delta_swing_table_idx_tdown[DELTA_SWINGIDX_SIZE] = {0};
781 u8 delta_LCK = 0, delta_IQK = 0, i = 0, j = 0, p;
782 u8 thermal_value_avg_count[MAX_RF_PATH] = {0};
783 u32 thermal_value_avg[MAX_RF_PATH] = {0};
784 s8 thermal_value_temp[MAX_RF_PATH] = {0};
785 u8 tracking_method = MIX_MODE;
786
787 struct txpwrtrack_cfg c;
788
789 u8 *delta_swing_table_idx_tup_a = NULL;
790 u8 *delta_swing_table_idx_tdown_a = NULL;
791 u8 *delta_swing_table_idx_tup_b = NULL;
792 u8 *delta_swing_table_idx_tdown_b = NULL;
793 u8 *delta_swing_table_idx_tup_c = NULL;
794 u8 *delta_swing_table_idx_tdown_c = NULL;
795 u8 *delta_swing_table_idx_tup_d = NULL;
796 u8 *delta_swing_table_idx_tdown_d = NULL;
797
798 configure_txpower_track(dm, &c);
799
800 (*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_a, (u8 **)&delta_swing_table_idx_tdown_a,
801 (u8 **)&delta_swing_table_idx_tup_b, (u8 **)&delta_swing_table_idx_tdown_b);
802
803 if (dm->support_ic_type & (ODM_RTL8814B | ODM_RTL8814C)) {
804 (*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_c, (u8 **)&delta_swing_table_idx_tdown_c,
805 (u8 **)&delta_swing_table_idx_tup_d, (u8 **)&delta_swing_table_idx_tdown_d);
806 }
807
808 cali_info->txpowertracking_callback_cnt++;
809 cali_info->is_txpowertracking_init = true;
810
811 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
812 "===>odm_txpowertracking_callback_thermal_meter\n cali_info->bb_swing_idx_cck_base: %d, cali_info->bb_swing_idx_ofdm_base[A]: %d, cali_info->default_ofdm_index: %d\n",
813 cali_info->bb_swing_idx_cck_base, cali_info->bb_swing_idx_ofdm_base[RF_PATH_A], cali_info->default_ofdm_index);
814
815 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
816 "cali_info->txpowertrack_control=%d, tssi->thermal[RF_PATH_A]=%d tssi->thermal[RF_PATH_B]=%d\n",
817 cali_info->txpowertrack_control, tssi->thermal[RF_PATH_A], tssi->thermal[RF_PATH_B]);
818
819 if (dm->support_ic_type == ODM_RTL8822C) {
820 for (i = 0; i < c.rf_path_count; i++)
821 thermal_value[i] = (u8)odm_get_rf_reg(dm, i, c.thermal_reg_addr, 0x7e); /* 0x42: RF Reg[6:1] Thermal Trim*/
822 } else {
823 for (i = 0; i < c.rf_path_count; i++) {
824 thermal_value[i] = (u8)odm_get_rf_reg(dm, i, c.thermal_reg_addr, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
825
826 if (dm->support_ic_type & (ODM_RTL8814B | ODM_RTL8814C)) {
827 thermal_value_temp[i] = (s8)thermal_value[i] + phydm_get_multi_thermal_offset(dm, i);
828 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
829 "thermal_value_temp[%d](%d) = thermal_value[%d](%d) + multi_thermal_trim(%d)\n", i, thermal_value_temp[i], i, thermal_value[i], phydm_get_multi_thermal_offset(dm, i));
830 } else {
831 thermal_value_temp[i] = (s8)thermal_value[i] + phydm_get_thermal_offset(dm);
832 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
833 "thermal_value_temp[%d](%d) = thermal_value[%d](%d) + thermal_trim(%d)\n", i, thermal_value_temp[i], i, thermal_value[i], phydm_get_thermal_offset(dm));
834 }
835
836 if (thermal_value_temp[i] > 63)
837 thermal_value[i] = 63;
838 else if (thermal_value_temp[i] < 0)
839 thermal_value[i] = 0;
840 else
841 thermal_value[i] = thermal_value_temp[i];
842 }
843 }
844
845 if ((tssi->thermal[RF_PATH_A] == 0xff || tssi->thermal[RF_PATH_B] == 0xff)) {
846 for (i = 0; i < c.rf_path_count; i++)
847 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no pg, tssi->thermal[%d] = 0x%x\n",
848 i, tssi->thermal[i]);
849 return;
850 }
851
852 for (j = 0; j < c.rf_path_count; j++) {
853 cali_info->thermal_value_avg_path[j][cali_info->thermal_value_avg_index_path[j]] = thermal_value[j];
854 cali_info->thermal_value_avg_index_path[j]++;
855 if (cali_info->thermal_value_avg_index_path[j] == c.average_thermal_num) /*Average times = c.average_thermal_num*/
856 cali_info->thermal_value_avg_index_path[j] = 0;
857
858
859 for (i = 0; i < c.average_thermal_num; i++) {
860 if (cali_info->thermal_value_avg_path[j][i]) {
861 thermal_value_avg[j] += cali_info->thermal_value_avg_path[j][i];
862 thermal_value_avg_count[j]++;
863 }
864 }
865
866 if (thermal_value_avg_count[j]) { /* Calculate Average thermal_value after average enough times */
867 thermal_value[j] = (u8)(thermal_value_avg[j] / thermal_value_avg_count[j]);
868 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
869 "AVG Thermal Meter = 0x%X, tssi->thermal[%d] = 0x%x\n",
870 thermal_value[j], j, tssi->thermal[j]);
871 }
872 /* 4 5. Calculate delta, delta_LCK, delta_IQK. */
873
874 /* "delta" here is used to determine whether thermal value changes or not. */
875 delta[j] = (thermal_value[j] > cali_info->thermal_value_path[j]) ? (thermal_value[j] - cali_info->thermal_value_path[j]) : (cali_info->thermal_value_path[j] - thermal_value[j]);
876 delta_LCK = (thermal_value[0] > cali_info->thermal_value_lck) ? (thermal_value[0] - cali_info->thermal_value_lck) : (cali_info->thermal_value_lck - thermal_value[0]);
877 delta_IQK = (thermal_value[0] > cali_info->thermal_value_iqk) ? (thermal_value[0] - cali_info->thermal_value_iqk) : (cali_info->thermal_value_iqk - thermal_value[0]);
878 }
879
880 /*4 6. If necessary, do LCK.*/
881
882 for (i = 0; i < c.rf_path_count; i++)
883 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "(delta[%d], delta_LCK, delta_IQK) = (%d, %d, %d)\n", i, delta[i], delta_LCK, delta_IQK);
884
885 /* Wait sacn to do LCK by RF Jenyu*/
886 if( (*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden)) {
887 /* Delta temperature is equal to or larger than 20 centigrade.*/
888 if (delta_LCK >= c.threshold_iqk) {
889 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_LCK(%d) >= threshold_iqk(%d)\n", delta_LCK, c.threshold_iqk);
890 cali_info->thermal_value_lck = thermal_value[RF_PATH_A];
891
892 /*Use RTLCK, so close power tracking driver LCK*/
893 if ((!(dm->support_ic_type & ODM_RTL8814A)) &&
894 (!(dm->support_ic_type & ODM_RTL8822B)) &&
895 (!(dm->support_ic_type & ODM_RTL8723F))) {
896 if (c.phy_lc_calibrate)
897 (*c.phy_lc_calibrate)(dm);
898 } else
899 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "Do not do LCK\n");
900 }
901 }
902
903 /*3 7. If necessary, move the index of swing table to adjust Tx power.*/
904 for (i = 0; i < c.rf_path_count; i++) {
905 if (i == RF_PATH_B) {
906 odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_b, DELTA_SWINGIDX_SIZE);
907 odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_b, DELTA_SWINGIDX_SIZE);
908 } else if (i == RF_PATH_C) {
909 odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_c, DELTA_SWINGIDX_SIZE);
910 odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_c, DELTA_SWINGIDX_SIZE);
911 } else if (i == RF_PATH_D) {
912 odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_d, DELTA_SWINGIDX_SIZE);
913 odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_d, DELTA_SWINGIDX_SIZE);
914 } else {
915 odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_a, DELTA_SWINGIDX_SIZE);
916 odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_a, DELTA_SWINGIDX_SIZE);
917 }
918
919 cali_info->delta_power_index_last[i] = cali_info->delta_power_index[i]; /*recording poer index offset*/
920 delta[i] = thermal_value[i] > tssi->thermal[i] ? (thermal_value[i] - tssi->thermal[i]) : (tssi->thermal[i] - thermal_value[i]);
921
922 if (delta[i] >= TXPWR_TRACK_TABLE_SIZE)
923 delta[i] = TXPWR_TRACK_TABLE_SIZE - 1;
924
925 if (thermal_value[i] > tssi->thermal[i]) {
926 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
927 "delta_swing_table_idx_tup[%d]=%d Path=%d\n", delta[i], delta_swing_table_idx_tup[delta[i]], i);
928
929 cali_info->delta_power_index[i] = delta_swing_table_idx_tup[delta[i]];
930 cali_info->absolute_ofdm_swing_idx[i] = delta_swing_table_idx_tup[delta[i]]; /*Record delta swing for mix mode power tracking*/
931 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
932 "******Temp is higher and cali_info->absolute_ofdm_swing_idx[%d]=%d Path=%d\n", delta[i], cali_info->absolute_ofdm_swing_idx[i], i);
933 } else {
934 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
935 "delta_swing_table_idx_tdown[%d]=%d Path=%d\n", delta[i], delta_swing_table_idx_tdown[delta[i]], i);
936 cali_info->delta_power_index[i] = -1 * delta_swing_table_idx_tdown[delta[i]];
937 cali_info->absolute_ofdm_swing_idx[i] = -1 * delta_swing_table_idx_tdown[delta[i]]; /*Record delta swing for mix mode power tracking*/
938 RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
939 "******Temp is lower and cali_info->absolute_ofdm_swing_idx[%d]=%d Path=%d\n", delta[i], cali_info->absolute_ofdm_swing_idx[i], i);
940 }
941 }
942
943 for (p = RF_PATH_A; p < c.rf_path_count; p++) {
944 if (cali_info->delta_power_index[p] == cali_info->delta_power_index_last[p]) /*If Thermal value changes but lookup table value still the same*/
945 cali_info->power_index_offset[p] = 0;
946 else
947 cali_info->power_index_offset[p] = cali_info->delta_power_index[p] - cali_info->delta_power_index_last[p]; /*Power index diff between 2 times Power Tracking*/
948 }
949
950 #if 0
951 if (dm->support_ic_type == ODM_RTL8822C) {
952 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
953 for (p = RF_PATH_A; p < c.rf_path_count; p++)
954 (*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
955 } else {
956 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking BBSWING_MODE**********\n");
957 for (p = RF_PATH_A; p < c.rf_path_count; p++)
958 (*c.odm_tx_pwr_track_set_pwr)(dm, BBSWING, p, 0);
959 }
960 #endif
961 if (*dm->mp_mode == 1) {
962 if (cali_info->txpowertrack_control == 1) {
963 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
964 tracking_method = MIX_MODE;
965 } else if (cali_info->txpowertrack_control == 3) {
966 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking TSSI_MODE**********\n");
967 tracking_method = TSSI_MODE;
968 }
969 } else {
970 if (rf->power_track_type >= 0 && rf->power_track_type <= 3) {
971 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
972 tracking_method = MIX_MODE;
973 } else if (rf->power_track_type >= 4 && rf->power_track_type <= 7) {
974 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking TSSI_MODE**********\n");
975 tracking_method = TSSI_MODE;
976 }
977 }
978
979 if (dm->support_ic_type & (ODM_RTL8822C | ODM_RTL8814B | ODM_RTL8814C))
980 for (p = RF_PATH_A; p < c.rf_path_count; p++)
981 (*c.odm_tx_pwr_track_set_pwr)(dm, tracking_method, p, 0);
982
983 /* Wait sacn to do IQK by RF Jenyu*/
984 if ((*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden) && (dm->is_linked || *dm->mp_mode)) {
985 /*Delta temperature is equal to or larger than 20 centigrade (When threshold is 8).*/
986 if (delta_IQK >= c.threshold_iqk) {
987 cali_info->thermal_value_iqk = thermal_value[RF_PATH_A];
988 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_IQK(%d) >= threshold_iqk(%d)\n", delta_IQK, c.threshold_iqk);
989 /*if (!cali_info->is_iqk_in_progress)*/
990 /* (*c.do_iqk)(dm, delta_IQK, thermal_value[RF_PATH_A], 8);*/
991 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "Do IQK\n");
992
993 /*if (!cali_info->is_iqk_in_progress)*/
994 /* (*c.do_tssi_dck)(dm, true);*/
995 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "Do TSSI DCK\n");
996 }
997 }
998
999 RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "<===%s\n", __func__);
1000
1001 cali_info->tx_powercount = 0;
1002 }
1003 #endif
1004
1005 /* 3============================================================
1006 * 3 IQ Calibration
1007 * 3============================================================ */
1008
1009 void
1010 odm_reset_iqk_result(
1011 struct dm_struct *dm
1012 )
1013 {
1014 return;
1015 }
1016 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
1017 u8 odm_get_right_chnl_place_for_iqk(u8 chnl)
1018 {
1019 u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
1020 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, 161, 163, 165
1021 };
1022 u8 place = chnl;
1023
1024
1025 if (chnl > 14) {
1026 for (place = 14; place < sizeof(channel_all); place++) {
1027 if (channel_all[place] == chnl)
1028 return place - 13;
1029 }
1030 }
1031 return 0;
1032
1033 }
1034 #endif
1035
1036 void
1037 odm_iq_calibrate(
1038 struct dm_struct *dm
1039 )
1040 {
1041 void *adapter = dm->adapter;
1042 struct dm_iqk_info *iqk_info = &dm->IQK_info;
1043
1044 RF_DBG(dm, DBG_RF_IQK, "=>%s\n",__FUNCTION__);
1045
1046 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
1047 if (*dm->is_fcs_mode_enable)
1048 return;
1049 #endif
1050 if (dm->is_linked) {
1051 RF_DBG(dm, DBG_RF_IQK,
1052 "interval=%d ch=%d prech=%d scan=%s rfk_f =%s\n",
1053 dm->linked_interval, *dm->channel, dm->pre_channel,
1054 *dm->is_scan_in_process == TRUE ? "TRUE":"FALSE",
1055 iqk_info->rfk_forbidden == TRUE ? "TRUE":"FALSE");
1056
1057 if (iqk_info->rfk_forbidden) {
1058 RF_DBG(dm, DBG_RF_IQK, "return by rfk_forbidden\n");
1059 return;
1060 }
1061
1062 if (*dm->is_scan_in_process) {
1063 RF_DBG(dm, DBG_RF_IQK, "return by is_scan_in_process\n");
1064 return;
1065 }
1066
1067 if (*dm->channel != dm->pre_channel) {
1068 dm->pre_channel = *dm->channel;
1069 dm->linked_interval = 0;
1070 }
1071
1072 if (dm->linked_interval < 3)
1073 dm->linked_interval++;
1074
1075 if (dm->linked_interval == 2)
1076 PHY_IQCalibrate(adapter, false);
1077 } else {
1078 dm->linked_interval = 0;
1079 RF_DBG(dm, DBG_RF_IQK, "is_linked =%s, interval =%d\n",
1080 dm->is_linked == TRUE ? "TRUE":"FALSE",
1081 dm->linked_interval);
1082 }
1083 }
1084
1085 void phydm_rf_init(struct dm_struct *dm)
1086 {
1087
1088 odm_txpowertracking_init(dm);
1089
1090 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
1091 odm_clear_txpowertracking_state(dm);
1092 #endif
1093
1094 #if (DM_ODM_SUPPORT_TYPE & (ODM_AP))
1095 #if (RTL8814A_SUPPORT == 1)
1096 if (dm->support_ic_type & ODM_RTL8814A)
1097 phy_iq_calibrate_8814a_init(dm);
1098 #endif
1099 #endif
1100
1101 }
1102
1103 void phydm_rf_watchdog(struct dm_struct *dm)
1104 {
1105 #if (DM_ODM_SUPPORT_TYPE & ODM_WIN)
1106 FunctionIn(COMP_MLME);
1107
1108 if (*dm->mp_mode == 1) {
1109 #if (MP_DRIVER == 1)
1110 odm_txpowertracking_check(dm);
1111 #endif
1112 } else {
1113 odm_txpowertracking_check(dm);
1114
1115 if (dm->support_ic_type & (ODM_IC_11AC_SERIES | ODM_IC_JGR3_SERIES))
1116 odm_iq_calibrate(dm);
1117 }
1118 #endif
1119 }
1120