2 * Copyright (c) 2010-2011 Atheros Communications Inc.
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.
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.
18 #include "ar9003_phy.h"
20 void ar9003_paprd_enable(struct ath_hw
*ah
, bool val
)
22 struct ath_regulatory
*regulatory
= ath9k_hw_regulatory(ah
);
23 struct ath9k_channel
*chan
= ah
->curchan
;
26 ah
->paprd_table_write_done
= true;
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);
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
);
45 EXPORT_SYMBOL(ar9003_paprd_enable
);
47 static int ar9003_get_training_power_2g(struct ath_hw
*ah
)
49 struct ath9k_channel
*chan
= ah
->curchan
;
50 unsigned int power
, scale
, delta
;
52 scale
= ar9003_get_paprd_scale_factor(ah
, chan
);
53 power
= REG_READ_FIELD(ah
, AR_PHY_POWERTX_RATE5
,
54 AR_PHY_POWERTX_RATE5_POWERTXHT20_0
);
56 delta
= abs((int) ah
->paprd_target_power
- (int) power
);
66 static int ar9003_get_training_power_5g(struct ath_hw
*ah
)
68 struct ath_common
*common
= ath9k_hw_common(ah
);
69 struct ath9k_channel
*chan
= ah
->curchan
;
70 unsigned int power
, scale
, delta
;
72 scale
= ar9003_get_paprd_scale_factor(ah
, chan
);
74 if (IS_CHAN_HT40(chan
))
75 power
= REG_READ_FIELD(ah
, AR_PHY_POWERTX_RATE8
,
76 AR_PHY_POWERTX_RATE8_POWERTXHT40_5
);
78 power
= REG_READ_FIELD(ah
, AR_PHY_POWERTX_RATE6
,
79 AR_PHY_POWERTX_RATE6_POWERTXHT20_5
);
82 delta
= abs((int) ah
->paprd_target_power
- (int) power
);
86 power
+= 2 * get_streams(common
->tx_chainmask
);
90 static int ar9003_paprd_setup_single_table(struct ath_hw
*ah
)
92 struct ath_common
*common
= ath9k_hw_common(ah
);
93 static const u32 ctrl0
[3] = {
94 AR_PHY_PAPRD_CTRL0_B0
,
95 AR_PHY_PAPRD_CTRL0_B1
,
98 static const u32 ctrl1
[3] = {
99 AR_PHY_PAPRD_CTRL1_B0
,
100 AR_PHY_PAPRD_CTRL1_B1
,
101 AR_PHY_PAPRD_CTRL1_B2
106 if (IS_CHAN_2GHZ(ah
->curchan
))
107 training_power
= ar9003_get_training_power_2g(ah
);
109 training_power
= ar9003_get_training_power_5g(ah
);
111 ath_dbg(common
, ATH_DBG_CALIBRATE
,
112 "Training power: %d, Target power: %d\n",
113 training_power
, ah
->paprd_target_power
);
115 if (training_power
< 0) {
116 ath_dbg(common
, ATH_DBG_CALIBRATE
,
117 "PAPRD target power delta out of range");
120 ah
->paprd_training_power
= training_power
;
122 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_AM2AM
, AR_PHY_PAPRD_AM2AM_MASK
,
124 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_AM2PM
, AR_PHY_PAPRD_AM2PM_MASK
,
126 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_HT40
, AR_PHY_PAPRD_HT40_MASK
,
127 ah
->paprd_ratemask_ht40
);
129 for (i
= 0; i
< ah
->caps
.max_txchains
; i
++) {
130 REG_RMW_FIELD(ah
, ctrl0
[i
],
131 AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK
, 1);
132 REG_RMW_FIELD(ah
, ctrl1
[i
],
133 AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE
, 1);
134 REG_RMW_FIELD(ah
, ctrl1
[i
],
135 AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE
, 1);
136 REG_RMW_FIELD(ah
, ctrl1
[i
],
137 AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA
, 0);
138 REG_RMW_FIELD(ah
, ctrl1
[i
],
139 AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK
, 181);
140 REG_RMW_FIELD(ah
, ctrl1
[i
],
141 AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT
, 361);
142 REG_RMW_FIELD(ah
, ctrl1
[i
],
143 AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA
, 0);
144 REG_RMW_FIELD(ah
, ctrl0
[i
],
145 AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH
, 3);
148 ar9003_paprd_enable(ah
, false);
150 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL1
,
151 AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP
, 0x30);
152 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL1
,
153 AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE
, 1);
154 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL1
,
155 AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE
, 1);
156 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL1
,
157 AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE
, 0);
158 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL1
,
159 AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE
, 0);
160 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL1
,
161 AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING
, 28);
162 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL1
,
163 AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE
, 1);
164 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL2
,
165 AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN
, 147);
166 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL3
,
167 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN
, 4);
168 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL3
,
169 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN
, 4);
170 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL3
,
171 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES
, 7);
172 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL3
,
173 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL
, 1);
174 if (AR_SREV_9485(ah
))
175 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL3
,
176 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP
,
179 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL3
,
180 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP
,
182 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL3
,
183 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE
,
185 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL3
,
186 AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE
, 1);
187 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL4
,
188 AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA
, 0);
189 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL4
,
190 AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR
, 400);
191 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_TRAINER_CNTL4
,
192 AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES
,
194 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_PRE_POST_SCALE_0_B0
,
195 AR_PHY_PAPRD_PRE_POST_SCALING
, 261376);
196 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_PRE_POST_SCALE_1_B0
,
197 AR_PHY_PAPRD_PRE_POST_SCALING
, 248079);
198 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_PRE_POST_SCALE_2_B0
,
199 AR_PHY_PAPRD_PRE_POST_SCALING
, 233759);
200 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0
,
201 AR_PHY_PAPRD_PRE_POST_SCALING
, 220464);
202 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0
,
203 AR_PHY_PAPRD_PRE_POST_SCALING
, 208194);
204 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0
,
205 AR_PHY_PAPRD_PRE_POST_SCALING
, 196949);
206 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0
,
207 AR_PHY_PAPRD_PRE_POST_SCALING
, 185706);
208 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0
,
209 AR_PHY_PAPRD_PRE_POST_SCALING
, 175487);
213 static void ar9003_paprd_get_gain_table(struct ath_hw
*ah
)
215 u32
*entry
= ah
->paprd_gain_table_entries
;
216 u8
*index
= ah
->paprd_gain_table_index
;
217 u32 reg
= AR_PHY_TXGAIN_TABLE
;
220 memset(entry
, 0, sizeof(ah
->paprd_gain_table_entries
));
221 memset(index
, 0, sizeof(ah
->paprd_gain_table_index
));
223 for (i
= 0; i
< 32; i
++) {
224 entry
[i
] = REG_READ(ah
, reg
);
225 index
[i
] = (entry
[i
] >> 24) & 0xff;
230 static unsigned int ar9003_get_desired_gain(struct ath_hw
*ah
, int chain
,
233 int olpc_gain_delta
= 0;
234 int alpha_therm
, alpha_volt
;
235 int therm_cal_value
, volt_cal_value
;
236 int therm_value
, volt_value
;
237 int thermal_gain_corr
, voltage_gain_corr
;
238 int desired_scale
, desired_gain
= 0;
241 REG_CLR_BIT(ah
, AR_PHY_PAPRD_TRAINER_STAT1
,
242 AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE
);
243 desired_scale
= REG_READ_FIELD(ah
, AR_PHY_TPC_12
,
244 AR_PHY_TPC_12_DESIRED_SCALE_HT40_5
);
245 alpha_therm
= REG_READ_FIELD(ah
, AR_PHY_TPC_19
,
246 AR_PHY_TPC_19_ALPHA_THERM
);
247 alpha_volt
= REG_READ_FIELD(ah
, AR_PHY_TPC_19
,
248 AR_PHY_TPC_19_ALPHA_VOLT
);
249 therm_cal_value
= REG_READ_FIELD(ah
, AR_PHY_TPC_18
,
250 AR_PHY_TPC_18_THERM_CAL_VALUE
);
251 volt_cal_value
= REG_READ_FIELD(ah
, AR_PHY_TPC_18
,
252 AR_PHY_TPC_18_VOLT_CAL_VALUE
);
253 therm_value
= REG_READ_FIELD(ah
, AR_PHY_BB_THERM_ADC_4
,
254 AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE
);
255 volt_value
= REG_READ_FIELD(ah
, AR_PHY_BB_THERM_ADC_4
,
256 AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE
);
259 reg
= AR_PHY_TPC_11_B0
;
261 reg
= AR_PHY_TPC_11_B1
;
263 reg
= AR_PHY_TPC_11_B2
;
265 olpc_gain_delta
= REG_READ_FIELD(ah
, reg
,
266 AR_PHY_TPC_11_OLPC_GAIN_DELTA
);
268 if (olpc_gain_delta
>= 128)
269 olpc_gain_delta
= olpc_gain_delta
- 256;
271 thermal_gain_corr
= (alpha_therm
* (therm_value
- therm_cal_value
) +
273 voltage_gain_corr
= (alpha_volt
* (volt_value
- volt_cal_value
) +
275 desired_gain
= target_power
- olpc_gain_delta
- thermal_gain_corr
-
276 voltage_gain_corr
+ desired_scale
;
281 static void ar9003_tx_force_gain(struct ath_hw
*ah
, unsigned int gain_index
)
283 int selected_gain_entry
, txbb1dbgain
, txbb6dbgain
, txmxrgain
;
284 int padrvgnA
, padrvgnB
, padrvgnC
, padrvgnD
;
285 u32
*gain_table_entries
= ah
->paprd_gain_table_entries
;
287 selected_gain_entry
= gain_table_entries
[gain_index
];
288 txbb1dbgain
= selected_gain_entry
& 0x7;
289 txbb6dbgain
= (selected_gain_entry
>> 3) & 0x3;
290 txmxrgain
= (selected_gain_entry
>> 5) & 0xf;
291 padrvgnA
= (selected_gain_entry
>> 9) & 0xf;
292 padrvgnB
= (selected_gain_entry
>> 13) & 0xf;
293 padrvgnC
= (selected_gain_entry
>> 17) & 0xf;
294 padrvgnD
= (selected_gain_entry
>> 21) & 0x3;
296 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
297 AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN
, txbb1dbgain
);
298 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
299 AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN
, txbb6dbgain
);
300 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
301 AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN
, txmxrgain
);
302 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
303 AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA
, padrvgnA
);
304 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
305 AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB
, padrvgnB
);
306 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
307 AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC
, padrvgnC
);
308 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
309 AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND
, padrvgnD
);
310 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
311 AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL
, 0);
312 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
313 AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN
, 0);
314 REG_RMW_FIELD(ah
, AR_PHY_TPC_1
, AR_PHY_TPC_1_FORCED_DAC_GAIN
, 0);
315 REG_RMW_FIELD(ah
, AR_PHY_TPC_1
, AR_PHY_TPC_1_FORCE_DAC_GAIN
, 0);
318 static inline int find_expn(int num
)
323 static inline int find_proper_scale(int expn
, int N
)
325 return (expn
> N
) ? expn
- 10 : 0;
330 static bool create_pa_curve(u32
*data_L
, u32
*data_U
, u32
*pa_table
, u16
*gain
)
332 unsigned int thresh_accum_cnt
;
333 int x_est
[NUM_BIN
+ 1], Y
[NUM_BIN
+ 1], theta
[NUM_BIN
+ 1];
334 int PA_in
[NUM_BIN
+ 1];
335 int B1_tmp
[NUM_BIN
+ 1], B2_tmp
[NUM_BIN
+ 1];
336 unsigned int B1_abs_max
, B2_abs_max
;
337 int max_index
, scale_factor
;
338 int y_est
[NUM_BIN
+ 1];
339 int x_est_fxp1_nonlin
, x_tilde
[NUM_BIN
+ 1];
340 unsigned int x_tilde_abs
;
341 int G_fxp
, Y_intercept
, order_x_by_y
, M
, I
, L
, sum_y_sqr
, sum_y_quad
;
342 int Q_x
, Q_B1
, Q_B2
, beta_raw
, alpha_raw
, scale_B
;
343 int Q_scale_B
, Q_beta
, Q_alpha
, alpha
, beta
, order_1
, order_2
;
344 int order1_5x
, order2_3x
, order1_5x_rem
, order2_3x_rem
;
346 int theta_low_bin
= 0;
349 /* disregard any bin that contains <= 16 samples */
350 thresh_accum_cnt
= 16;
353 memset(theta
, 0, sizeof(theta
));
354 memset(x_est
, 0, sizeof(x_est
));
355 memset(Y
, 0, sizeof(Y
));
356 memset(y_est
, 0, sizeof(y_est
));
357 memset(x_tilde
, 0, sizeof(x_tilde
));
359 for (i
= 0; i
< NUM_BIN
; i
++) {
360 s32 accum_cnt
, accum_tx
, accum_rx
, accum_ang
;
362 /* number of samples */
363 accum_cnt
= data_L
[i
] & 0xffff;
365 if (accum_cnt
<= thresh_accum_cnt
)
368 /* sum(tx amplitude) */
369 accum_tx
= ((data_L
[i
] >> 16) & 0xffff) |
370 ((data_U
[i
] & 0x7ff) << 16);
372 /* sum(rx amplitude distance to lower bin edge) */
373 accum_rx
= ((data_U
[i
] >> 11) & 0x1f) |
374 ((data_L
[i
+ 23] & 0xffff) << 5);
377 accum_ang
= ((data_L
[i
+ 23] >> 16) & 0xffff) |
378 ((data_U
[i
+ 23] & 0x7ff) << 16);
380 accum_tx
<<= scale_factor
;
381 accum_rx
<<= scale_factor
;
382 x_est
[i
+ 1] = (((accum_tx
+ accum_cnt
) / accum_cnt
) + 32) >>
385 Y
[i
+ 1] = ((((accum_rx
+ accum_cnt
) / accum_cnt
) + 32) >>
387 (1 << scale_factor
) * max_index
+ 16;
389 if (accum_ang
>= (1 << 26))
390 accum_ang
-= 1 << 27;
392 theta
[i
+ 1] = ((accum_ang
* (1 << scale_factor
)) + accum_cnt
) /
399 * Find average theta of first 5 bin and all of those to same value.
400 * Curve is linear at that range.
402 for (i
= 1; i
< 6; i
++)
403 theta_low_bin
+= theta
[i
];
405 theta_low_bin
= theta_low_bin
/ 5;
406 for (i
= 1; i
< 6; i
++)
407 theta
[i
] = theta_low_bin
;
409 /* Set values at origin */
410 theta
[0] = theta_low_bin
;
411 for (i
= 0; i
<= max_index
; i
++)
412 theta
[i
] -= theta_low_bin
;
418 /* low signal gain */
419 if (x_est
[6] == x_est
[3])
423 (((Y
[6] - Y
[3]) * 1 << scale_factor
) +
424 (x_est
[6] - x_est
[3])) / (x_est
[6] - x_est
[3]);
426 /* prevent division by zero */
431 (G_fxp
* (x_est
[0] - x_est
[3]) +
432 (1 << scale_factor
)) / (1 << scale_factor
) + Y
[3];
434 for (i
= 0; i
<= max_index
; i
++)
435 y_est
[i
] = Y
[i
] - Y_intercept
;
437 for (i
= 0; i
<= 3; i
++) {
439 x_est
[i
] = ((y_est
[i
] * 1 << scale_factor
) + G_fxp
) / G_fxp
;
442 if (y_est
[max_index
] == 0)
446 x_est
[max_index
] - ((1 << scale_factor
) * y_est
[max_index
] +
450 (x_est_fxp1_nonlin
+ y_est
[max_index
]) / y_est
[max_index
];
452 if (order_x_by_y
== 0)
454 else if (order_x_by_y
== 1)
459 I
= (max_index
> 15) ? 7 : max_index
>> 1;
466 for (i
= 0; i
<= L
; i
++) {
469 unsigned int tmp_abs
;
471 /* prevent division by zero */
472 if (y_est
[i
+ I
] == 0)
476 x_est
[i
+ I
] - ((1 << scale_factor
) * y_est
[i
+ I
] +
480 (x_est_fxp1_nonlin
* (1 << M
) + y_est
[i
+ I
]) / y_est
[i
+
483 (x_tilde
[i
] * (1 << M
) + y_est
[i
+ I
]) / y_est
[i
+ I
];
485 (x_tilde
[i
] * (1 << M
) + y_est
[i
+ I
]) / y_est
[i
+ I
];
487 (y_est
[i
+ I
] * y_est
[i
+ I
] +
488 (scale_factor
* scale_factor
)) / (scale_factor
*
490 tmp_abs
= abs(x_tilde
[i
]);
491 if (tmp_abs
> x_tilde_abs
)
492 x_tilde_abs
= tmp_abs
;
494 y_quad
= y_sqr
* y_sqr
;
495 sum_y_sqr
= sum_y_sqr
+ y_sqr
;
496 sum_y_quad
= sum_y_quad
+ y_quad
;
497 B1_tmp
[i
] = y_sqr
* (L
+ 1);
503 for (i
= 0; i
<= L
; i
++) {
506 B1_tmp
[i
] -= sum_y_sqr
;
507 B2_tmp
[i
] = sum_y_quad
- sum_y_sqr
* B2_tmp
[i
];
509 abs_val
= abs(B1_tmp
[i
]);
510 if (abs_val
> B1_abs_max
)
511 B1_abs_max
= abs_val
;
513 abs_val
= abs(B2_tmp
[i
]);
514 if (abs_val
> B2_abs_max
)
515 B2_abs_max
= abs_val
;
518 Q_x
= find_proper_scale(find_expn(x_tilde_abs
), 10);
519 Q_B1
= find_proper_scale(find_expn(B1_abs_max
), 10);
520 Q_B2
= find_proper_scale(find_expn(B2_abs_max
), 10);
524 for (i
= 0; i
<= L
; i
++) {
525 x_tilde
[i
] = x_tilde
[i
] / (1 << Q_x
);
526 B1_tmp
[i
] = B1_tmp
[i
] / (1 << Q_B1
);
527 B2_tmp
[i
] = B2_tmp
[i
] / (1 << Q_B2
);
528 beta_raw
= beta_raw
+ B1_tmp
[i
] * x_tilde
[i
];
529 alpha_raw
= alpha_raw
+ B2_tmp
[i
] * x_tilde
[i
];
533 ((sum_y_quad
/ scale_factor
) * (L
+ 1) -
534 (sum_y_sqr
/ scale_factor
) * sum_y_sqr
) * scale_factor
;
536 Q_scale_B
= find_proper_scale(find_expn(abs(scale_B
)), 10);
537 scale_B
= scale_B
/ (1 << Q_scale_B
);
540 Q_beta
= find_proper_scale(find_expn(abs(beta_raw
)), 10);
541 Q_alpha
= find_proper_scale(find_expn(abs(alpha_raw
)), 10);
542 beta_raw
= beta_raw
/ (1 << Q_beta
);
543 alpha_raw
= alpha_raw
/ (1 << Q_alpha
);
544 alpha
= (alpha_raw
<< 10) / scale_B
;
545 beta
= (beta_raw
<< 10) / scale_B
;
546 order_1
= 3 * M
- Q_x
- Q_B1
- Q_beta
+ 10 + Q_scale_B
;
547 order_2
= 3 * M
- Q_x
- Q_B2
- Q_alpha
+ 10 + Q_scale_B
;
548 order1_5x
= order_1
/ 5;
549 order2_3x
= order_2
/ 3;
550 order1_5x_rem
= order_1
- 5 * order1_5x
;
551 order2_3x_rem
= order_2
- 3 * order2_3x
;
553 for (i
= 0; i
< PAPRD_TABLE_SZ
; i
++) {
555 y5
= ((beta
* tmp
) >> 6) >> order1_5x
;
556 y5
= (y5
* tmp
) >> order1_5x
;
557 y5
= (y5
* tmp
) >> order1_5x
;
558 y5
= (y5
* tmp
) >> order1_5x
;
559 y5
= (y5
* tmp
) >> order1_5x
;
560 y5
= y5
>> order1_5x_rem
;
561 y3
= (alpha
* tmp
) >> order2_3x
;
562 y3
= (y3
* tmp
) >> order2_3x
;
563 y3
= (y3
* tmp
) >> order2_3x
;
564 y3
= y3
>> order2_3x_rem
;
565 PA_in
[i
] = y5
+ y3
+ (256 * tmp
) / G_fxp
;
568 tmp
= PA_in
[i
] - PA_in
[i
- 1];
571 PA_in
[i
- 1] + (PA_in
[i
- 1] -
575 PA_in
[i
] = (PA_in
[i
] < 1400) ? PA_in
[i
] : 1400;
581 for (i
= 0; i
<= L
; i
++) {
583 ((theta
[i
+ I
] << M
) + y_est
[i
+ I
]) / y_est
[i
+ I
];
585 ((theta_tilde
<< M
) + y_est
[i
+ I
]) / y_est
[i
+ I
];
587 ((theta_tilde
<< M
) + y_est
[i
+ I
]) / y_est
[i
+ I
];
588 beta_raw
= beta_raw
+ B1_tmp
[i
] * theta_tilde
;
589 alpha_raw
= alpha_raw
+ B2_tmp
[i
] * theta_tilde
;
592 Q_beta
= find_proper_scale(find_expn(abs(beta_raw
)), 10);
593 Q_alpha
= find_proper_scale(find_expn(abs(alpha_raw
)), 10);
594 beta_raw
= beta_raw
/ (1 << Q_beta
);
595 alpha_raw
= alpha_raw
/ (1 << Q_alpha
);
597 alpha
= (alpha_raw
<< 10) / scale_B
;
598 beta
= (beta_raw
<< 10) / scale_B
;
599 order_1
= 3 * M
- Q_x
- Q_B1
- Q_beta
+ 10 + Q_scale_B
+ 5;
600 order_2
= 3 * M
- Q_x
- Q_B2
- Q_alpha
+ 10 + Q_scale_B
+ 5;
601 order1_5x
= order_1
/ 5;
602 order2_3x
= order_2
/ 3;
603 order1_5x_rem
= order_1
- 5 * order1_5x
;
604 order2_3x_rem
= order_2
- 3 * order2_3x
;
606 for (i
= 0; i
< PAPRD_TABLE_SZ
; i
++) {
609 /* pa_table[4] is calculated from PA_angle for i=5 */
615 y5
= (((beta
* tmp
- 64) >> 6) -
616 (1 << order1_5x
)) / (1 << order1_5x
);
618 y5
= ((((beta
* tmp
- 64) >> 6) +
619 (1 << order1_5x
)) / (1 << order1_5x
));
621 y5
= (y5
* tmp
) / (1 << order1_5x
);
622 y5
= (y5
* tmp
) / (1 << order1_5x
);
623 y5
= (y5
* tmp
) / (1 << order1_5x
);
624 y5
= (y5
* tmp
) / (1 << order1_5x
);
625 y5
= y5
/ (1 << order1_5x_rem
);
629 (1 << order2_3x
)) / (1 << order2_3x
);
632 (1 << order2_3x
)) / (1 << order2_3x
);
633 y3
= (y3
* tmp
) / (1 << order2_3x
);
634 y3
= (y3
* tmp
) / (1 << order2_3x
);
635 y3
= y3
/ (1 << order2_3x_rem
);
643 else if (PA_angle
> 150)
647 pa_table
[i
] = ((PA_in
[i
] & 0x7ff) << 11) + (PA_angle
& 0x7ff);
649 PA_angle
= (PA_angle
+ 2) >> 1;
650 pa_table
[i
- 1] = ((PA_in
[i
- 1] & 0x7ff) << 11) +
659 void ar9003_paprd_populate_single_table(struct ath_hw
*ah
,
660 struct ath9k_hw_cal_data
*caldata
,
663 u32
*paprd_table_val
= caldata
->pa_table
[chain
];
664 u32 small_signal_gain
= caldata
->small_signal_gain
[chain
];
665 u32 training_power
= ah
->paprd_training_power
;
670 reg
= AR_PHY_PAPRD_MEM_TAB_B0
;
672 reg
= AR_PHY_PAPRD_MEM_TAB_B1
;
674 reg
= AR_PHY_PAPRD_MEM_TAB_B2
;
676 for (i
= 0; i
< PAPRD_TABLE_SZ
; i
++) {
677 REG_WRITE(ah
, reg
, paprd_table_val
[i
]);
682 reg
= AR_PHY_PA_GAIN123_B0
;
684 reg
= AR_PHY_PA_GAIN123_B1
;
686 reg
= AR_PHY_PA_GAIN123_B2
;
688 REG_RMW_FIELD(ah
, reg
, AR_PHY_PA_GAIN123_PA_GAIN1
, small_signal_gain
);
690 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_CTRL1_B0
,
691 AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL
,
694 if (ah
->caps
.tx_chainmask
& BIT(1))
695 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_CTRL1_B1
,
696 AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL
,
699 if (ah
->caps
.tx_chainmask
& BIT(2))
700 REG_RMW_FIELD(ah
, AR_PHY_PAPRD_CTRL1_B2
,
701 AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL
,
704 EXPORT_SYMBOL(ar9003_paprd_populate_single_table
);
706 int ar9003_paprd_setup_gain_table(struct ath_hw
*ah
, int chain
)
708 unsigned int i
, desired_gain
, gain_index
;
709 unsigned int train_power
= ah
->paprd_training_power
;
711 desired_gain
= ar9003_get_desired_gain(ah
, chain
, train_power
);
714 for (i
= 0; i
< 32; i
++) {
715 if (ah
->paprd_gain_table_index
[i
] >= desired_gain
)
720 ar9003_tx_force_gain(ah
, gain_index
);
722 REG_CLR_BIT(ah
, AR_PHY_PAPRD_TRAINER_STAT1
,
723 AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE
);
727 EXPORT_SYMBOL(ar9003_paprd_setup_gain_table
);
729 int ar9003_paprd_create_curve(struct ath_hw
*ah
,
730 struct ath9k_hw_cal_data
*caldata
, int chain
)
732 u16
*small_signal_gain
= &caldata
->small_signal_gain
[chain
];
733 u32
*pa_table
= caldata
->pa_table
[chain
];
734 u32
*data_L
, *data_U
;
739 memset(caldata
->pa_table
[chain
], 0, sizeof(caldata
->pa_table
[chain
]));
741 buf
= kmalloc(2 * 48 * sizeof(u32
), GFP_ATOMIC
);
748 REG_CLR_BIT(ah
, AR_PHY_CHAN_INFO_MEMORY
,
749 AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ
);
751 reg
= AR_PHY_CHAN_INFO_TAB_0
;
752 for (i
= 0; i
< 48; i
++)
753 data_L
[i
] = REG_READ(ah
, reg
+ (i
<< 2));
755 REG_SET_BIT(ah
, AR_PHY_CHAN_INFO_MEMORY
,
756 AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ
);
758 for (i
= 0; i
< 48; i
++)
759 data_U
[i
] = REG_READ(ah
, reg
+ (i
<< 2));
761 if (!create_pa_curve(data_L
, data_U
, pa_table
, small_signal_gain
))
764 REG_CLR_BIT(ah
, AR_PHY_PAPRD_TRAINER_STAT1
,
765 AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE
);
771 EXPORT_SYMBOL(ar9003_paprd_create_curve
);
773 int ar9003_paprd_init_table(struct ath_hw
*ah
)
777 ret
= ar9003_paprd_setup_single_table(ah
);
781 ar9003_paprd_get_gain_table(ah
);
784 EXPORT_SYMBOL(ar9003_paprd_init_table
);
786 bool ar9003_paprd_is_done(struct ath_hw
*ah
)
788 return !!REG_READ_FIELD(ah
, AR_PHY_PAPRD_TRAINER_STAT1
,
789 AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE
);
791 EXPORT_SYMBOL(ar9003_paprd_is_done
);