GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / staging / rtl8723bs / hal / HalPhyRf.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7
8 /* include "Mp_Precomp.h" */
9 #include "odm_precomp.h"
10
11 void ConfigureTxpowerTrack(struct dm_odm_t *pDM_Odm, struct txpwrtrack_cfg *pConfig)
12 {
13         ConfigureTxpowerTrack_8723B(pConfig);
14 }
15
16 /*  */
17 /*  <20121113, Kordan> This function should be called when TxAGC changed. */
18 /*  Otherwise the previous compensation is gone, because we record the */
19 /*  delta of temperature between two TxPowerTracking watch dogs. */
20 /*  */
21 /*  NOTE: If Tx BB swing or Tx scaling is varified during run-time, still */
22 /*        need to call this function. */
23 /*  */
24 void ODM_ClearTxPowerTrackingState(struct dm_odm_t *pDM_Odm)
25 {
26         struct hal_com_data *pHalData = GET_HAL_DATA(pDM_Odm->Adapter);
27         u8 p = 0;
28
29         pDM_Odm->BbSwingIdxCckBase = pDM_Odm->DefaultCckIndex;
30         pDM_Odm->BbSwingIdxCck = pDM_Odm->DefaultCckIndex;
31         pDM_Odm->RFCalibrateInfo.CCK_index = 0;
32
33         for (p = RF_PATH_A; p < MAX_RF_PATH; ++p) {
34                 pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->DefaultOfdmIndex;
35                 pDM_Odm->BbSwingIdxOfdm[p] = pDM_Odm->DefaultOfdmIndex;
36                 pDM_Odm->RFCalibrateInfo.OFDM_index[p] = pDM_Odm->DefaultOfdmIndex;
37
38                 pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
39                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] = 0;
40                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p] = 0;
41                 pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
42
43                 /*  Initial Mix mode power tracking */
44                 pDM_Odm->Absolute_OFDMSwingIdx[p] = 0;
45                 pDM_Odm->Remnant_OFDMSwingIdx[p] = 0;
46         }
47
48         /* Initial at Modify Tx Scaling Mode */
49         pDM_Odm->Modify_TxAGC_Flag_PathA = false;
50         /* Initial at Modify Tx Scaling Mode */
51         pDM_Odm->Modify_TxAGC_Flag_PathB = false;
52         pDM_Odm->Remnant_CCKSwingIdx = 0;
53         pDM_Odm->RFCalibrateInfo.ThermalValue = pHalData->EEPROMThermalMeter;
54         pDM_Odm->RFCalibrateInfo.ThermalValue_IQK = pHalData->EEPROMThermalMeter;
55         pDM_Odm->RFCalibrateInfo.ThermalValue_LCK = pHalData->EEPROMThermalMeter;
56 }
57
58 void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter)
59 {
60
61         struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
62         struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
63
64         u8 ThermalValue = 0, delta, delta_LCK, p = 0, i = 0;
65         u8 ThermalValue_AVG_count = 0;
66         u32 ThermalValue_AVG = 0;
67
68         u8 OFDM_min_index = 0;  /*  OFDM BB Swing should be less than +3.0dB, which is required by Arthur */
69         u8 Indexforchannel = 0; /*  GetRightChnlPlaceforIQK(pHalData->CurrentChannel) */
70
71         struct txpwrtrack_cfg c;
72
73
74         /* 4 1. The following TWO tables decide the final index of OFDM/CCK swing table. */
75         u8 *deltaSwingTableIdx_TUP_A;
76         u8 *deltaSwingTableIdx_TDOWN_A;
77         u8 *deltaSwingTableIdx_TUP_B;
78         u8 *deltaSwingTableIdx_TDOWN_B;
79
80         /* 4 2. Initialization (7 steps in total) */
81
82         ConfigureTxpowerTrack(pDM_Odm, &c);
83
84         (*c.GetDeltaSwingTable)(
85                 pDM_Odm,
86                 (u8 **)&deltaSwingTableIdx_TUP_A,
87                 (u8 **)&deltaSwingTableIdx_TDOWN_A,
88                 (u8 **)&deltaSwingTableIdx_TUP_B,
89                 (u8 **)&deltaSwingTableIdx_TDOWN_B
90         );
91
92         /* cosa add for debug */
93         pDM_Odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
94         pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = true;
95
96         ThermalValue = (u8)PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_A, c.ThermalRegAddr, 0xfc00);       /* 0x42: RF Reg[15:10] 88E */
97         if (
98                 !pDM_Odm->RFCalibrateInfo.TxPowerTrackControl ||
99                 pHalData->EEPROMThermalMeter == 0 ||
100                 pHalData->EEPROMThermalMeter == 0xFF
101         )
102                 return;
103
104         /* 4 3. Initialize ThermalValues of RFCalibrateInfo */
105
106         /* 4 4. Calculate average thermal meter */
107
108         pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index] = ThermalValue;
109         pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index++;
110         if (pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index == c.AverageThermalNum)   /* Average times =  c.AverageThermalNum */
111                 pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
112
113         for (i = 0; i < c.AverageThermalNum; i++) {
114                 if (pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
115                         ThermalValue_AVG += pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[i];
116                         ThermalValue_AVG_count++;
117                 }
118         }
119
120         /* Calculate Average ThermalValue after average enough times */
121         if (ThermalValue_AVG_count) {
122                 ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count);
123         }
124
125         /* 4 5. Calculate delta, delta_LCK */
126         /* delta" here is used to determine whether thermal value changes or not. */
127         delta =
128                 (ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue) ?
129                 (ThermalValue - pDM_Odm->RFCalibrateInfo.ThermalValue) :
130                 (pDM_Odm->RFCalibrateInfo.ThermalValue - ThermalValue);
131         delta_LCK =
132                 (ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue_LCK) ?
133                 (ThermalValue - pDM_Odm->RFCalibrateInfo.ThermalValue_LCK) :
134                 (pDM_Odm->RFCalibrateInfo.ThermalValue_LCK - ThermalValue);
135
136         /* 4 6. If necessary, do LCK. */
137         /*  Delta temperature is equal to or larger than 20 centigrade. */
138         if (delta_LCK >= c.Threshold_IQK) {
139                 pDM_Odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue;
140                 if (c.PHY_LCCalibrate)
141                         (*c.PHY_LCCalibrate)(pDM_Odm);
142         }
143
144         /* 3 7. If necessary, move the index of swing table to adjust Tx power. */
145         if (delta > 0 && pDM_Odm->RFCalibrateInfo.TxPowerTrackControl) {
146                 /* delta" here is used to record the absolute value of difference. */
147                 delta =
148                         ThermalValue > pHalData->EEPROMThermalMeter ?
149                         (ThermalValue - pHalData->EEPROMThermalMeter) :
150                         (pHalData->EEPROMThermalMeter - ThermalValue);
151
152                 if (delta >= TXPWR_TRACK_TABLE_SIZE)
153                         delta = TXPWR_TRACK_TABLE_SIZE - 1;
154
155                 /* 4 7.1 The Final Power Index = BaseIndex + PowerIndexOffset */
156                 if (ThermalValue > pHalData->EEPROMThermalMeter) {
157                         pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_A] =
158                                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A];
159                         pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A] =
160                                 deltaSwingTableIdx_TUP_A[delta];
161
162                         /*  Record delta swing for mix mode power tracking */
163                         pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_A] =
164                                 deltaSwingTableIdx_TUP_A[delta];
165
166                         if (c.RfPathCount > 1) {
167                                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_B] =
168                                         pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B];
169                                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B] =
170                                         deltaSwingTableIdx_TUP_B[delta];
171
172                                 /*  Record delta swing for mix mode power tracking */
173                                 pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_B] =
174                                         deltaSwingTableIdx_TUP_B[delta];
175                         }
176
177                 } else {
178                         pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_A] =
179                                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A];
180                         pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A] =
181                                 -1 * deltaSwingTableIdx_TDOWN_A[delta];
182
183                         /*  Record delta swing for mix mode power tracking */
184                         pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_A] =
185                                 -1 * deltaSwingTableIdx_TDOWN_A[delta];
186
187                         if (c.RfPathCount > 1) {
188                                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_B] =
189                                         pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B];
190                                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B] =
191                                         -1 * deltaSwingTableIdx_TDOWN_B[delta];
192
193                                  /*  Record delta swing for mix mode power tracking */
194                                 pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_B] =
195                                         -1 * deltaSwingTableIdx_TDOWN_B[delta];
196                         }
197                 }
198
199                 for (p = RF_PATH_A; p < c.RfPathCount; p++) {
200                         if (
201                                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] ==
202                                 pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p]
203                         ) /*  If Thermal value changes but lookup table value still the same */
204                                 pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
205                         else
206                                 pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] - pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p];      /*  Power Index Diff between 2 times Power Tracking */
207
208                         pDM_Odm->RFCalibrateInfo.OFDM_index[p] =
209                                 pDM_Odm->BbSwingIdxOfdmBase[p] +
210                                 pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p];
211
212                         pDM_Odm->RFCalibrateInfo.CCK_index =
213                                 pDM_Odm->BbSwingIdxCckBase +
214                                 pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p];
215
216                         pDM_Odm->BbSwingIdxCck =
217                                 pDM_Odm->RFCalibrateInfo.CCK_index;
218
219                         pDM_Odm->BbSwingIdxOfdm[p] =
220                                 pDM_Odm->RFCalibrateInfo.OFDM_index[p];
221
222                         /* 4 7.1 Handle boundary conditions of index. */
223                         if (pDM_Odm->RFCalibrateInfo.OFDM_index[p] > c.SwingTableSize_OFDM-1)
224                                 pDM_Odm->RFCalibrateInfo.OFDM_index[p] = c.SwingTableSize_OFDM-1;
225                         else if (pDM_Odm->RFCalibrateInfo.OFDM_index[p] < OFDM_min_index)
226                                 pDM_Odm->RFCalibrateInfo.OFDM_index[p] = OFDM_min_index;
227                 }
228                 if (pDM_Odm->RFCalibrateInfo.CCK_index > c.SwingTableSize_CCK-1)
229                         pDM_Odm->RFCalibrateInfo.CCK_index = c.SwingTableSize_CCK-1;
230                 /* else if (pDM_Odm->RFCalibrateInfo.CCK_index < 0) */
231                         /* pDM_Odm->RFCalibrateInfo.CCK_index = 0; */
232         } else {
233                         for (p = RF_PATH_A; p < c.RfPathCount; p++)
234                                 pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
235         }
236
237         /* Print Swing base & current */
238         for (p = RF_PATH_A; p < c.RfPathCount; p++) {
239         }
240
241         if (
242                 (pDM_Odm->RFCalibrateInfo.PowerIndexOffset[RF_PATH_A] != 0 ||
243                  pDM_Odm->RFCalibrateInfo.PowerIndexOffset[RF_PATH_B] != 0) &&
244                  pDM_Odm->RFCalibrateInfo.TxPowerTrackControl
245          ) {
246                 /* 4 7.2 Configure the Swing Table to adjust Tx Power. */
247
248                 pDM_Odm->RFCalibrateInfo.bTxPowerChanged = true; /*  Always true after Tx Power is adjusted by power tracking. */
249                 /*  */
250                 /*  2012/04/23 MH According to Luke's suggestion, we can not write BB digital */
251                 /*  to increase TX power. Otherwise, EVM will be bad. */
252                 /*  */
253                 /*  2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
254
255                 if (ThermalValue > pHalData->EEPROMThermalMeter) {
256                         for (p = RF_PATH_A; p < c.RfPathCount; p++)
257                                         (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, 0);
258                 } else {
259                         for (p = RF_PATH_A; p < c.RfPathCount; p++)
260                                 (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, Indexforchannel);
261                 }
262
263                 /*  Record last time Power Tracking result as base. */
264                 pDM_Odm->BbSwingIdxCckBase = pDM_Odm->BbSwingIdxCck;
265                 for (p = RF_PATH_A; p < c.RfPathCount; p++)
266                         pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->BbSwingIdxOfdm[p];
267
268                 /* Record last Power Tracking Thermal Value */
269                 pDM_Odm->RFCalibrateInfo.ThermalValue = ThermalValue;
270         }
271
272         pDM_Odm->RFCalibrateInfo.TXPowercount = 0;
273 }