GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / staging / rtlwifi / phydm / rtl8822b / halphyrf_8822b.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2016  Realtek Corporation.
5  *
6  * Contact Information:
7  * wlanfae <wlanfae@realtek.com>
8  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
9  * Hsinchu 300, Taiwan.
10  *
11  * Larry Finger <Larry.Finger@lwfinger.net>
12  *
13  *****************************************************************************/
14
15 #include "../mp_precomp.h"
16 #include "../phydm_precomp.h"
17
18 static bool
19 get_mix_mode_tx_agc_bb_swing_offset_8822b(void *dm_void,
20                                           enum pwrtrack_method method,
21                                           u8 rf_path, u8 tx_power_index_offset)
22 {
23         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
24         struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
25
26         u8 bb_swing_upper_bound = cali_info->default_ofdm_index + 10;
27         u8 bb_swing_lower_bound = 0;
28
29         s8 tx_agc_index = 0;
30         u8 tx_bb_swing_index = cali_info->default_ofdm_index;
31
32         ODM_RT_TRACE(
33                 dm, ODM_COMP_TX_PWR_TRACK,
34                 "Path_%d cali_info->absolute_ofdm_swing_idx[rf_path]=%d, tx_power_index_offset=%d\n",
35                 rf_path, cali_info->absolute_ofdm_swing_idx[rf_path],
36                 tx_power_index_offset);
37
38         if (tx_power_index_offset > 0XF)
39                 tx_power_index_offset = 0XF;
40
41         if (cali_info->absolute_ofdm_swing_idx[rf_path] >= 0 &&
42             cali_info->absolute_ofdm_swing_idx[rf_path] <=
43                     tx_power_index_offset) {
44                 tx_agc_index = cali_info->absolute_ofdm_swing_idx[rf_path];
45                 tx_bb_swing_index = cali_info->default_ofdm_index;
46         } else if (cali_info->absolute_ofdm_swing_idx[rf_path] >
47                    tx_power_index_offset) {
48                 tx_agc_index = tx_power_index_offset;
49                 cali_info->remnant_ofdm_swing_idx[rf_path] =
50                         cali_info->absolute_ofdm_swing_idx[rf_path] -
51                         tx_power_index_offset;
52                 tx_bb_swing_index = cali_info->default_ofdm_index +
53                                     cali_info->remnant_ofdm_swing_idx[rf_path];
54
55                 if (tx_bb_swing_index > bb_swing_upper_bound)
56                         tx_bb_swing_index = bb_swing_upper_bound;
57         } else {
58                 tx_agc_index = 0;
59
60                 if (cali_info->default_ofdm_index >
61                     (cali_info->absolute_ofdm_swing_idx[rf_path] * (-1)))
62                         tx_bb_swing_index =
63                                 cali_info->default_ofdm_index +
64                                 cali_info->absolute_ofdm_swing_idx[rf_path];
65                 else
66                         tx_bb_swing_index = bb_swing_lower_bound;
67
68                 if (tx_bb_swing_index < bb_swing_lower_bound)
69                         tx_bb_swing_index = bb_swing_lower_bound;
70         }
71
72         cali_info->absolute_ofdm_swing_idx[rf_path] = tx_agc_index;
73         cali_info->bb_swing_idx_ofdm[rf_path] = tx_bb_swing_index;
74
75         ODM_RT_TRACE(
76                 dm, ODM_COMP_TX_PWR_TRACK,
77                 "MixMode Offset Path_%d   cali_info->absolute_ofdm_swing_idx[rf_path]=%d   cali_info->bb_swing_idx_ofdm[rf_path]=%d   tx_power_index_offset=%d\n",
78                 rf_path, cali_info->absolute_ofdm_swing_idx[rf_path],
79                 cali_info->bb_swing_idx_ofdm[rf_path], tx_power_index_offset);
80
81         return true;
82 }
83
84 void odm_tx_pwr_track_set_pwr8822b(void *dm_void, enum pwrtrack_method method,
85                                    u8 rf_path, u8 channel_mapped_index)
86 {
87         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
88         struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
89         u8 tx_power_index_offset = 0;
90         u8 tx_power_index = 0;
91
92         struct rtl_priv *rtlpriv = (struct rtl_priv *)dm->adapter;
93         struct rtl_phy *rtlphy = &rtlpriv->phy;
94         u8 channel = rtlphy->current_channel;
95         u8 band_width = rtlphy->current_chan_bw;
96         u8 tx_rate = 0xFF;
97
98         if (!dm->mp_mode) {
99                 u16 rate = *dm->forced_data_rate;
100
101                 if (!rate) /*auto rate*/
102                         tx_rate = dm->tx_rate;
103                 else /*force rate*/
104                         tx_rate = (u8)rate;
105         }
106
107         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK, "Call:%s tx_rate=0x%X\n",
108                      __func__, tx_rate);
109
110         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
111                      "pRF->default_ofdm_index=%d   pRF->default_cck_index=%d\n",
112                      cali_info->default_ofdm_index,
113                      cali_info->default_cck_index);
114
115         ODM_RT_TRACE(
116                 dm, ODM_COMP_TX_PWR_TRACK,
117                 "pRF->absolute_ofdm_swing_idx=%d   pRF->remnant_ofdm_swing_idx=%d   pRF->absolute_cck_swing_idx=%d   pRF->remnant_cck_swing_idx=%d   rf_path=%d\n",
118                 cali_info->absolute_ofdm_swing_idx[rf_path],
119                 cali_info->remnant_ofdm_swing_idx[rf_path],
120                 cali_info->absolute_cck_swing_idx[rf_path],
121                 cali_info->remnant_cck_swing_idx, rf_path);
122
123         if (dm->number_linked_client != 0)
124                 tx_power_index = odm_get_tx_power_index(
125                         dm, (enum odm_rf_radio_path)rf_path, tx_rate,
126                         band_width, channel);
127
128         if (tx_power_index >= 63)
129                 tx_power_index = 63;
130
131         tx_power_index_offset = 63 - tx_power_index;
132
133         ODM_RT_TRACE(dm, ODM_COMP_TX_PWR_TRACK,
134                      "tx_power_index=%d tx_power_index_offset=%d rf_path=%d\n",
135                      tx_power_index, tx_power_index_offset, rf_path);
136
137         if (method ==
138             BBSWING) { /*use for mp driver clean power tracking status*/
139                 switch (rf_path) {
140                 case ODM_RF_PATH_A:
141                         odm_set_bb_reg(
142                                 dm, 0xC94, (BIT(29) | BIT(28) | BIT(27) |
143                                             BIT(26) | BIT(25)),
144                                 cali_info->absolute_ofdm_swing_idx[rf_path]);
145                         odm_set_bb_reg(
146                                 dm, REG_A_TX_SCALE_JAGUAR, 0xFFE00000,
147                                 tx_scaling_table_jaguar
148                                         [cali_info
149                                                  ->bb_swing_idx_ofdm[rf_path]]);
150                         break;
151                 case ODM_RF_PATH_B:
152                         odm_set_bb_reg(
153                                 dm, 0xE94, (BIT(29) | BIT(28) | BIT(27) |
154                                             BIT(26) | BIT(25)),
155                                 cali_info->absolute_ofdm_swing_idx[rf_path]);
156                         odm_set_bb_reg(
157                                 dm, REG_B_TX_SCALE_JAGUAR, 0xFFE00000,
158                                 tx_scaling_table_jaguar
159                                         [cali_info
160                                                  ->bb_swing_idx_ofdm[rf_path]]);
161                         break;
162
163                 default:
164                         break;
165                 }
166         } else if (method == MIX_MODE) {
167                 switch (rf_path) {
168                 case ODM_RF_PATH_A:
169                         get_mix_mode_tx_agc_bb_swing_offset_8822b(
170                                 dm, method, rf_path, tx_power_index_offset);
171                         odm_set_bb_reg(
172                                 dm, 0xC94, (BIT(29) | BIT(28) | BIT(27) |
173                                             BIT(26) | BIT(25)),
174                                 cali_info->absolute_ofdm_swing_idx[rf_path]);
175                         odm_set_bb_reg(
176                                 dm, REG_A_TX_SCALE_JAGUAR, 0xFFE00000,
177                                 tx_scaling_table_jaguar
178                                         [cali_info
179                                                  ->bb_swing_idx_ofdm[rf_path]]);
180
181                         ODM_RT_TRACE(
182                                 dm, ODM_COMP_TX_PWR_TRACK,
183                                 "TXAGC(0xC94)=0x%x BBSwing(0xc1c)=0x%x BBSwingIndex=%d rf_path=%d\n",
184                                 odm_get_bb_reg(dm, 0xC94,
185                                                (BIT(29) | BIT(28) | BIT(27) |
186                                                 BIT(26) | BIT(25))),
187                                 odm_get_bb_reg(dm, 0xc1c, 0xFFE00000),
188                                 cali_info->bb_swing_idx_ofdm[rf_path], rf_path);
189                         break;
190
191                 case ODM_RF_PATH_B:
192                         get_mix_mode_tx_agc_bb_swing_offset_8822b(
193                                 dm, method, rf_path, tx_power_index_offset);
194                         odm_set_bb_reg(
195                                 dm, 0xE94, (BIT(29) | BIT(28) | BIT(27) |
196                                             BIT(26) | BIT(25)),
197                                 cali_info->absolute_ofdm_swing_idx[rf_path]);
198                         odm_set_bb_reg(
199                                 dm, REG_B_TX_SCALE_JAGUAR, 0xFFE00000,
200                                 tx_scaling_table_jaguar
201                                         [cali_info
202                                                  ->bb_swing_idx_ofdm[rf_path]]);
203
204                         ODM_RT_TRACE(
205                                 dm, ODM_COMP_TX_PWR_TRACK,
206                                 "TXAGC(0xE94)=0x%x BBSwing(0xe1c)=0x%x BBSwingIndex=%d rf_path=%d\n",
207                                 odm_get_bb_reg(dm, 0xE94,
208                                                (BIT(29) | BIT(28) | BIT(27) |
209                                                 BIT(26) | BIT(25))),
210                                 odm_get_bb_reg(dm, 0xe1c, 0xFFE00000),
211                                 cali_info->bb_swing_idx_ofdm[rf_path], rf_path);
212                         break;
213
214                 default:
215                         break;
216                 }
217         }
218 }
219
220 void get_delta_swing_table_8822b(void *dm_void, u8 **temperature_up_a,
221                                  u8 **temperature_down_a, u8 **temperature_up_b,
222                                  u8 **temperature_down_b)
223 {
224         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
225         struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
226
227         struct rtl_priv *rtlpriv = (struct rtl_priv *)dm->adapter;
228         struct rtl_phy *rtlphy = &rtlpriv->phy;
229         u8 channel = rtlphy->current_channel;
230
231         *temperature_up_a = cali_info->delta_swing_table_idx_2ga_p;
232         *temperature_down_a = cali_info->delta_swing_table_idx_2ga_n;
233         *temperature_up_b = cali_info->delta_swing_table_idx_2gb_p;
234         *temperature_down_b = cali_info->delta_swing_table_idx_2gb_n;
235
236         if (channel >= 36 && channel <= 64) {
237                 *temperature_up_a = cali_info->delta_swing_table_idx_5ga_p[0];
238                 *temperature_down_a = cali_info->delta_swing_table_idx_5ga_n[0];
239                 *temperature_up_b = cali_info->delta_swing_table_idx_5gb_p[0];
240                 *temperature_down_b = cali_info->delta_swing_table_idx_5gb_n[0];
241         } else if (channel >= 100 && channel <= 144) {
242                 *temperature_up_a = cali_info->delta_swing_table_idx_5ga_p[1];
243                 *temperature_down_a = cali_info->delta_swing_table_idx_5ga_n[1];
244                 *temperature_up_b = cali_info->delta_swing_table_idx_5gb_p[1];
245                 *temperature_down_b = cali_info->delta_swing_table_idx_5gb_n[1];
246         } else if (channel >= 149 && channel <= 177) {
247                 *temperature_up_a = cali_info->delta_swing_table_idx_5ga_p[2];
248                 *temperature_down_a = cali_info->delta_swing_table_idx_5ga_n[2];
249                 *temperature_up_b = cali_info->delta_swing_table_idx_5gb_p[2];
250                 *temperature_down_b = cali_info->delta_swing_table_idx_5gb_n[2];
251         }
252 }
253
254 static void _phy_lc_calibrate_8822b(struct phy_dm_struct *dm)
255 {
256         u32 lc_cal = 0, cnt = 0;
257
258         /*backup RF0x18*/
259         lc_cal = odm_get_rf_reg(dm, ODM_RF_PATH_A, RF_CHNLBW, RFREGOFFSETMASK);
260
261         /*Start LCK*/
262         odm_set_rf_reg(dm, ODM_RF_PATH_A, RF_CHNLBW, RFREGOFFSETMASK,
263                        lc_cal | 0x08000);
264
265         ODM_delay_ms(100);
266
267         for (cnt = 0; cnt < 100; cnt++) {
268                 if (odm_get_rf_reg(dm, ODM_RF_PATH_A, RF_CHNLBW, 0x8000) != 0x1)
269                         break;
270                 ODM_delay_ms(10);
271         }
272
273         /*Recover channel number*/
274         odm_set_rf_reg(dm, ODM_RF_PATH_A, RF_CHNLBW, RFREGOFFSETMASK, lc_cal);
275 }
276
277 void phy_lc_calibrate_8822b(void *dm_void)
278 {
279         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
280         bool is_start_cont_tx = false, is_single_tone = false,
281              is_carrier_suppression = false;
282         u64 start_time;
283         u64 progressing_time;
284
285         if (is_start_cont_tx || is_single_tone || is_carrier_suppression) {
286                 ODM_RT_TRACE(dm, ODM_COMP_CALIBRATION,
287                              "[LCK]continues TX ing !!! LCK return\n");
288                 return;
289         }
290
291         start_time = odm_get_current_time(dm);
292         _phy_lc_calibrate_8822b(dm);
293         progressing_time = odm_get_progressing_time(dm, start_time);
294         ODM_RT_TRACE(dm, ODM_COMP_CALIBRATION,
295                      "[LCK]LCK progressing_time = %lld\n", progressing_time);
296 }
297
298 void configure_txpower_track_8822b(struct txpwrtrack_cfg *config)
299 {
300         config->swing_table_size_cck = TXSCALE_TABLE_SIZE;
301         config->swing_table_size_ofdm = TXSCALE_TABLE_SIZE;
302         config->threshold_iqk = IQK_THRESHOLD;
303         config->threshold_dpk = DPK_THRESHOLD;
304         config->average_thermal_num = AVG_THERMAL_NUM_8822B;
305         config->rf_path_count = MAX_PATH_NUM_8822B;
306         config->thermal_reg_addr = RF_T_METER_8822B;
307
308         config->odm_tx_pwr_track_set_pwr = odm_tx_pwr_track_set_pwr8822b;
309         config->do_iqk = do_iqk_8822b;
310         config->phy_lc_calibrate = phy_lc_calibrate_8822b;
311
312         config->get_delta_swing_table = get_delta_swing_table_8822b;
313 }
314
315 void phy_set_rf_path_switch_8822b(struct phy_dm_struct *dm, bool is_main)
316 {
317         /*BY SY Request */
318         odm_set_bb_reg(dm, 0x4C, (BIT(24) | BIT(23)), 0x2);
319         odm_set_bb_reg(dm, 0x974, 0xff, 0xff);
320
321         /*odm_set_bb_reg(dm, 0x1991, 0x3, 0x0);*/
322         odm_set_bb_reg(dm, 0x1990, (BIT(9) | BIT(8)), 0x0);
323
324         /*odm_set_bb_reg(dm, 0xCBE, 0x8, 0x0);*/
325         odm_set_bb_reg(dm, 0xCBC, BIT(19), 0x0);
326
327         odm_set_bb_reg(dm, 0xCB4, 0xff, 0x77);
328
329         odm_set_bb_reg(dm, 0x70, MASKBYTE3, 0x0e);
330         odm_set_bb_reg(dm, 0x1704, MASKDWORD, 0x0000ff00);
331         odm_set_bb_reg(dm, 0x1700, MASKDWORD, 0xc00f0038);
332
333         if (is_main) {
334                 /*odm_set_bb_reg(dm, 0xCBD, 0x3, 0x2);          WiFi */
335                 odm_set_bb_reg(dm, 0xCBC, (BIT(9) | BIT(8)), 0x2); /*WiFi */
336         } else {
337                 /*odm_set_bb_reg(dm, 0xCBD, 0x3, 0x1);   BT*/
338                 odm_set_bb_reg(dm, 0xCBC, (BIT(9) | BIT(8)), 0x1); /*BT*/
339         }
340 }