ath9k: fix some more issues in the paprd changes
[librecmc/librecmc.git] / package / mac80211 / patches / 532-ath9k_paprd_training_power.patch
1 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
2 +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
3 @@ -30,9 +30,69 @@ void ar9003_paprd_enable(struct ath_hw *
4  }
5  EXPORT_SYMBOL(ar9003_paprd_enable);
6  
7 -static void ar9003_paprd_setup_single_table(struct ath_hw *ah)
8 +static int ar9003_get_training_power_2g(struct ath_hw *ah)
9  {
10         struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
11 +       struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G;
12 +       unsigned int power, scale, delta;
13 +
14 +       scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1);
15 +       power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
16 +                              AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
17 +
18 +       delta = abs((int) ah->paprd_target_power - (int) power);
19 +       if (delta > scale)
20 +               return -1;
21 +
22 +       if (delta < 4)
23 +               power -= 4 - delta;
24 +
25 +       return power;
26 +}
27 +
28 +static int get_streams(int mask)
29 +{
30 +       return !!(mask & BIT(0)) + !!(mask & BIT(1)) + !!(mask & BIT(2));
31 +}
32 +
33 +static int ar9003_get_training_power_5g(struct ath_hw *ah)
34 +{
35 +       struct ath_common *common = ath9k_hw_common(ah);
36 +       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
37 +       struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;
38 +       struct ath9k_channel *chan = ah->curchan;
39 +       unsigned int power, scale, delta;
40 +
41 +       if (chan->channel >= 5700)
42 +               scale = MS(le32_to_cpu(hdr->papdRateMaskHt20),
43 +                          AR9300_PAPRD_SCALE_1);
44 +       else if (chan->channel >= 5400)
45 +               scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
46 +                          AR9300_PAPRD_SCALE_2);
47 +       else
48 +               scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
49 +                          AR9300_PAPRD_SCALE_1);
50 +
51 +       if (IS_CHAN_HT40(chan))
52 +               power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
53 +                       AR_PHY_POWERTX_RATE8_POWERTXHT40_5);
54 +       else
55 +               power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6,
56 +                       AR_PHY_POWERTX_RATE6_POWERTXHT20_5);
57 +
58 +       power += scale;
59 +       delta = abs((int) ah->paprd_target_power - (int) power);
60 +       if (delta > scale)
61 +               return -1;
62 +
63 +       power += 2 * get_streams(common->tx_chainmask);
64 +       return power;
65 +}
66 +
67 +static int ar9003_paprd_setup_single_table(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;
72         static const u32 ctrl0[3] = {
73                 AR_PHY_PAPRD_CTRL0_B0,
74 @@ -45,6 +105,7 @@ static void ar9003_paprd_setup_single_ta
75                 AR_PHY_PAPRD_CTRL1_B2
76         };
77         u32 am_mask, ht40_mask;
78 +       int training_power;
79         int i;
80  
81         if (ah->curchan && IS_CHAN_5GHZ(ah->curchan))
82 @@ -55,11 +116,25 @@ static void ar9003_paprd_setup_single_ta
83         am_mask = le32_to_cpu(hdr->papdRateMaskHt20) & AR9300_PAPRD_RATE_MASK;
84         ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40) & AR9300_PAPRD_RATE_MASK;
85  
86 +       if (IS_CHAN_2GHZ(ah->curchan))
87 +               training_power = ar9003_get_training_power_2g(ah);
88 +       else
89 +               training_power = ar9003_get_training_power_5g(ah);
90 +
91 +       if (training_power < 0) {
92 +               ath_dbg(common, ATH_DBG_CALIBRATE,
93 +                       "PAPRD target power delta out of range");
94 +               return -ERANGE;
95 +       }
96 +       ah->paprd_training_power = training_power;
97 +       ath_dbg(common, ATH_DBG_CALIBRATE,
98 +               "Training power: %d, Target power: %d\n",
99 +               ah->paprd_training_power, ah->paprd_target_power);
100 +
101         REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask);
102         REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask);
103         REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask);
104  
105 -
106         for (i = 0; i < ah->caps.max_txchains; i++) {
107                 REG_RMW_FIELD(ah, ctrl0[i],
108                               AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1);
109 @@ -141,6 +216,7 @@ static void ar9003_paprd_setup_single_ta
110                       AR_PHY_PAPRD_PRE_POST_SCALING, 185706);
111         REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0,
112                       AR_PHY_PAPRD_PRE_POST_SCALING, 175487);
113 +       return 0;
114  }
115  
116  static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
117 @@ -595,15 +671,10 @@ void ar9003_paprd_populate_single_table(
118  {
119         u32 *paprd_table_val = caldata->pa_table[chain];
120         u32 small_signal_gain = caldata->small_signal_gain[chain];
121 -       u32 training_power;
122 +       u32 training_power = ah->paprd_training_power;
123         u32 reg = 0;
124         int i;
125  
126 -       training_power =
127 -           REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
128 -                          AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
129 -       training_power -= 4;
130 -
131         if (chain == 0)
132                 reg = AR_PHY_PAPRD_MEM_TAB_B0;
133         else if (chain == 1)
134 @@ -643,14 +714,8 @@ EXPORT_SYMBOL(ar9003_paprd_populate_sing
135  
136  int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
137  {
138 -
139         unsigned int i, desired_gain, gain_index;
140 -       unsigned int train_power;
141 -
142 -       train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
143 -                                    AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
144 -
145 -       train_power = train_power - 4;
146 +       unsigned int train_power = ah->paprd_training_power;
147  
148         desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
149  
150 @@ -716,7 +781,12 @@ EXPORT_SYMBOL(ar9003_paprd_create_curve)
151  
152  int ar9003_paprd_init_table(struct ath_hw *ah)
153  {
154 -       ar9003_paprd_setup_single_table(ah);
155 +       int ret;
156 +
157 +       ret = ar9003_paprd_setup_single_table(ah);
158 +       if (ret < 0)
159 +           return ret;
160 +
161         ar9003_paprd_get_gain_table(ah);
162         return 0;
163  }
164 --- a/drivers/net/wireless/ath/ath9k/hw.h
165 +++ b/drivers/net/wireless/ath/ath9k/hw.h
166 @@ -835,6 +835,8 @@ struct ath_hw {
167         u32 bb_watchdog_last_status;
168         u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */
169  
170 +       unsigned int paprd_target_power;
171 +       unsigned int paprd_training_power;
172         u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
173         u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
174         /*
175 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
176 +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
177 @@ -1090,6 +1090,14 @@
178  #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0     0x3F
179  #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S   0
180  
181 +#define AR_PHY_POWERTX_RATE6                   (AR_SM_BASE + 0x1d4)
182 +#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5     0x3F00
183 +#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5_S   8
184 +
185 +#define AR_PHY_POWERTX_RATE8                   (AR_SM_BASE + 0x1dc)
186 +#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5     0x3F00
187 +#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S   8
188 +
189  void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
190  
191  #endif  /* AR9003_PHY_H */
192 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
193 +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
194 @@ -4798,6 +4798,19 @@ static void ath9k_hw_ar9300_set_txpower(
195         /* Write target power array to registers */
196         ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
197         ar9003_hw_calibration_apply(ah, chan->channel);
198 +
199 +       if (IS_CHAN_2GHZ(chan)) {
200 +               if (IS_CHAN_HT40(chan))
201 +                       i = ALL_TARGET_HT40_0_8_16;
202 +               else
203 +                       i = ALL_TARGET_HT20_0_8_16;
204 +       } else {
205 +               if (IS_CHAN_HT40(chan))
206 +                       i = ALL_TARGET_HT40_7;
207 +               else
208 +                       i = ALL_TARGET_HT20_7;
209 +       }
210 +       ah->paprd_target_power = targetPowerValT2[i];
211  }
212  
213  static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
214 --- a/drivers/net/wireless/ath/ath9k/main.c
215 +++ b/drivers/net/wireless/ath/ath9k/main.c
216 @@ -373,6 +373,9 @@ void ath_paprd_calibrate(struct work_str
217         if (!caldata)
218                 return;
219  
220 +       if (ar9003_paprd_init_table(ah) < 0)
221 +               return;
222 +
223         skb = alloc_skb(len, GFP_KERNEL);
224         if (!skb)
225                 return;
226 @@ -388,7 +391,6 @@ void ath_paprd_calibrate(struct work_str
227         memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
228  
229         ath9k_ps_wakeup(sc);
230 -       ar9003_paprd_init_table(ah);
231         for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
232                 if (!(common->tx_chainmask & BIT(chain)))
233                         continue;