Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ar9003_paprd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2011 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 <linux/export.h>
18 #include "hw.h"
19 #include "ar9003_phy.h"
20 
21 void ar9003_paprd_enable(struct ath_hw *ah, bool val)
22 {
23  struct ath9k_channel *chan = ah->curchan;
24  struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
25 
26  /*
27  * 3 bits for modalHeader5G.papdRateMaskHt20
28  * is used for sub-band disabling of PAPRD.
29  * 5G band is divided into 3 sub-bands -- upper,
30  * middle, lower.
31  * if bit 30 of modalHeader5G.papdRateMaskHt20 is set
32  * -- disable PAPRD for upper band 5GHz
33  * if bit 29 of modalHeader5G.papdRateMaskHt20 is set
34  * -- disable PAPRD for middle band 5GHz
35  * if bit 28 of modalHeader5G.papdRateMaskHt20 is set
36  * -- disable PAPRD for lower band 5GHz
37  */
38 
39  if (IS_CHAN_5GHZ(chan)) {
40  if (chan->channel >= UPPER_5G_SUB_BAND_START) {
41  if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
42  & BIT(30))
43  val = false;
44  } else if (chan->channel >= MID_5G_SUB_BAND_START) {
45  if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
46  & BIT(29))
47  val = false;
48  } else {
49  if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
50  & BIT(28))
51  val = false;
52  }
53  }
54 
55  if (val) {
56  ah->paprd_table_write_done = true;
57  ath9k_hw_apply_txpower(ah, chan, false);
58  }
59 
62  if (ah->caps.tx_chainmask & BIT(1))
65  if (ah->caps.tx_chainmask & BIT(2))
68 }
70 
71 static int ar9003_get_training_power_2g(struct ath_hw *ah)
72 {
73  struct ath9k_channel *chan = ah->curchan;
74  unsigned int power, scale, delta;
75 
76  scale = ar9003_get_paprd_scale_factor(ah, chan);
79 
80  delta = abs((int) ah->paprd_target_power - (int) power);
81  if (delta > scale)
82  return -1;
83 
84  if (delta < 4)
85  power -= 4 - delta;
86 
87  return power;
88 }
89 
90 static int ar9003_get_training_power_5g(struct ath_hw *ah)
91 {
92  struct ath_common *common = ath9k_hw_common(ah);
93  struct ath9k_channel *chan = ah->curchan;
94  unsigned int power, scale, delta;
95 
96  scale = ar9003_get_paprd_scale_factor(ah, chan);
97 
98  if (IS_CHAN_HT40(chan))
101  else
104 
105  power += scale;
106  delta = abs((int) ah->paprd_target_power - (int) power);
107  if (delta > scale)
108  return -1;
109 
110  switch (get_streams(ah->txchainmask)) {
111  case 1:
112  delta = 6;
113  break;
114  case 2:
115  delta = 4;
116  break;
117  case 3:
118  delta = 2;
119  break;
120  default:
121  delta = 0;
122  ath_dbg(common, CALIBRATE, "Invalid tx-chainmask: %u\n",
123  ah->txchainmask);
124  }
125 
126  power += delta;
127  return power;
128 }
129 
130 static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
131 {
132  struct ath_common *common = ath9k_hw_common(ah);
133  static const u32 ctrl0[3] = {
137  };
138  static const u32 ctrl1[3] = {
142  };
143  int training_power;
144  int i, val;
145  u32 am2pm_mask = ah->paprd_ratemask;
146 
147  if (IS_CHAN_2GHZ(ah->curchan))
148  training_power = ar9003_get_training_power_2g(ah);
149  else
150  training_power = ar9003_get_training_power_5g(ah);
151 
152  ath_dbg(common, CALIBRATE, "Training power: %d, Target power: %d\n",
153  training_power, ah->paprd_target_power);
154 
155  if (training_power < 0) {
156  ath_dbg(common, CALIBRATE,
157  "PAPRD target power delta out of range\n");
158  return -ERANGE;
159  }
160  ah->paprd_training_power = training_power;
161 
162  if (AR_SREV_9330(ah))
163  am2pm_mask = 0;
164 
166  ah->paprd_ratemask);
168  am2pm_mask);
170  ah->paprd_ratemask_ht40);
171 
172  for (i = 0; i < ah->caps.max_txchains; i++) {
173  REG_RMW_FIELD(ah, ctrl0[i],
175  REG_RMW_FIELD(ah, ctrl1[i],
177  REG_RMW_FIELD(ah, ctrl1[i],
179  REG_RMW_FIELD(ah, ctrl1[i],
181  REG_RMW_FIELD(ah, ctrl1[i],
183  REG_RMW_FIELD(ah, ctrl1[i],
185  REG_RMW_FIELD(ah, ctrl1[i],
187  REG_RMW_FIELD(ah, ctrl0[i],
189  }
190 
191  ar9003_paprd_enable(ah, false);
192 
207  val = AR_SREV_9462(ah) ? 0x91 : 147;
218  if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9550(ah))
221  -3);
222  else
225  -6);
226  val = AR_SREV_9462(ah) ? -10 : -15;
229  val);
238  100);
255  return 0;
256 }
257 
258 static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
259 {
263  int i;
264 
265  memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
266  memset(index, 0, sizeof(ah->paprd_gain_table_index));
267 
268  for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
269  entry[i] = REG_READ(ah, reg);
270  index[i] = (entry[i] >> 24) & 0xff;
271  reg += 4;
272  }
273 }
274 
275 static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
276  int target_power)
277 {
278  int olpc_gain_delta = 0, cl_gain_mod;
279  int alpha_therm, alpha_volt;
280  int therm_cal_value, volt_cal_value;
281  int therm_value, volt_value;
282  int thermal_gain_corr, voltage_gain_corr;
283  int desired_scale, desired_gain = 0;
284  u32 reg_olpc = 0, reg_cl_gain = 0;
285 
288  desired_scale = REG_READ_FIELD(ah, AR_PHY_TPC_12,
290  alpha_therm = REG_READ_FIELD(ah, AR_PHY_TPC_19,
292  alpha_volt = REG_READ_FIELD(ah, AR_PHY_TPC_19,
294  therm_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18,
296  volt_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18,
298  therm_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
300  volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
302 
303  switch (chain) {
304  case 0:
305  reg_olpc = AR_PHY_TPC_11_B0;
306  reg_cl_gain = AR_PHY_CL_TAB_0;
307  break;
308  case 1:
309  reg_olpc = AR_PHY_TPC_11_B1;
310  reg_cl_gain = AR_PHY_CL_TAB_1;
311  break;
312  case 2:
313  reg_olpc = AR_PHY_TPC_11_B2;
314  reg_cl_gain = AR_PHY_CL_TAB_2;
315  break;
316  default:
317  ath_dbg(ath9k_hw_common(ah), CALIBRATE,
318  "Invalid chainmask: %d\n", chain);
319  break;
320  }
321 
322  olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,
324  cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain,
326 
327  if (olpc_gain_delta >= 128)
328  olpc_gain_delta = olpc_gain_delta - 256;
329 
330  thermal_gain_corr = (alpha_therm * (therm_value - therm_cal_value) +
331  (256 / 2)) / 256;
332  voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
333  (128 / 2)) / 128;
334  desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
335  voltage_gain_corr + desired_scale + cl_gain_mod;
336 
337  return desired_gain;
338 }
339 
340 static void ar9003_tx_force_gain(struct ath_hw *ah, unsigned int gain_index)
341 {
342  int selected_gain_entry, txbb1dbgain, txbb6dbgain, txmxrgain;
343  int padrvgnA, padrvgnB, padrvgnC, padrvgnD;
344  u32 *gain_table_entries = ah->paprd_gain_table_entries;
345 
346  selected_gain_entry = gain_table_entries[gain_index];
347  txbb1dbgain = selected_gain_entry & 0x7;
348  txbb6dbgain = (selected_gain_entry >> 3) & 0x3;
349  txmxrgain = (selected_gain_entry >> 5) & 0xf;
350  padrvgnA = (selected_gain_entry >> 9) & 0xf;
351  padrvgnB = (selected_gain_entry >> 13) & 0xf;
352  padrvgnC = (selected_gain_entry >> 17) & 0xf;
353  padrvgnD = (selected_gain_entry >> 21) & 0x3;
354 
375 }
376 
377 static inline int find_expn(int num)
378 {
379  return fls(num) - 1;
380 }
381 
382 static inline int find_proper_scale(int expn, int N)
383 {
384  return (expn > N) ? expn - 10 : 0;
385 }
386 
387 #define NUM_BIN 23
388 
389 static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain)
390 {
391  unsigned int thresh_accum_cnt;
392  int x_est[NUM_BIN + 1], Y[NUM_BIN + 1], theta[NUM_BIN + 1];
393  int PA_in[NUM_BIN + 1];
394  int B1_tmp[NUM_BIN + 1], B2_tmp[NUM_BIN + 1];
395  unsigned int B1_abs_max, B2_abs_max;
396  int max_index, scale_factor;
397  int y_est[NUM_BIN + 1];
398  int x_est_fxp1_nonlin, x_tilde[NUM_BIN + 1];
399  unsigned int x_tilde_abs;
400  int G_fxp, Y_intercept, order_x_by_y, M, I, L, sum_y_sqr, sum_y_quad;
401  int Q_x, Q_B1, Q_B2, beta_raw, alpha_raw, scale_B;
402  int Q_scale_B, Q_beta, Q_alpha, alpha, beta, order_1, order_2;
403  int order1_5x, order2_3x, order1_5x_rem, order2_3x_rem;
404  int y5, y3, tmp;
405  int theta_low_bin = 0;
406  int i;
407 
408  /* disregard any bin that contains <= 16 samples */
409  thresh_accum_cnt = 16;
410  scale_factor = 5;
411  max_index = 0;
412  memset(theta, 0, sizeof(theta));
413  memset(x_est, 0, sizeof(x_est));
414  memset(Y, 0, sizeof(Y));
415  memset(y_est, 0, sizeof(y_est));
416  memset(x_tilde, 0, sizeof(x_tilde));
417 
418  for (i = 0; i < NUM_BIN; i++) {
419  s32 accum_cnt, accum_tx, accum_rx, accum_ang;
420 
421  /* number of samples */
422  accum_cnt = data_L[i] & 0xffff;
423 
424  if (accum_cnt <= thresh_accum_cnt)
425  continue;
426 
427  /* sum(tx amplitude) */
428  accum_tx = ((data_L[i] >> 16) & 0xffff) |
429  ((data_U[i] & 0x7ff) << 16);
430 
431  /* sum(rx amplitude distance to lower bin edge) */
432  accum_rx = ((data_U[i] >> 11) & 0x1f) |
433  ((data_L[i + 23] & 0xffff) << 5);
434 
435  /* sum(angles) */
436  accum_ang = ((data_L[i + 23] >> 16) & 0xffff) |
437  ((data_U[i + 23] & 0x7ff) << 16);
438 
439  accum_tx <<= scale_factor;
440  accum_rx <<= scale_factor;
441  x_est[i + 1] = (((accum_tx + accum_cnt) / accum_cnt) + 32) >>
442  scale_factor;
443 
444  Y[i + 1] = ((((accum_rx + accum_cnt) / accum_cnt) + 32) >>
445  scale_factor) +
446  (1 << scale_factor) * max_index + 16;
447 
448  if (accum_ang >= (1 << 26))
449  accum_ang -= 1 << 27;
450 
451  theta[i + 1] = ((accum_ang * (1 << scale_factor)) + accum_cnt) /
452  accum_cnt;
453 
454  max_index++;
455  }
456 
457  /*
458  * Find average theta of first 5 bin and all of those to same value.
459  * Curve is linear at that range.
460  */
461  for (i = 1; i < 6; i++)
462  theta_low_bin += theta[i];
463 
464  theta_low_bin = theta_low_bin / 5;
465  for (i = 1; i < 6; i++)
466  theta[i] = theta_low_bin;
467 
468  /* Set values at origin */
469  theta[0] = theta_low_bin;
470  for (i = 0; i <= max_index; i++)
471  theta[i] -= theta_low_bin;
472 
473  x_est[0] = 0;
474  Y[0] = 0;
475  scale_factor = 8;
476 
477  /* low signal gain */
478  if (x_est[6] == x_est[3])
479  return false;
480 
481  G_fxp =
482  (((Y[6] - Y[3]) * 1 << scale_factor) +
483  (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]);
484 
485  /* prevent division by zero */
486  if (G_fxp == 0)
487  return false;
488 
489  Y_intercept =
490  (G_fxp * (x_est[0] - x_est[3]) +
491  (1 << scale_factor)) / (1 << scale_factor) + Y[3];
492 
493  for (i = 0; i <= max_index; i++)
494  y_est[i] = Y[i] - Y_intercept;
495 
496  for (i = 0; i <= 3; i++) {
497  y_est[i] = i * 32;
498  x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp;
499  }
500 
501  if (y_est[max_index] == 0)
502  return false;
503 
504  x_est_fxp1_nonlin =
505  x_est[max_index] - ((1 << scale_factor) * y_est[max_index] +
506  G_fxp) / G_fxp;
507 
508  order_x_by_y =
509  (x_est_fxp1_nonlin + y_est[max_index]) / y_est[max_index];
510 
511  if (order_x_by_y == 0)
512  M = 10;
513  else if (order_x_by_y == 1)
514  M = 9;
515  else
516  M = 8;
517 
518  I = (max_index > 15) ? 7 : max_index >> 1;
519  L = max_index - I;
520  scale_factor = 8;
521  sum_y_sqr = 0;
522  sum_y_quad = 0;
523  x_tilde_abs = 0;
524 
525  for (i = 0; i <= L; i++) {
526  unsigned int y_sqr;
527  unsigned int y_quad;
528  unsigned int tmp_abs;
529 
530  /* prevent division by zero */
531  if (y_est[i + I] == 0)
532  return false;
533 
534  x_est_fxp1_nonlin =
535  x_est[i + I] - ((1 << scale_factor) * y_est[i + I] +
536  G_fxp) / G_fxp;
537 
538  x_tilde[i] =
539  (x_est_fxp1_nonlin * (1 << M) + y_est[i + I]) / y_est[i +
540  I];
541  x_tilde[i] =
542  (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I];
543  x_tilde[i] =
544  (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I];
545  y_sqr =
546  (y_est[i + I] * y_est[i + I] +
547  (scale_factor * scale_factor)) / (scale_factor *
548  scale_factor);
549  tmp_abs = abs(x_tilde[i]);
550  if (tmp_abs > x_tilde_abs)
551  x_tilde_abs = tmp_abs;
552 
553  y_quad = y_sqr * y_sqr;
554  sum_y_sqr = sum_y_sqr + y_sqr;
555  sum_y_quad = sum_y_quad + y_quad;
556  B1_tmp[i] = y_sqr * (L + 1);
557  B2_tmp[i] = y_sqr;
558  }
559 
560  B1_abs_max = 0;
561  B2_abs_max = 0;
562  for (i = 0; i <= L; i++) {
563  int abs_val;
564 
565  B1_tmp[i] -= sum_y_sqr;
566  B2_tmp[i] = sum_y_quad - sum_y_sqr * B2_tmp[i];
567 
568  abs_val = abs(B1_tmp[i]);
569  if (abs_val > B1_abs_max)
570  B1_abs_max = abs_val;
571 
572  abs_val = abs(B2_tmp[i]);
573  if (abs_val > B2_abs_max)
574  B2_abs_max = abs_val;
575  }
576 
577  Q_x = find_proper_scale(find_expn(x_tilde_abs), 10);
578  Q_B1 = find_proper_scale(find_expn(B1_abs_max), 10);
579  Q_B2 = find_proper_scale(find_expn(B2_abs_max), 10);
580 
581  beta_raw = 0;
582  alpha_raw = 0;
583  for (i = 0; i <= L; i++) {
584  x_tilde[i] = x_tilde[i] / (1 << Q_x);
585  B1_tmp[i] = B1_tmp[i] / (1 << Q_B1);
586  B2_tmp[i] = B2_tmp[i] / (1 << Q_B2);
587  beta_raw = beta_raw + B1_tmp[i] * x_tilde[i];
588  alpha_raw = alpha_raw + B2_tmp[i] * x_tilde[i];
589  }
590 
591  scale_B =
592  ((sum_y_quad / scale_factor) * (L + 1) -
593  (sum_y_sqr / scale_factor) * sum_y_sqr) * scale_factor;
594 
595  Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10);
596  scale_B = scale_B / (1 << Q_scale_B);
597  if (scale_B == 0)
598  return false;
599  Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10);
600  Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10);
601  beta_raw = beta_raw / (1 << Q_beta);
602  alpha_raw = alpha_raw / (1 << Q_alpha);
603  alpha = (alpha_raw << 10) / scale_B;
604  beta = (beta_raw << 10) / scale_B;
605  order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B;
606  order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B;
607  order1_5x = order_1 / 5;
608  order2_3x = order_2 / 3;
609  order1_5x_rem = order_1 - 5 * order1_5x;
610  order2_3x_rem = order_2 - 3 * order2_3x;
611 
612  for (i = 0; i < PAPRD_TABLE_SZ; i++) {
613  tmp = i * 32;
614  y5 = ((beta * tmp) >> 6) >> order1_5x;
615  y5 = (y5 * tmp) >> order1_5x;
616  y5 = (y5 * tmp) >> order1_5x;
617  y5 = (y5 * tmp) >> order1_5x;
618  y5 = (y5 * tmp) >> order1_5x;
619  y5 = y5 >> order1_5x_rem;
620  y3 = (alpha * tmp) >> order2_3x;
621  y3 = (y3 * tmp) >> order2_3x;
622  y3 = (y3 * tmp) >> order2_3x;
623  y3 = y3 >> order2_3x_rem;
624  PA_in[i] = y5 + y3 + (256 * tmp) / G_fxp;
625 
626  if (i >= 2) {
627  tmp = PA_in[i] - PA_in[i - 1];
628  if (tmp < 0)
629  PA_in[i] =
630  PA_in[i - 1] + (PA_in[i - 1] -
631  PA_in[i - 2]);
632  }
633 
634  PA_in[i] = (PA_in[i] < 1400) ? PA_in[i] : 1400;
635  }
636 
637  beta_raw = 0;
638  alpha_raw = 0;
639 
640  for (i = 0; i <= L; i++) {
641  int theta_tilde =
642  ((theta[i + I] << M) + y_est[i + I]) / y_est[i + I];
643  theta_tilde =
644  ((theta_tilde << M) + y_est[i + I]) / y_est[i + I];
645  theta_tilde =
646  ((theta_tilde << M) + y_est[i + I]) / y_est[i + I];
647  beta_raw = beta_raw + B1_tmp[i] * theta_tilde;
648  alpha_raw = alpha_raw + B2_tmp[i] * theta_tilde;
649  }
650 
651  Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10);
652  Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10);
653  beta_raw = beta_raw / (1 << Q_beta);
654  alpha_raw = alpha_raw / (1 << Q_alpha);
655 
656  alpha = (alpha_raw << 10) / scale_B;
657  beta = (beta_raw << 10) / scale_B;
658  order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B + 5;
659  order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B + 5;
660  order1_5x = order_1 / 5;
661  order2_3x = order_2 / 3;
662  order1_5x_rem = order_1 - 5 * order1_5x;
663  order2_3x_rem = order_2 - 3 * order2_3x;
664 
665  for (i = 0; i < PAPRD_TABLE_SZ; i++) {
666  int PA_angle;
667 
668  /* pa_table[4] is calculated from PA_angle for i=5 */
669  if (i == 4)
670  continue;
671 
672  tmp = i * 32;
673  if (beta > 0)
674  y5 = (((beta * tmp - 64) >> 6) -
675  (1 << order1_5x)) / (1 << order1_5x);
676  else
677  y5 = ((((beta * tmp - 64) >> 6) +
678  (1 << order1_5x)) / (1 << order1_5x));
679 
680  y5 = (y5 * tmp) / (1 << order1_5x);
681  y5 = (y5 * tmp) / (1 << order1_5x);
682  y5 = (y5 * tmp) / (1 << order1_5x);
683  y5 = (y5 * tmp) / (1 << order1_5x);
684  y5 = y5 / (1 << order1_5x_rem);
685 
686  if (beta > 0)
687  y3 = (alpha * tmp -
688  (1 << order2_3x)) / (1 << order2_3x);
689  else
690  y3 = (alpha * tmp +
691  (1 << order2_3x)) / (1 << order2_3x);
692  y3 = (y3 * tmp) / (1 << order2_3x);
693  y3 = (y3 * tmp) / (1 << order2_3x);
694  y3 = y3 / (1 << order2_3x_rem);
695 
696  if (i < 4) {
697  PA_angle = 0;
698  } else {
699  PA_angle = y5 + y3;
700  if (PA_angle < -150)
701  PA_angle = -150;
702  else if (PA_angle > 150)
703  PA_angle = 150;
704  }
705 
706  pa_table[i] = ((PA_in[i] & 0x7ff) << 11) + (PA_angle & 0x7ff);
707  if (i == 5) {
708  PA_angle = (PA_angle + 2) >> 1;
709  pa_table[i - 1] = ((PA_in[i - 1] & 0x7ff) << 11) +
710  (PA_angle & 0x7ff);
711  }
712  }
713 
714  *gain = G_fxp;
715  return true;
716 }
717 
719  struct ath9k_hw_cal_data *caldata,
720  int chain)
721 {
722  u32 *paprd_table_val = caldata->pa_table[chain];
723  u32 small_signal_gain = caldata->small_signal_gain[chain];
724  u32 training_power = ah->paprd_training_power;
725  u32 reg = 0;
726  int i;
727 
728  if (chain == 0)
730  else if (chain == 1)
732  else if (chain == 2)
734 
735  for (i = 0; i < PAPRD_TABLE_SZ; i++) {
736  REG_WRITE(ah, reg, paprd_table_val[i]);
737  reg = reg + 4;
738  }
739 
740  if (chain == 0)
741  reg = AR_PHY_PA_GAIN123_B0;
742  else if (chain == 1)
743  reg = AR_PHY_PA_GAIN123_B1;
744  else
745  reg = AR_PHY_PA_GAIN123_B2;
746 
747  REG_RMW_FIELD(ah, reg, AR_PHY_PA_GAIN123_PA_GAIN1, small_signal_gain);
748 
751  training_power);
752 
753  if (ah->caps.tx_chainmask & BIT(1))
756  training_power);
757 
758  if (ah->caps.tx_chainmask & BIT(2))
759  /* val AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL correct? */
762  training_power);
763 }
765 
766 int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
767 {
768  unsigned int i, desired_gain, gain_index;
769  unsigned int train_power = ah->paprd_training_power;
770 
771  desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
772 
773  gain_index = 0;
774  for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
775  if (ah->paprd_gain_table_index[i] >= desired_gain)
776  break;
777  gain_index++;
778  }
779 
780  ar9003_tx_force_gain(ah, gain_index);
781 
784 
785  return 0;
786 }
788 
789 static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah,
790  struct ath9k_hw_cal_data *caldata,
791  int chain)
792 {
793  u32 *pa_in = caldata->pa_table[chain];
794  int capdiv_offset, quick_drop_offset;
795  int capdiv2g, quick_drop;
796  int count = 0;
797  int i;
798 
799  if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah))
800  return false;
801 
802  capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
804 
807 
808  if (quick_drop)
809  quick_drop -= 0x40;
810 
811  for (i = 0; i < NUM_BIN + 1; i++) {
812  if (pa_in[i] == 1400)
813  count++;
814  }
815 
816  if (AR_SREV_9485(ah)) {
817  if (pa_in[23] < 800) {
818  capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150);
819  capdiv2g += capdiv_offset;
820  if (capdiv2g > 7) {
821  capdiv2g = 7;
822  if (pa_in[23] < 600) {
823  quick_drop++;
824  if (quick_drop > 0)
825  quick_drop = 0;
826  }
827  }
828  } else if (pa_in[23] == 1400) {
829  quick_drop_offset = min_t(int, count / 3, 2);
830  quick_drop += quick_drop_offset;
831  capdiv2g += quick_drop_offset / 2;
832 
833  if (capdiv2g > 7)
834  capdiv2g = 7;
835 
836  if (quick_drop > 0) {
837  quick_drop = 0;
838  capdiv2g -= quick_drop_offset;
839  if (capdiv2g < 0)
840  capdiv2g = 0;
841  }
842  } else {
843  return false;
844  }
845  } else if (AR_SREV_9330(ah)) {
846  if (pa_in[23] < 1000) {
847  capdiv_offset = (1000 - pa_in[23]) / 100;
848  capdiv2g += capdiv_offset;
849  if (capdiv_offset > 3) {
850  capdiv_offset = 1;
851  quick_drop--;
852  }
853 
854  capdiv2g += capdiv_offset;
855  if (capdiv2g > 6)
856  capdiv2g = 6;
857  if (quick_drop < -4)
858  quick_drop = -4;
859  } else if (pa_in[23] == 1400) {
860  if (count > 3) {
861  quick_drop++;
862  capdiv2g -= count / 4;
863  if (quick_drop > -2)
864  quick_drop = -2;
865  } else {
866  capdiv2g--;
867  }
868 
869  if (capdiv2g < 0)
870  capdiv2g = 0;
871  } else {
872  return false;
873  }
874  }
875 
880  quick_drop);
881 
882  return true;
883 }
884 
886  struct ath9k_hw_cal_data *caldata, int chain)
887 {
888  u16 *small_signal_gain = &caldata->small_signal_gain[chain];
889  u32 *pa_table = caldata->pa_table[chain];
890  u32 *data_L, *data_U;
891  int i, status = 0;
892  u32 *buf;
893  u32 reg;
894 
895  memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain]));
896 
897  buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC);
898  if (!buf)
899  return -ENOMEM;
900 
901  data_L = &buf[0];
902  data_U = &buf[48];
903 
906 
908  for (i = 0; i < 48; i++)
909  data_L[i] = REG_READ(ah, reg + (i << 2));
910 
913 
914  for (i = 0; i < 48; i++)
915  data_U[i] = REG_READ(ah, reg + (i << 2));
916 
917  if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))
918  status = -2;
919 
920  if (ar9003_paprd_retrain_pa_in(ah, caldata, chain))
921  status = -EINPROGRESS;
922 
925 
926  kfree(buf);
927 
928  return status;
929 }
931 
933 {
934  int ret;
935 
936  ret = ar9003_paprd_setup_single_table(ah);
937  if (ret < 0)
938  return ret;
939 
940  ar9003_paprd_get_gain_table(ah);
941  return 0;
942 }
944 
945 bool ar9003_paprd_is_done(struct ath_hw *ah)
946 {
947  int paprd_done, agc2_pwr;
950 
951  if (paprd_done == 0x1) {
954 
955  ath_dbg(ath9k_hw_common(ah), CALIBRATE,
956  "AGC2_PWR = 0x%x training done = 0x%x\n",
957  agc2_pwr, paprd_done);
958  /*
959  * agc2_pwr range should not be less than 'IDEAL_AGC2_PWR_CHANGE'
960  * when the training is completely done, otherwise retraining is
961  * done to make sure the value is in ideal range
962  */
963  if (agc2_pwr <= PAPRD_IDEAL_AGC2_PWR_RANGE)
964  paprd_done = 0;
965  }
966 
967  return !!paprd_done;
968 }