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