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
get_mix_mode_tx_agc_bb_swing_offset_8822b(void * dm_void,enum pwrtrack_method method,u8 rf_path,u8 tx_power_index_offset)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 
odm_tx_pwr_track_set_pwr8822b(void * dm_void,enum pwrtrack_method method,u8 rf_path,u8 channel_mapped_index)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 
get_delta_swing_table_8822b(void * dm_void,u8 ** temperature_up_a,u8 ** temperature_down_a,u8 ** temperature_up_b,u8 ** temperature_down_b)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 
_phy_lc_calibrate_8822b(struct phy_dm_struct * dm)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 
phy_lc_calibrate_8822b(void * dm_void)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 
configure_txpower_track_8822b(struct txpwrtrack_cfg * config)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 
phy_set_rf_path_switch_8822b(struct phy_dm_struct * dm,bool is_main)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 }
341