1 /*
2  * Copyright (c) 2010 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include "hw.h"
18 #include "ar9003_phy.h"
19 
ar9003_paprd_enable(struct ath_hw * ah,bool val)20 void ar9003_paprd_enable(struct ath_hw *ah, bool val)
21 {
22 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
23 	struct ath9k_channel *chan = ah->curchan;
24 
25 	if (val) {
26 		ah->paprd_table_write_done = true;
27 
28 		ah->eep_ops->set_txpower(ah, chan,
29 				ath9k_regd_get_ctl(regulatory, chan),
30 				chan->chan->max_antenna_gain * 2,
31 				chan->chan->max_power * 2,
32 				min((u32) MAX_RATE_POWER,
33 				(u32) regulatory->power_limit), false);
34 	}
35 
36 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
37 		      AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
38 	if (ah->caps.tx_chainmask & BIT(1))
39 		REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1,
40 			      AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
41 	if (ah->caps.tx_chainmask & BIT(2))
42 		REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2,
43 			      AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
44 }
45 EXPORT_SYMBOL(ar9003_paprd_enable);
46 
ar9003_get_training_power_2g(struct ath_hw * ah)47 static int ar9003_get_training_power_2g(struct ath_hw *ah)
48 {
49 	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
50 	struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G;
51 	unsigned int power, scale, delta;
52 
53 	scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1);
54 	power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
55 			       AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
56 
57 	delta = abs((int) ah->paprd_target_power - (int) power);
58 	if (delta > scale)
59 		return -1;
60 
61 	if (delta < 4)
62 		power -= 4 - delta;
63 
64 	return power;
65 }
66 
ar9003_get_training_power_5g(struct ath_hw * ah)67 static int ar9003_get_training_power_5g(struct ath_hw *ah)
68 {
69 	struct ath_common *common = ath9k_hw_common(ah);
70 	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
71 	struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;
72 	struct ath9k_channel *chan = ah->curchan;
73 	unsigned int power, scale, delta;
74 
75 	if (chan->channel >= 5700)
76 		scale = MS(le32_to_cpu(hdr->papdRateMaskHt20),
77 			   AR9300_PAPRD_SCALE_1);
78 	else if (chan->channel >= 5400)
79 		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
80 			   AR9300_PAPRD_SCALE_2);
81 	else
82 		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
83 			   AR9300_PAPRD_SCALE_1);
84 
85 	if (IS_CHAN_HT40(chan))
86 		power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
87 			AR_PHY_POWERTX_RATE8_POWERTXHT40_5);
88 	else
89 		power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6,
90 			AR_PHY_POWERTX_RATE6_POWERTXHT20_5);
91 
92 	power += scale;
93 	delta = abs((int) ah->paprd_target_power - (int) power);
94 	if (delta > scale)
95 		return -1;
96 
97 	power += 2 * get_streams(common->tx_chainmask);
98 	return power;
99 }
100 
ar9003_paprd_setup_single_table(struct ath_hw * ah)101 static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
102 {
103 	struct ath_common *common = ath9k_hw_common(ah);
104 	static const u32 ctrl0[3] = {
105 		AR_PHY_PAPRD_CTRL0_B0,
106 		AR_PHY_PAPRD_CTRL0_B1,
107 		AR_PHY_PAPRD_CTRL0_B2
108 	};
109 	static const u32 ctrl1[3] = {
110 		AR_PHY_PAPRD_CTRL1_B0,
111 		AR_PHY_PAPRD_CTRL1_B1,
112 		AR_PHY_PAPRD_CTRL1_B2
113 	};
114 	int training_power;
115 	int i;
116 
117 	if (IS_CHAN_2GHZ(ah->curchan))
118 		training_power = ar9003_get_training_power_2g(ah);
119 	else
120 		training_power = ar9003_get_training_power_5g(ah);
121 
122 	if (training_power < 0) {
123 		ath_dbg(common, ATH_DBG_CALIBRATE,
124 			"PAPRD target power delta out of range");
125 		return -ERANGE;
126 	}
127 	ah->paprd_training_power = training_power;
128 	ath_dbg(common, ATH_DBG_CALIBRATE,
129 		"Training power: %d, Target power: %d\n",
130 		ah->paprd_training_power, ah->paprd_target_power);
131 
132 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
133 		      ah->paprd_ratemask);
134 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,
135 		      ah->paprd_ratemask);
136 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
137 		      ah->paprd_ratemask_ht40);
138 
139 	for (i = 0; i < ah->caps.max_txchains; i++) {
140 		REG_RMW_FIELD(ah, ctrl0[i],
141 			      AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1);
142 		REG_RMW_FIELD(ah, ctrl1[i],
143 			      AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE, 1);
144 		REG_RMW_FIELD(ah, ctrl1[i],
145 			      AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE, 1);
146 		REG_RMW_FIELD(ah, ctrl1[i],
147 			      AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0);
148 		REG_RMW_FIELD(ah, ctrl1[i],
149 			      AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK, 181);
150 		REG_RMW_FIELD(ah, ctrl1[i],
151 			      AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT, 361);
152 		REG_RMW_FIELD(ah, ctrl1[i],
153 			      AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0);
154 		REG_RMW_FIELD(ah, ctrl0[i],
155 			      AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH, 3);
156 	}
157 
158 	ar9003_paprd_enable(ah, false);
159 
160 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
161 		      AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP, 0x30);
162 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
163 		      AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE, 1);
164 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
165 		      AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE, 1);
166 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
167 		      AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE, 0);
168 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
169 		      AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE, 0);
170 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
171 		      AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28);
172 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
173 		      AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1);
174 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2,
175 		      AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147);
176 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
177 		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4);
178 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
179 		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN, 4);
180 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
181 		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);
182 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
183 		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);
184 	if (AR_SREV_9485(ah))
185 		REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
186 			      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
187 			      -3);
188 	else
189 		REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
190 			      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
191 			      -6);
192 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
193 		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE,
194 		      -15);
195 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
196 		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1);
197 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
198 		      AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA, 0);
199 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
200 		      AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR, 400);
201 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
202 		      AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES,
203 		      100);
204 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_0_B0,
205 		      AR_PHY_PAPRD_PRE_POST_SCALING, 261376);
206 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_1_B0,
207 		      AR_PHY_PAPRD_PRE_POST_SCALING, 248079);
208 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_2_B0,
209 		      AR_PHY_PAPRD_PRE_POST_SCALING, 233759);
210 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0,
211 		      AR_PHY_PAPRD_PRE_POST_SCALING, 220464);
212 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0,
213 		      AR_PHY_PAPRD_PRE_POST_SCALING, 208194);
214 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0,
215 		      AR_PHY_PAPRD_PRE_POST_SCALING, 196949);
216 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0,
217 		      AR_PHY_PAPRD_PRE_POST_SCALING, 185706);
218 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0,
219 		      AR_PHY_PAPRD_PRE_POST_SCALING, 175487);
220 	return 0;
221 }
222 
ar9003_paprd_get_gain_table(struct ath_hw * ah)223 static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
224 {
225 	u32 *entry = ah->paprd_gain_table_entries;
226 	u8 *index = ah->paprd_gain_table_index;
227 	u32 reg = AR_PHY_TXGAIN_TABLE;
228 	int i;
229 
230 	memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
231 	memset(index, 0, sizeof(ah->paprd_gain_table_index));
232 
233 	for (i = 0; i < 32; i++) {
234 		entry[i] = REG_READ(ah, reg);
235 		index[i] = (entry[i] >> 24) & 0xff;
236 		reg += 4;
237 	}
238 }
239 
ar9003_get_desired_gain(struct ath_hw * ah,int chain,int target_power)240 static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
241 					    int target_power)
242 {
243 	int olpc_gain_delta = 0;
244 	int alpha_therm, alpha_volt;
245 	int therm_cal_value, volt_cal_value;
246 	int therm_value, volt_value;
247 	int thermal_gain_corr, voltage_gain_corr;
248 	int desired_scale, desired_gain = 0;
249 	u32 reg;
250 
251 	REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
252 		    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
253 	desired_scale = REG_READ_FIELD(ah, AR_PHY_TPC_12,
254 				       AR_PHY_TPC_12_DESIRED_SCALE_HT40_5);
255 	alpha_therm = REG_READ_FIELD(ah, AR_PHY_TPC_19,
256 				     AR_PHY_TPC_19_ALPHA_THERM);
257 	alpha_volt = REG_READ_FIELD(ah, AR_PHY_TPC_19,
258 				    AR_PHY_TPC_19_ALPHA_VOLT);
259 	therm_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18,
260 					 AR_PHY_TPC_18_THERM_CAL_VALUE);
261 	volt_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18,
262 					AR_PHY_TPC_18_VOLT_CAL_VALUE);
263 	therm_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
264 				     AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE);
265 	volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
266 				    AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE);
267 
268 	if (chain == 0)
269 		reg = AR_PHY_TPC_11_B0;
270 	else if (chain == 1)
271 		reg = AR_PHY_TPC_11_B1;
272 	else
273 		reg = AR_PHY_TPC_11_B2;
274 
275 	olpc_gain_delta = REG_READ_FIELD(ah, reg,
276 					 AR_PHY_TPC_11_OLPC_GAIN_DELTA);
277 
278 	if (olpc_gain_delta >= 128)
279 		olpc_gain_delta = olpc_gain_delta - 256;
280 
281 	thermal_gain_corr = (alpha_therm * (therm_value - therm_cal_value) +
282 			     (256 / 2)) / 256;
283 	voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
284 			     (128 / 2)) / 128;
285 	desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
286 	    voltage_gain_corr + desired_scale;
287 
288 	return desired_gain;
289 }
290 
ar9003_tx_force_gain(struct ath_hw * ah,unsigned int gain_index)291 static void ar9003_tx_force_gain(struct ath_hw *ah, unsigned int gain_index)
292 {
293 	int selected_gain_entry, txbb1dbgain, txbb6dbgain, txmxrgain;
294 	int padrvgnA, padrvgnB, padrvgnC, padrvgnD;
295 	u32 *gain_table_entries = ah->paprd_gain_table_entries;
296 
297 	selected_gain_entry = gain_table_entries[gain_index];
298 	txbb1dbgain = selected_gain_entry & 0x7;
299 	txbb6dbgain = (selected_gain_entry >> 3) & 0x3;
300 	txmxrgain = (selected_gain_entry >> 5) & 0xf;
301 	padrvgnA = (selected_gain_entry >> 9) & 0xf;
302 	padrvgnB = (selected_gain_entry >> 13) & 0xf;
303 	padrvgnC = (selected_gain_entry >> 17) & 0xf;
304 	padrvgnD = (selected_gain_entry >> 21) & 0x3;
305 
306 	REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
307 		      AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN, txbb1dbgain);
308 	REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
309 		      AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN, txbb6dbgain);
310 	REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
311 		      AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN, txmxrgain);
312 	REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
313 		      AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA, padrvgnA);
314 	REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
315 		      AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB, padrvgnB);
316 	REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
317 		      AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC, padrvgnC);
318 	REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
319 		      AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND, padrvgnD);
320 	REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
321 		      AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL, 0);
322 	REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
323 		      AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN, 0);
324 	REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCED_DAC_GAIN, 0);
325 	REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCE_DAC_GAIN, 0);
326 }
327 
find_expn(int num)328 static inline int find_expn(int num)
329 {
330 	return fls(num) - 1;
331 }
332 
find_proper_scale(int expn,int N)333 static inline int find_proper_scale(int expn, int N)
334 {
335 	return (expn > N) ? expn - 10 : 0;
336 }
337 
338 #define NUM_BIN 23
339 
create_pa_curve(u32 * data_L,u32 * data_U,u32 * pa_table,u16 * gain)340 static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain)
341 {
342 	unsigned int thresh_accum_cnt;
343 	int x_est[NUM_BIN + 1], Y[NUM_BIN + 1], theta[NUM_BIN + 1];
344 	int PA_in[NUM_BIN + 1];
345 	int B1_tmp[NUM_BIN + 1], B2_tmp[NUM_BIN + 1];
346 	unsigned int B1_abs_max, B2_abs_max;
347 	int max_index, scale_factor;
348 	int y_est[NUM_BIN + 1];
349 	int x_est_fxp1_nonlin, x_tilde[NUM_BIN + 1];
350 	unsigned int x_tilde_abs;
351 	int G_fxp, Y_intercept, order_x_by_y, M, I, L, sum_y_sqr, sum_y_quad;
352 	int Q_x, Q_B1, Q_B2, beta_raw, alpha_raw, scale_B;
353 	int Q_scale_B, Q_beta, Q_alpha, alpha, beta, order_1, order_2;
354 	int order1_5x, order2_3x, order1_5x_rem, order2_3x_rem;
355 	int y5, y3, tmp;
356 	int theta_low_bin = 0;
357 	int i;
358 
359 	/* disregard any bin that contains <= 16 samples */
360 	thresh_accum_cnt = 16;
361 	scale_factor = 5;
362 	max_index = 0;
363 	memset(theta, 0, sizeof(theta));
364 	memset(x_est, 0, sizeof(x_est));
365 	memset(Y, 0, sizeof(Y));
366 	memset(y_est, 0, sizeof(y_est));
367 	memset(x_tilde, 0, sizeof(x_tilde));
368 
369 	for (i = 0; i < NUM_BIN; i++) {
370 		s32 accum_cnt, accum_tx, accum_rx, accum_ang;
371 
372 		/* number of samples */
373 		accum_cnt = data_L[i] & 0xffff;
374 
375 		if (accum_cnt <= thresh_accum_cnt)
376 			continue;
377 
378 		/* sum(tx amplitude) */
379 		accum_tx = ((data_L[i] >> 16) & 0xffff) |
380 		    ((data_U[i] & 0x7ff) << 16);
381 
382 		/* sum(rx amplitude distance to lower bin edge) */
383 		accum_rx = ((data_U[i] >> 11) & 0x1f) |
384 		    ((data_L[i + 23] & 0xffff) << 5);
385 
386 		/* sum(angles) */
387 		accum_ang = ((data_L[i + 23] >> 16) & 0xffff) |
388 		    ((data_U[i + 23] & 0x7ff) << 16);
389 
390 		accum_tx <<= scale_factor;
391 		accum_rx <<= scale_factor;
392 		x_est[i + 1] = (((accum_tx + accum_cnt) / accum_cnt) + 32) >>
393 		    scale_factor;
394 
395 		Y[i + 1] = ((((accum_rx + accum_cnt) / accum_cnt) + 32) >>
396 			    scale_factor) +
397 			    (1 << scale_factor) * max_index + 16;
398 
399 		if (accum_ang >= (1 << 26))
400 			accum_ang -= 1 << 27;
401 
402 		theta[i + 1] = ((accum_ang * (1 << scale_factor)) + accum_cnt) /
403 		    accum_cnt;
404 
405 		max_index++;
406 	}
407 
408 	/*
409 	 * Find average theta of first 5 bin and all of those to same value.
410 	 * Curve is linear at that range.
411 	 */
412 	for (i = 1; i < 6; i++)
413 		theta_low_bin += theta[i];
414 
415 	theta_low_bin = theta_low_bin / 5;
416 	for (i = 1; i < 6; i++)
417 		theta[i] = theta_low_bin;
418 
419 	/* Set values at origin */
420 	theta[0] = theta_low_bin;
421 	for (i = 0; i <= max_index; i++)
422 		theta[i] -= theta_low_bin;
423 
424 	x_est[0] = 0;
425 	Y[0] = 0;
426 	scale_factor = 8;
427 
428 	/* low signal gain */
429 	if (x_est[6] == x_est[3])
430 		return false;
431 
432 	G_fxp =
433 	    (((Y[6] - Y[3]) * 1 << scale_factor) +
434 	     (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]);
435 
436 	/* prevent division by zero */
437 	if (G_fxp == 0)
438 		return false;
439 
440 	Y_intercept =
441 	    (G_fxp * (x_est[0] - x_est[3]) +
442 	     (1 << scale_factor)) / (1 << scale_factor) + Y[3];
443 
444 	for (i = 0; i <= max_index; i++)
445 		y_est[i] = Y[i] - Y_intercept;
446 
447 	for (i = 0; i <= 3; i++) {
448 		y_est[i] = i * 32;
449 		x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp;
450 	}
451 
452 	if (y_est[max_index] == 0)
453 		return false;
454 
455 	x_est_fxp1_nonlin =
456 	    x_est[max_index] - ((1 << scale_factor) * y_est[max_index] +
457 				G_fxp) / G_fxp;
458 
459 	order_x_by_y =
460 	    (x_est_fxp1_nonlin + y_est[max_index]) / y_est[max_index];
461 
462 	if (order_x_by_y == 0)
463 		M = 10;
464 	else if (order_x_by_y == 1)
465 		M = 9;
466 	else
467 		M = 8;
468 
469 	I = (max_index > 15) ? 7 : max_index >> 1;
470 	L = max_index - I;
471 	scale_factor = 8;
472 	sum_y_sqr = 0;
473 	sum_y_quad = 0;
474 	x_tilde_abs = 0;
475 
476 	for (i = 0; i <= L; i++) {
477 		unsigned int y_sqr;
478 		unsigned int y_quad;
479 		unsigned int tmp_abs;
480 
481 		/* prevent division by zero */
482 		if (y_est[i + I] == 0)
483 			return false;
484 
485 		x_est_fxp1_nonlin =
486 		    x_est[i + I] - ((1 << scale_factor) * y_est[i + I] +
487 				    G_fxp) / G_fxp;
488 
489 		x_tilde[i] =
490 		    (x_est_fxp1_nonlin * (1 << M) + y_est[i + I]) / y_est[i +
491 									  I];
492 		x_tilde[i] =
493 		    (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I];
494 		x_tilde[i] =
495 		    (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I];
496 		y_sqr =
497 		    (y_est[i + I] * y_est[i + I] +
498 		     (scale_factor * scale_factor)) / (scale_factor *
499 						       scale_factor);
500 		tmp_abs = abs(x_tilde[i]);
501 		if (tmp_abs > x_tilde_abs)
502 			x_tilde_abs = tmp_abs;
503 
504 		y_quad = y_sqr * y_sqr;
505 		sum_y_sqr = sum_y_sqr + y_sqr;
506 		sum_y_quad = sum_y_quad + y_quad;
507 		B1_tmp[i] = y_sqr * (L + 1);
508 		B2_tmp[i] = y_sqr;
509 	}
510 
511 	B1_abs_max = 0;
512 	B2_abs_max = 0;
513 	for (i = 0; i <= L; i++) {
514 		int abs_val;
515 
516 		B1_tmp[i] -= sum_y_sqr;
517 		B2_tmp[i] = sum_y_quad - sum_y_sqr * B2_tmp[i];
518 
519 		abs_val = abs(B1_tmp[i]);
520 		if (abs_val > B1_abs_max)
521 			B1_abs_max = abs_val;
522 
523 		abs_val = abs(B2_tmp[i]);
524 		if (abs_val > B2_abs_max)
525 			B2_abs_max = abs_val;
526 	}
527 
528 	Q_x = find_proper_scale(find_expn(x_tilde_abs), 10);
529 	Q_B1 = find_proper_scale(find_expn(B1_abs_max), 10);
530 	Q_B2 = find_proper_scale(find_expn(B2_abs_max), 10);
531 
532 	beta_raw = 0;
533 	alpha_raw = 0;
534 	for (i = 0; i <= L; i++) {
535 		x_tilde[i] = x_tilde[i] / (1 << Q_x);
536 		B1_tmp[i] = B1_tmp[i] / (1 << Q_B1);
537 		B2_tmp[i] = B2_tmp[i] / (1 << Q_B2);
538 		beta_raw = beta_raw + B1_tmp[i] * x_tilde[i];
539 		alpha_raw = alpha_raw + B2_tmp[i] * x_tilde[i];
540 	}
541 
542 	scale_B =
543 	    ((sum_y_quad / scale_factor) * (L + 1) -
544 	     (sum_y_sqr / scale_factor) * sum_y_sqr) * scale_factor;
545 
546 	Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10);
547 	scale_B = scale_B / (1 << Q_scale_B);
548 	if (scale_B == 0)
549 		return false;
550 	Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10);
551 	Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10);
552 	beta_raw = beta_raw / (1 << Q_beta);
553 	alpha_raw = alpha_raw / (1 << Q_alpha);
554 	alpha = (alpha_raw << 10) / scale_B;
555 	beta = (beta_raw << 10) / scale_B;
556 	order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B;
557 	order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B;
558 	order1_5x = order_1 / 5;
559 	order2_3x = order_2 / 3;
560 	order1_5x_rem = order_1 - 5 * order1_5x;
561 	order2_3x_rem = order_2 - 3 * order2_3x;
562 
563 	for (i = 0; i < PAPRD_TABLE_SZ; i++) {
564 		tmp = i * 32;
565 		y5 = ((beta * tmp) >> 6) >> order1_5x;
566 		y5 = (y5 * tmp) >> order1_5x;
567 		y5 = (y5 * tmp) >> order1_5x;
568 		y5 = (y5 * tmp) >> order1_5x;
569 		y5 = (y5 * tmp) >> order1_5x;
570 		y5 = y5 >> order1_5x_rem;
571 		y3 = (alpha * tmp) >> order2_3x;
572 		y3 = (y3 * tmp) >> order2_3x;
573 		y3 = (y3 * tmp) >> order2_3x;
574 		y3 = y3 >> order2_3x_rem;
575 		PA_in[i] = y5 + y3 + (256 * tmp) / G_fxp;
576 
577 		if (i >= 2) {
578 			tmp = PA_in[i] - PA_in[i - 1];
579 			if (tmp < 0)
580 				PA_in[i] =
581 				    PA_in[i - 1] + (PA_in[i - 1] -
582 						    PA_in[i - 2]);
583 		}
584 
585 		PA_in[i] = (PA_in[i] < 1400) ? PA_in[i] : 1400;
586 	}
587 
588 	beta_raw = 0;
589 	alpha_raw = 0;
590 
591 	for (i = 0; i <= L; i++) {
592 		int theta_tilde =
593 		    ((theta[i + I] << M) + y_est[i + I]) / y_est[i + I];
594 		theta_tilde =
595 		    ((theta_tilde << M) + y_est[i + I]) / y_est[i + I];
596 		theta_tilde =
597 		    ((theta_tilde << M) + y_est[i + I]) / y_est[i + I];
598 		beta_raw = beta_raw + B1_tmp[i] * theta_tilde;
599 		alpha_raw = alpha_raw + B2_tmp[i] * theta_tilde;
600 	}
601 
602 	Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10);
603 	Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10);
604 	beta_raw = beta_raw / (1 << Q_beta);
605 	alpha_raw = alpha_raw / (1 << Q_alpha);
606 
607 	alpha = (alpha_raw << 10) / scale_B;
608 	beta = (beta_raw << 10) / scale_B;
609 	order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B + 5;
610 	order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B + 5;
611 	order1_5x = order_1 / 5;
612 	order2_3x = order_2 / 3;
613 	order1_5x_rem = order_1 - 5 * order1_5x;
614 	order2_3x_rem = order_2 - 3 * order2_3x;
615 
616 	for (i = 0; i < PAPRD_TABLE_SZ; i++) {
617 		int PA_angle;
618 
619 		/* pa_table[4] is calculated from PA_angle for i=5 */
620 		if (i == 4)
621 			continue;
622 
623 		tmp = i * 32;
624 		if (beta > 0)
625 			y5 = (((beta * tmp - 64) >> 6) -
626 			      (1 << order1_5x)) / (1 << order1_5x);
627 		else
628 			y5 = ((((beta * tmp - 64) >> 6) +
629 			       (1 << order1_5x)) / (1 << order1_5x));
630 
631 		y5 = (y5 * tmp) / (1 << order1_5x);
632 		y5 = (y5 * tmp) / (1 << order1_5x);
633 		y5 = (y5 * tmp) / (1 << order1_5x);
634 		y5 = (y5 * tmp) / (1 << order1_5x);
635 		y5 = y5 / (1 << order1_5x_rem);
636 
637 		if (beta > 0)
638 			y3 = (alpha * tmp -
639 			      (1 << order2_3x)) / (1 << order2_3x);
640 		else
641 			y3 = (alpha * tmp +
642 			      (1 << order2_3x)) / (1 << order2_3x);
643 		y3 = (y3 * tmp) / (1 << order2_3x);
644 		y3 = (y3 * tmp) / (1 << order2_3x);
645 		y3 = y3 / (1 << order2_3x_rem);
646 
647 		if (i < 4) {
648 			PA_angle = 0;
649 		} else {
650 			PA_angle = y5 + y3;
651 			if (PA_angle < -150)
652 				PA_angle = -150;
653 			else if (PA_angle > 150)
654 				PA_angle = 150;
655 		}
656 
657 		pa_table[i] = ((PA_in[i] & 0x7ff) << 11) + (PA_angle & 0x7ff);
658 		if (i == 5) {
659 			PA_angle = (PA_angle + 2) >> 1;
660 			pa_table[i - 1] = ((PA_in[i - 1] & 0x7ff) << 11) +
661 			    (PA_angle & 0x7ff);
662 		}
663 	}
664 
665 	*gain = G_fxp;
666 	return true;
667 }
668 
ar9003_paprd_populate_single_table(struct ath_hw * ah,struct ath9k_hw_cal_data * caldata,int chain)669 void ar9003_paprd_populate_single_table(struct ath_hw *ah,
670 					struct ath9k_hw_cal_data *caldata,
671 					int chain)
672 {
673 	u32 *paprd_table_val = caldata->pa_table[chain];
674 	u32 small_signal_gain = caldata->small_signal_gain[chain];
675 	u32 training_power = ah->paprd_training_power;
676 	u32 reg = 0;
677 	int i;
678 
679 	if (chain == 0)
680 		reg = AR_PHY_PAPRD_MEM_TAB_B0;
681 	else if (chain == 1)
682 		reg = AR_PHY_PAPRD_MEM_TAB_B1;
683 	else if (chain == 2)
684 		reg = AR_PHY_PAPRD_MEM_TAB_B2;
685 
686 	for (i = 0; i < PAPRD_TABLE_SZ; i++) {
687 		REG_WRITE(ah, reg, paprd_table_val[i]);
688 		reg = reg + 4;
689 	}
690 
691 	if (chain == 0)
692 		reg = AR_PHY_PA_GAIN123_B0;
693 	else if (chain == 1)
694 		reg = AR_PHY_PA_GAIN123_B1;
695 	else
696 		reg = AR_PHY_PA_GAIN123_B2;
697 
698 	REG_RMW_FIELD(ah, reg, AR_PHY_PA_GAIN123_PA_GAIN1, small_signal_gain);
699 
700 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B0,
701 		      AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
702 		      training_power);
703 
704 	if (ah->caps.tx_chainmask & BIT(1))
705 		REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1,
706 			      AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
707 			      training_power);
708 
709 	if (ah->caps.tx_chainmask & BIT(2))
710 		REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2,
711 			      AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
712 			      training_power);
713 }
714 EXPORT_SYMBOL(ar9003_paprd_populate_single_table);
715 
ar9003_paprd_setup_gain_table(struct ath_hw * ah,int chain)716 int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
717 {
718 	unsigned int i, desired_gain, gain_index;
719 	unsigned int train_power = ah->paprd_training_power;
720 
721 	desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
722 
723 	gain_index = 0;
724 	for (i = 0; i < 32; i++) {
725 		if (ah->paprd_gain_table_index[i] >= desired_gain)
726 			break;
727 		gain_index++;
728 	}
729 
730 	ar9003_tx_force_gain(ah, gain_index);
731 
732 	REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
733 			AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
734 
735 	return 0;
736 }
737 EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
738 
ar9003_paprd_create_curve(struct ath_hw * ah,struct ath9k_hw_cal_data * caldata,int chain)739 int ar9003_paprd_create_curve(struct ath_hw *ah,
740 			      struct ath9k_hw_cal_data *caldata, int chain)
741 {
742 	u16 *small_signal_gain = &caldata->small_signal_gain[chain];
743 	u32 *pa_table = caldata->pa_table[chain];
744 	u32 *data_L, *data_U;
745 	int i, status = 0;
746 	u32 *buf;
747 	u32 reg;
748 
749 	memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain]));
750 
751 	buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC);
752 	if (!buf)
753 		return -ENOMEM;
754 
755 	data_L = &buf[0];
756 	data_U = &buf[48];
757 
758 	REG_CLR_BIT(ah, AR_PHY_CHAN_INFO_MEMORY,
759 		    AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ);
760 
761 	reg = AR_PHY_CHAN_INFO_TAB_0;
762 	for (i = 0; i < 48; i++)
763 		data_L[i] = REG_READ(ah, reg + (i << 2));
764 
765 	REG_SET_BIT(ah, AR_PHY_CHAN_INFO_MEMORY,
766 		    AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ);
767 
768 	for (i = 0; i < 48; i++)
769 		data_U[i] = REG_READ(ah, reg + (i << 2));
770 
771 	if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))
772 		status = -2;
773 
774 	REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
775 		    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
776 
777 	kfree(buf);
778 
779 	return status;
780 }
781 EXPORT_SYMBOL(ar9003_paprd_create_curve);
782 
ar9003_paprd_init_table(struct ath_hw * ah)783 int ar9003_paprd_init_table(struct ath_hw *ah)
784 {
785 	int ret;
786 
787 	ret = ar9003_paprd_setup_single_table(ah);
788 	if (ret < 0)
789 	    return ret;
790 
791 	ar9003_paprd_get_gain_table(ah);
792 	return 0;
793 }
794 EXPORT_SYMBOL(ar9003_paprd_init_table);
795 
ar9003_paprd_is_done(struct ath_hw * ah)796 bool ar9003_paprd_is_done(struct ath_hw *ah)
797 {
798 	return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
799 				AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
800 }
801 EXPORT_SYMBOL(ar9003_paprd_is_done);
802