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