diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/phy.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 833 |
1 files changed, 580 insertions, 253 deletions
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 6284c389ba18..55441913344d 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -29,6 +29,95 @@ | |||
29 | #include "rfbuffer.h" | 29 | #include "rfbuffer.h" |
30 | #include "rfgain.h" | 30 | #include "rfgain.h" |
31 | 31 | ||
32 | |||
33 | /******************\ | ||
34 | * Helper functions * | ||
35 | \******************/ | ||
36 | |||
37 | /* | ||
38 | * Get the PHY Chip revision | ||
39 | */ | ||
40 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | ||
41 | { | ||
42 | unsigned int i; | ||
43 | u32 srev; | ||
44 | u16 ret; | ||
45 | |||
46 | /* | ||
47 | * Set the radio chip access register | ||
48 | */ | ||
49 | switch (chan) { | ||
50 | case CHANNEL_2GHZ: | ||
51 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); | ||
52 | break; | ||
53 | case CHANNEL_5GHZ: | ||
54 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
55 | break; | ||
56 | default: | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | mdelay(2); | ||
61 | |||
62 | /* ...wait until PHY is ready and read the selected radio revision */ | ||
63 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | ||
64 | |||
65 | for (i = 0; i < 8; i++) | ||
66 | ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); | ||
67 | |||
68 | if (ah->ah_version == AR5K_AR5210) { | ||
69 | srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; | ||
70 | ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; | ||
71 | } else { | ||
72 | srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; | ||
73 | ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | | ||
74 | ((srev & 0x0f) << 4), 8); | ||
75 | } | ||
76 | |||
77 | /* Reset to the 5GHz mode */ | ||
78 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
79 | |||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Check if a channel is supported | ||
85 | */ | ||
86 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) | ||
87 | { | ||
88 | /* Check if the channel is in our supported range */ | ||
89 | if (flags & CHANNEL_2GHZ) { | ||
90 | if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && | ||
91 | (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) | ||
92 | return true; | ||
93 | } else if (flags & CHANNEL_5GHZ) | ||
94 | if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && | ||
95 | (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) | ||
96 | return true; | ||
97 | |||
98 | return false; | ||
99 | } | ||
100 | |||
101 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | ||
102 | struct ieee80211_channel *channel) | ||
103 | { | ||
104 | u8 refclk_freq; | ||
105 | |||
106 | if ((ah->ah_radio == AR5K_RF5112) || | ||
107 | (ah->ah_radio == AR5K_RF5413) || | ||
108 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
109 | refclk_freq = 40; | ||
110 | else | ||
111 | refclk_freq = 32; | ||
112 | |||
113 | if ((channel->center_freq % refclk_freq != 0) && | ||
114 | ((channel->center_freq % refclk_freq < 10) || | ||
115 | (channel->center_freq % refclk_freq > 22))) | ||
116 | return true; | ||
117 | else | ||
118 | return false; | ||
119 | } | ||
120 | |||
32 | /* | 121 | /* |
33 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER | 122 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER |
34 | */ | 123 | */ |
@@ -110,12 +199,124 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
110 | return data; | 199 | return data; |
111 | } | 200 | } |
112 | 201 | ||
202 | /** | ||
203 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | ||
204 | * | ||
205 | * @ah: the &struct ath5k_hw | ||
206 | * @channel: the currently set channel upon reset | ||
207 | * | ||
208 | * Write the delta slope coefficient (used on pilot tracking ?) for OFDM | ||
209 | * operation on the AR5212 upon reset. This is a helper for ath5k_hw_phy_init. | ||
210 | * | ||
211 | * Since delta slope is floating point we split it on its exponent and | ||
212 | * mantissa and provide these values on hw. | ||
213 | * | ||
214 | * For more infos i think this patent is related | ||
215 | * http://www.freepatentsonline.com/7184495.html | ||
216 | */ | ||
217 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | ||
218 | struct ieee80211_channel *channel) | ||
219 | { | ||
220 | /* Get exponent and mantissa and set it */ | ||
221 | u32 coef_scaled, coef_exp, coef_man, | ||
222 | ds_coef_exp, ds_coef_man, clock; | ||
223 | |||
224 | BUG_ON(!(ah->ah_version == AR5K_AR5212) || | ||
225 | !(channel->hw_value & CHANNEL_OFDM)); | ||
226 | |||
227 | /* Get coefficient | ||
228 | * ALGO: coef = (5 * clock / carrier_freq) / 2 | ||
229 | * we scale coef by shifting clock value by 24 for | ||
230 | * better precision since we use integers */ | ||
231 | switch (ah->ah_bwmode) { | ||
232 | case AR5K_BWMODE_40MHZ: | ||
233 | clock = 40 * 2; | ||
234 | break; | ||
235 | case AR5K_BWMODE_10MHZ: | ||
236 | clock = 40 / 2; | ||
237 | break; | ||
238 | case AR5K_BWMODE_5MHZ: | ||
239 | clock = 40 / 4; | ||
240 | break; | ||
241 | default: | ||
242 | clock = 40; | ||
243 | break; | ||
244 | } | ||
245 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; | ||
246 | |||
247 | /* Get exponent | ||
248 | * ALGO: coef_exp = 14 - highest set bit position */ | ||
249 | coef_exp = ilog2(coef_scaled); | ||
250 | |||
251 | /* Doesn't make sense if it's zero*/ | ||
252 | if (!coef_scaled || !coef_exp) | ||
253 | return -EINVAL; | ||
254 | |||
255 | /* Note: we've shifted coef_scaled by 24 */ | ||
256 | coef_exp = 14 - (coef_exp - 24); | ||
257 | |||
258 | |||
259 | /* Get mantissa (significant digits) | ||
260 | * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ | ||
261 | coef_man = coef_scaled + | ||
262 | (1 << (24 - coef_exp - 1)); | ||
263 | |||
264 | /* Calculate delta slope coefficient exponent | ||
265 | * and mantissa (remove scaling) and set them on hw */ | ||
266 | ds_coef_man = coef_man >> (24 - coef_exp); | ||
267 | ds_coef_exp = coef_exp - 16; | ||
268 | |||
269 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
270 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | ||
271 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
272 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | ||
278 | { | ||
279 | /*Just a try M.F.*/ | ||
280 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Wait for synth to settle | ||
287 | */ | ||
288 | static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, | ||
289 | struct ieee80211_channel *channel) | ||
290 | { | ||
291 | /* | ||
292 | * On 5211+ read activation -> rx delay | ||
293 | * and use it (100ns steps). | ||
294 | */ | ||
295 | if (ah->ah_version != AR5K_AR5210) { | ||
296 | u32 delay; | ||
297 | delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
298 | AR5K_PHY_RX_DELAY_M; | ||
299 | delay = (channel->hw_value & CHANNEL_CCK) ? | ||
300 | ((delay << 2) / 22) : (delay / 10); | ||
301 | if (ah->ah_bwmode == AR5K_BWMODE_10MHZ) | ||
302 | delay = delay << 1; | ||
303 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ) | ||
304 | delay = delay << 2; | ||
305 | /* XXX: /2 on turbo ? Let's be safe | ||
306 | * for now */ | ||
307 | udelay(100 + delay); | ||
308 | } else { | ||
309 | mdelay(1); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | |||
113 | /**********************\ | 314 | /**********************\ |
114 | * RF Gain optimization * | 315 | * RF Gain optimization * |
115 | \**********************/ | 316 | \**********************/ |
116 | 317 | ||
117 | /* | 318 | /* |
118 | * This code is used to optimize rf gain on different environments | 319 | * This code is used to optimize RF gain on different environments |
119 | * (temperature mostly) based on feedback from a power detector. | 320 | * (temperature mostly) based on feedback from a power detector. |
120 | * | 321 | * |
121 | * It's only used on RF5111 and RF5112, later RF chips seem to have | 322 | * It's only used on RF5111 and RF5112, later RF chips seem to have |
@@ -134,11 +335,11 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
134 | * http://madwifi-project.org/ticket/1659 | 335 | * http://madwifi-project.org/ticket/1659 |
135 | * with various measurements and diagrams | 336 | * with various measurements and diagrams |
136 | * | 337 | * |
137 | * TODO: Deal with power drops due to probes by setting an apropriate | 338 | * TODO: Deal with power drops due to probes by setting an appropriate |
138 | * tx power on the probe packets ! Make this part of the calibration process. | 339 | * tx power on the probe packets ! Make this part of the calibration process. |
139 | */ | 340 | */ |
140 | 341 | ||
141 | /* Initialize ah_gain durring attach */ | 342 | /* Initialize ah_gain during attach */ |
142 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) | 343 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) |
143 | { | 344 | { |
144 | /* Initialize the gain optimization values */ | 345 | /* Initialize the gain optimization values */ |
@@ -302,7 +503,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | |||
302 | } | 503 | } |
303 | 504 | ||
304 | /* Perform gain_F adjustment by choosing the right set | 505 | /* Perform gain_F adjustment by choosing the right set |
305 | * of parameters from rf gain optimization ladder */ | 506 | * of parameters from RF gain optimization ladder */ |
306 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) | 507 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) |
307 | { | 508 | { |
308 | const struct ath5k_gain_opt *go; | 509 | const struct ath5k_gain_opt *go; |
@@ -367,7 +568,7 @@ done: | |||
367 | return ret; | 568 | return ret; |
368 | } | 569 | } |
369 | 570 | ||
370 | /* Main callback for thermal rf gain calibration engine | 571 | /* Main callback for thermal RF gain calibration engine |
371 | * Check for a new gain reading and schedule an adjustment | 572 | * Check for a new gain reading and schedule an adjustment |
372 | * if needed. | 573 | * if needed. |
373 | * | 574 | * |
@@ -433,13 +634,13 @@ done: | |||
433 | return ah->ah_gain.g_state; | 634 | return ah->ah_gain.g_state; |
434 | } | 635 | } |
435 | 636 | ||
436 | /* Write initial rf gain table to set the RF sensitivity | 637 | /* Write initial RF gain table to set the RF sensitivity |
437 | * this one works on all RF chips and has nothing to do | 638 | * this one works on all RF chips and has nothing to do |
438 | * with gain_F calibration */ | 639 | * with gain_F calibration */ |
439 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | 640 | static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) |
440 | { | 641 | { |
441 | const struct ath5k_ini_rfgain *ath5k_rfg; | 642 | const struct ath5k_ini_rfgain *ath5k_rfg; |
442 | unsigned int i, size; | 643 | unsigned int i, size, index; |
443 | 644 | ||
444 | switch (ah->ah_radio) { | 645 | switch (ah->ah_radio) { |
445 | case AR5K_RF5111: | 646 | case AR5K_RF5111: |
@@ -471,17 +672,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
471 | return -EINVAL; | 672 | return -EINVAL; |
472 | } | 673 | } |
473 | 674 | ||
474 | switch (freq) { | 675 | index = (band == IEEE80211_BAND_2GHZ) ? 1 : 0; |
475 | case AR5K_INI_RFGAIN_2GHZ: | ||
476 | case AR5K_INI_RFGAIN_5GHZ: | ||
477 | break; | ||
478 | default: | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | 676 | ||
482 | for (i = 0; i < size; i++) { | 677 | for (i = 0; i < size; i++) { |
483 | AR5K_REG_WAIT(i); | 678 | AR5K_REG_WAIT(i); |
484 | ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq], | 679 | ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[index], |
485 | (u32)ath5k_rfg[i].rfg_register); | 680 | (u32)ath5k_rfg[i].rfg_register); |
486 | } | 681 | } |
487 | 682 | ||
@@ -494,12 +689,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
494 | * RF Registers setup * | 689 | * RF Registers setup * |
495 | \********************/ | 690 | \********************/ |
496 | 691 | ||
497 | |||
498 | /* | 692 | /* |
499 | * Setup RF registers by writing rf buffer on hw | 693 | * Setup RF registers by writing RF buffer on hw |
500 | */ | 694 | */ |
501 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 695 | static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, |
502 | unsigned int mode) | 696 | struct ieee80211_channel *channel, unsigned int mode) |
503 | { | 697 | { |
504 | const struct ath5k_rf_reg *rf_regs; | 698 | const struct ath5k_rf_reg *rf_regs; |
505 | const struct ath5k_ini_rfbuffer *ini_rfb; | 699 | const struct ath5k_ini_rfbuffer *ini_rfb; |
@@ -571,7 +765,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
571 | return -EINVAL; | 765 | return -EINVAL; |
572 | } | 766 | } |
573 | 767 | ||
574 | /* If it's the first time we set rf buffer, allocate | 768 | /* If it's the first time we set RF buffer, allocate |
575 | * ah->ah_rf_banks based on ah->ah_rf_banks_size | 769 | * ah->ah_rf_banks based on ah->ah_rf_banks_size |
576 | * we set above */ | 770 | * we set above */ |
577 | if (ah->ah_rf_banks == NULL) { | 771 | if (ah->ah_rf_banks == NULL) { |
@@ -652,6 +846,11 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
652 | 846 | ||
653 | g_step = &go->go_step[ah->ah_gain.g_step_idx]; | 847 | g_step = &go->go_step[ah->ah_gain.g_step_idx]; |
654 | 848 | ||
849 | /* Set turbo mode (N/A on RF5413) */ | ||
850 | if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) && | ||
851 | (ah->ah_radio != AR5K_RF5413)) | ||
852 | ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_TURBO, false); | ||
853 | |||
655 | /* Bank Modifications (chip-specific) */ | 854 | /* Bank Modifications (chip-specific) */ |
656 | if (ah->ah_radio == AR5K_RF5111) { | 855 | if (ah->ah_radio == AR5K_RF5111) { |
657 | 856 | ||
@@ -691,7 +890,23 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
691 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], | 890 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], |
692 | AR5K_RF_PLO_SEL, true); | 891 | AR5K_RF_PLO_SEL, true); |
693 | 892 | ||
694 | /* TODO: Half/quarter channel support */ | 893 | /* Tweak power detectors for half/quarter rate support */ |
894 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || | ||
895 | ah->ah_bwmode == AR5K_BWMODE_10MHZ) { | ||
896 | u8 wait_i; | ||
897 | |||
898 | ath5k_hw_rfb_op(ah, rf_regs, 0x1f, | ||
899 | AR5K_RF_WAIT_S, true); | ||
900 | |||
901 | wait_i = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? | ||
902 | 0x1f : 0x10; | ||
903 | |||
904 | ath5k_hw_rfb_op(ah, rf_regs, wait_i, | ||
905 | AR5K_RF_WAIT_I, true); | ||
906 | ath5k_hw_rfb_op(ah, rf_regs, 3, | ||
907 | AR5K_RF_MAX_TIME, true); | ||
908 | |||
909 | } | ||
695 | } | 910 | } |
696 | 911 | ||
697 | if (ah->ah_radio == AR5K_RF5112) { | 912 | if (ah->ah_radio == AR5K_RF5112) { |
@@ -789,8 +1004,20 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
789 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], | 1004 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], |
790 | AR5K_RF_GAIN_I, true); | 1005 | AR5K_RF_GAIN_I, true); |
791 | 1006 | ||
792 | /* TODO: Half/quarter channel support */ | 1007 | /* Tweak power detector for half/quarter rates */ |
1008 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || | ||
1009 | ah->ah_bwmode == AR5K_BWMODE_10MHZ) { | ||
1010 | u8 pd_delay; | ||
1011 | |||
1012 | pd_delay = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? | ||
1013 | 0xf : 0x8; | ||
1014 | |||
1015 | ath5k_hw_rfb_op(ah, rf_regs, pd_delay, | ||
1016 | AR5K_RF_PD_PERIOD_A, true); | ||
1017 | ath5k_hw_rfb_op(ah, rf_regs, 0xf, | ||
1018 | AR5K_RF_PD_DELAY_A, true); | ||
793 | 1019 | ||
1020 | } | ||
794 | } | 1021 | } |
795 | 1022 | ||
796 | if (ah->ah_radio == AR5K_RF5413 && | 1023 | if (ah->ah_radio == AR5K_RF5413 && |
@@ -822,25 +1049,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
822 | \**************************/ | 1049 | \**************************/ |
823 | 1050 | ||
824 | /* | 1051 | /* |
825 | * Check if a channel is supported | 1052 | * Conversion needed for RF5110 |
826 | */ | ||
827 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) | ||
828 | { | ||
829 | /* Check if the channel is in our supported range */ | ||
830 | if (flags & CHANNEL_2GHZ) { | ||
831 | if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && | ||
832 | (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) | ||
833 | return true; | ||
834 | } else if (flags & CHANNEL_5GHZ) | ||
835 | if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && | ||
836 | (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) | ||
837 | return true; | ||
838 | |||
839 | return false; | ||
840 | } | ||
841 | |||
842 | /* | ||
843 | * Convertion needed for RF5110 | ||
844 | */ | 1053 | */ |
845 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) | 1054 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) |
846 | { | 1055 | { |
@@ -879,7 +1088,7 @@ static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, | |||
879 | } | 1088 | } |
880 | 1089 | ||
881 | /* | 1090 | /* |
882 | * Convertion needed for 5111 | 1091 | * Conversion needed for 5111 |
883 | */ | 1092 | */ |
884 | static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, | 1093 | static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, |
885 | struct ath5k_athchan_2ghz *athchan) | 1094 | struct ath5k_athchan_2ghz *athchan) |
@@ -1045,7 +1254,8 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | |||
1045 | /* | 1254 | /* |
1046 | * Set a channel on the radio chip | 1255 | * Set a channel on the radio chip |
1047 | */ | 1256 | */ |
1048 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | 1257 | static int ath5k_hw_channel(struct ath5k_hw *ah, |
1258 | struct ieee80211_channel *channel) | ||
1049 | { | 1259 | { |
1050 | int ret; | 1260 | int ret; |
1051 | /* | 1261 | /* |
@@ -1071,6 +1281,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1071 | case AR5K_RF5111: | 1281 | case AR5K_RF5111: |
1072 | ret = ath5k_hw_rf5111_channel(ah, channel); | 1282 | ret = ath5k_hw_rf5111_channel(ah, channel); |
1073 | break; | 1283 | break; |
1284 | case AR5K_RF2317: | ||
1074 | case AR5K_RF2425: | 1285 | case AR5K_RF2425: |
1075 | ret = ath5k_hw_rf2425_channel(ah, channel); | 1286 | ret = ath5k_hw_rf2425_channel(ah, channel); |
1076 | break; | 1287 | break; |
@@ -1092,7 +1303,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1092 | } | 1303 | } |
1093 | 1304 | ||
1094 | ah->ah_current_channel = channel; | 1305 | ah->ah_current_channel = channel; |
1095 | ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; | ||
1096 | 1306 | ||
1097 | return 0; | 1307 | return 0; |
1098 | } | 1308 | } |
@@ -1101,18 +1311,12 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1101 | PHY calibration | 1311 | PHY calibration |
1102 | \*****************/ | 1312 | \*****************/ |
1103 | 1313 | ||
1104 | static int sign_extend(int val, const int nbits) | ||
1105 | { | ||
1106 | int order = BIT(nbits-1); | ||
1107 | return (val ^ order) - order; | ||
1108 | } | ||
1109 | |||
1110 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) | 1314 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) |
1111 | { | 1315 | { |
1112 | s32 val; | 1316 | s32 val; |
1113 | 1317 | ||
1114 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); | 1318 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); |
1115 | return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9); | 1319 | return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8); |
1116 | } | 1320 | } |
1117 | 1321 | ||
1118 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) | 1322 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) |
@@ -1180,22 +1384,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | |||
1180 | return; | 1384 | return; |
1181 | } | 1385 | } |
1182 | 1386 | ||
1183 | switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) { | 1387 | ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); |
1184 | case CHANNEL_A: | ||
1185 | case CHANNEL_T: | ||
1186 | case CHANNEL_XR: | ||
1187 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
1188 | break; | ||
1189 | case CHANNEL_G: | ||
1190 | case CHANNEL_TG: | ||
1191 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
1192 | break; | ||
1193 | default: | ||
1194 | case CHANNEL_B: | ||
1195 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1196 | break; | ||
1197 | } | ||
1198 | |||
1199 | 1388 | ||
1200 | /* completed NF calibration, test threshold */ | 1389 | /* completed NF calibration, test threshold */ |
1201 | nf = ath5k_hw_read_measured_noise_floor(ah); | 1390 | nf = ath5k_hw_read_measured_noise_floor(ah); |
@@ -1257,7 +1446,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1257 | * Disable beacons and RX/TX queues, wait | 1446 | * Disable beacons and RX/TX queues, wait |
1258 | */ | 1447 | */ |
1259 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, | 1448 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, |
1260 | AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); | 1449 | AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); |
1261 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); | 1450 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); |
1262 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); | 1451 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); |
1263 | 1452 | ||
@@ -1336,7 +1525,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1336 | * Re-enable RX/TX and beacons | 1525 | * Re-enable RX/TX and beacons |
1337 | */ | 1526 | */ |
1338 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, | 1527 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, |
1339 | AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); | 1528 | AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); |
1340 | ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); | 1529 | ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); |
1341 | 1530 | ||
1342 | return 0; | 1531 | return 0; |
@@ -1377,7 +1566,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) | |||
1377 | 1566 | ||
1378 | /* protect against divide by 0 and loss of sign bits */ | 1567 | /* protect against divide by 0 and loss of sign bits */ |
1379 | if (i_coffd == 0 || q_coffd < 2) | 1568 | if (i_coffd == 0 || q_coffd < 2) |
1380 | return -1; | 1569 | return 0; |
1381 | 1570 | ||
1382 | i_coff = (-iq_corr) / i_coffd; | 1571 | i_coff = (-iq_corr) / i_coffd; |
1383 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ | 1572 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ |
@@ -1424,31 +1613,12 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | |||
1424 | return ret; | 1613 | return ret; |
1425 | } | 1614 | } |
1426 | 1615 | ||
1616 | |||
1427 | /***************************\ | 1617 | /***************************\ |
1428 | * Spur mitigation functions * | 1618 | * Spur mitigation functions * |
1429 | \***************************/ | 1619 | \***************************/ |
1430 | 1620 | ||
1431 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1621 | static void |
1432 | struct ieee80211_channel *channel) | ||
1433 | { | ||
1434 | u8 refclk_freq; | ||
1435 | |||
1436 | if ((ah->ah_radio == AR5K_RF5112) || | ||
1437 | (ah->ah_radio == AR5K_RF5413) || | ||
1438 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
1439 | refclk_freq = 40; | ||
1440 | else | ||
1441 | refclk_freq = 32; | ||
1442 | |||
1443 | if ((channel->center_freq % refclk_freq != 0) && | ||
1444 | ((channel->center_freq % refclk_freq < 10) || | ||
1445 | (channel->center_freq % refclk_freq > 22))) | ||
1446 | return true; | ||
1447 | else | ||
1448 | return false; | ||
1449 | } | ||
1450 | |||
1451 | void | ||
1452 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | 1622 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, |
1453 | struct ieee80211_channel *channel) | 1623 | struct ieee80211_channel *channel) |
1454 | { | 1624 | { |
@@ -1477,7 +1647,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1477 | spur_chan_fbin = AR5K_EEPROM_NO_SPUR; | 1647 | spur_chan_fbin = AR5K_EEPROM_NO_SPUR; |
1478 | spur_detection_window = AR5K_SPUR_CHAN_WIDTH; | 1648 | spur_detection_window = AR5K_SPUR_CHAN_WIDTH; |
1479 | /* XXX: Half/Quarter channels ?*/ | 1649 | /* XXX: Half/Quarter channels ?*/ |
1480 | if (channel->hw_value & CHANNEL_TURBO) | 1650 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
1481 | spur_detection_window *= 2; | 1651 | spur_detection_window *= 2; |
1482 | 1652 | ||
1483 | for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { | 1653 | for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { |
@@ -1506,32 +1676,43 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1506 | * Calculate deltas: | 1676 | * Calculate deltas: |
1507 | * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 | 1677 | * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 |
1508 | * spur_delta_phase -> spur_offset / chip_freq << 11 | 1678 | * spur_delta_phase -> spur_offset / chip_freq << 11 |
1509 | * Note: Both values have 100KHz resolution | 1679 | * Note: Both values have 100Hz resolution |
1510 | */ | 1680 | */ |
1511 | /* XXX: Half/Quarter rate channels ? */ | 1681 | switch (ah->ah_bwmode) { |
1512 | switch (channel->hw_value) { | 1682 | case AR5K_BWMODE_40MHZ: |
1513 | case CHANNEL_A: | ||
1514 | /* Both sample_freq and chip_freq are 40MHz */ | ||
1515 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1516 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
1517 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1518 | break; | ||
1519 | case CHANNEL_G: | ||
1520 | /* sample_freq -> 40MHz chip_freq -> 44MHz | ||
1521 | * (for b compatibility) */ | ||
1522 | spur_freq_sigma_delta = (spur_offset << 8) / 55; | ||
1523 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1524 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1525 | break; | ||
1526 | case CHANNEL_T: | ||
1527 | case CHANNEL_TG: | ||
1528 | /* Both sample_freq and chip_freq are 80MHz */ | 1683 | /* Both sample_freq and chip_freq are 80MHz */ |
1529 | spur_delta_phase = (spur_offset << 16) / 25; | 1684 | spur_delta_phase = (spur_offset << 16) / 25; |
1530 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | 1685 | spur_freq_sigma_delta = (spur_delta_phase >> 10); |
1531 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz; | 1686 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz * 2; |
1532 | break; | 1687 | break; |
1688 | case AR5K_BWMODE_10MHZ: | ||
1689 | /* Both sample_freq and chip_freq are 20MHz (?) */ | ||
1690 | spur_delta_phase = (spur_offset << 18) / 25; | ||
1691 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
1692 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2; | ||
1693 | case AR5K_BWMODE_5MHZ: | ||
1694 | /* Both sample_freq and chip_freq are 10MHz (?) */ | ||
1695 | spur_delta_phase = (spur_offset << 19) / 25; | ||
1696 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
1697 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; | ||
1533 | default: | 1698 | default: |
1534 | return; | 1699 | if (channel->hw_value == CHANNEL_A) { |
1700 | /* Both sample_freq and chip_freq are 40MHz */ | ||
1701 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1702 | spur_freq_sigma_delta = | ||
1703 | (spur_delta_phase >> 10); | ||
1704 | symbol_width = | ||
1705 | AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1706 | } else { | ||
1707 | /* sample_freq -> 40MHz chip_freq -> 44MHz | ||
1708 | * (for b compatibility) */ | ||
1709 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1710 | spur_freq_sigma_delta = | ||
1711 | (spur_offset << 8) / 55; | ||
1712 | symbol_width = | ||
1713 | AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1714 | } | ||
1715 | break; | ||
1535 | } | 1716 | } |
1536 | 1717 | ||
1537 | /* Calculate pilot and magnitude masks */ | 1718 | /* Calculate pilot and magnitude masks */ |
@@ -1582,7 +1763,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1582 | else if (curr_sym_off >= 31 && curr_sym_off <= 46) | 1763 | else if (curr_sym_off >= 31 && curr_sym_off <= 46) |
1583 | mag_mask[2] |= | 1764 | mag_mask[2] |= |
1584 | plt_mag_map << (curr_sym_off - 31) * 2; | 1765 | plt_mag_map << (curr_sym_off - 31) * 2; |
1585 | else if (curr_sym_off >= 46 && curr_sym_off <= 53) | 1766 | else if (curr_sym_off >= 47 && curr_sym_off <= 53) |
1586 | mag_mask[3] |= | 1767 | mag_mask[3] |= |
1587 | plt_mag_map << (curr_sym_off - 47) * 2; | 1768 | plt_mag_map << (curr_sym_off - 47) * 2; |
1588 | 1769 | ||
@@ -1671,63 +1852,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1671 | } | 1852 | } |
1672 | } | 1853 | } |
1673 | 1854 | ||
1674 | /********************\ | ||
1675 | Misc PHY functions | ||
1676 | \********************/ | ||
1677 | |||
1678 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | ||
1679 | { | ||
1680 | /*Just a try M.F.*/ | ||
1681 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
1682 | |||
1683 | return 0; | ||
1684 | } | ||
1685 | |||
1686 | /* | ||
1687 | * Get the PHY Chip revision | ||
1688 | */ | ||
1689 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | ||
1690 | { | ||
1691 | unsigned int i; | ||
1692 | u32 srev; | ||
1693 | u16 ret; | ||
1694 | |||
1695 | /* | ||
1696 | * Set the radio chip access register | ||
1697 | */ | ||
1698 | switch (chan) { | ||
1699 | case CHANNEL_2GHZ: | ||
1700 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); | ||
1701 | break; | ||
1702 | case CHANNEL_5GHZ: | ||
1703 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
1704 | break; | ||
1705 | default: | ||
1706 | return 0; | ||
1707 | } | ||
1708 | |||
1709 | mdelay(2); | ||
1710 | |||
1711 | /* ...wait until PHY is ready and read the selected radio revision */ | ||
1712 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | ||
1713 | |||
1714 | for (i = 0; i < 8; i++) | ||
1715 | ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); | ||
1716 | |||
1717 | if (ah->ah_version == AR5K_AR5210) { | ||
1718 | srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; | ||
1719 | ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; | ||
1720 | } else { | ||
1721 | srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; | ||
1722 | ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | | ||
1723 | ((srev & 0x0f) << 4), 8); | ||
1724 | } | ||
1725 | |||
1726 | /* Reset to the 5GHz mode */ | ||
1727 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
1728 | |||
1729 | return ret; | ||
1730 | } | ||
1731 | 1855 | ||
1732 | /*****************\ | 1856 | /*****************\ |
1733 | * Antenna control * | 1857 | * Antenna control * |
@@ -1821,7 +1945,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1821 | struct ieee80211_channel *channel = ah->ah_current_channel; | 1945 | struct ieee80211_channel *channel = ah->ah_current_channel; |
1822 | bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; | 1946 | bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; |
1823 | bool use_def_for_sg; | 1947 | bool use_def_for_sg; |
1824 | u8 def_ant, tx_ant, ee_mode; | 1948 | int ee_mode; |
1949 | u8 def_ant, tx_ant; | ||
1825 | u32 sta_id1 = 0; | 1950 | u32 sta_id1 = 0; |
1826 | 1951 | ||
1827 | /* if channel is not initialized yet we can't set the antennas | 1952 | /* if channel is not initialized yet we can't set the antennas |
@@ -1833,20 +1958,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1833 | 1958 | ||
1834 | def_ant = ah->ah_def_ant; | 1959 | def_ant = ah->ah_def_ant; |
1835 | 1960 | ||
1836 | switch (channel->hw_value & CHANNEL_MODES) { | 1961 | ee_mode = ath5k_eeprom_mode_from_channel(channel); |
1837 | case CHANNEL_A: | 1962 | if (ee_mode < 0) { |
1838 | case CHANNEL_T: | ||
1839 | case CHANNEL_XR: | ||
1840 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
1841 | break; | ||
1842 | case CHANNEL_G: | ||
1843 | case CHANNEL_TG: | ||
1844 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
1845 | break; | ||
1846 | case CHANNEL_B: | ||
1847 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1848 | break; | ||
1849 | default: | ||
1850 | ATH5K_ERR(ah->ah_sc, | 1963 | ATH5K_ERR(ah->ah_sc, |
1851 | "invalid channel: %d\n", channel->center_freq); | 1964 | "invalid channel: %d\n", channel->center_freq); |
1852 | return; | 1965 | return; |
@@ -2088,7 +2201,7 @@ ath5k_create_power_curve(s16 pmin, s16 pmax, | |||
2088 | /* | 2201 | /* |
2089 | * Get the surrounding per-channel power calibration piers | 2202 | * Get the surrounding per-channel power calibration piers |
2090 | * for a given frequency so that we can interpolate between | 2203 | * for a given frequency so that we can interpolate between |
2091 | * them and come up with an apropriate dataset for our current | 2204 | * them and come up with an appropriate dataset for our current |
2092 | * channel. | 2205 | * channel. |
2093 | */ | 2206 | */ |
2094 | static void | 2207 | static void |
@@ -2274,20 +2387,20 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, | |||
2274 | 2387 | ||
2275 | switch (channel->hw_value & CHANNEL_MODES) { | 2388 | switch (channel->hw_value & CHANNEL_MODES) { |
2276 | case CHANNEL_A: | 2389 | case CHANNEL_A: |
2277 | ctl_mode |= AR5K_CTL_11A; | 2390 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
2391 | ctl_mode |= AR5K_CTL_TURBO; | ||
2392 | else | ||
2393 | ctl_mode |= AR5K_CTL_11A; | ||
2278 | break; | 2394 | break; |
2279 | case CHANNEL_G: | 2395 | case CHANNEL_G: |
2280 | ctl_mode |= AR5K_CTL_11G; | 2396 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
2397 | ctl_mode |= AR5K_CTL_TURBOG; | ||
2398 | else | ||
2399 | ctl_mode |= AR5K_CTL_11G; | ||
2281 | break; | 2400 | break; |
2282 | case CHANNEL_B: | 2401 | case CHANNEL_B: |
2283 | ctl_mode |= AR5K_CTL_11B; | 2402 | ctl_mode |= AR5K_CTL_11B; |
2284 | break; | 2403 | break; |
2285 | case CHANNEL_T: | ||
2286 | ctl_mode |= AR5K_CTL_TURBO; | ||
2287 | break; | ||
2288 | case CHANNEL_TG: | ||
2289 | ctl_mode |= AR5K_CTL_TURBOG; | ||
2290 | break; | ||
2291 | case CHANNEL_XR: | 2404 | case CHANNEL_XR: |
2292 | /* Fall through */ | 2405 | /* Fall through */ |
2293 | default: | 2406 | default: |
@@ -2481,7 +2594,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, | |||
2481 | 2594 | ||
2482 | /* Write PCDAC values on hw */ | 2595 | /* Write PCDAC values on hw */ |
2483 | static void | 2596 | static void |
2484 | ath5k_setup_pcdac_table(struct ath5k_hw *ah) | 2597 | ath5k_write_pcdac_table(struct ath5k_hw *ah) |
2485 | { | 2598 | { |
2486 | u8 *pcdac_out = ah->ah_txpower.txp_pd_table; | 2599 | u8 *pcdac_out = ah->ah_txpower.txp_pd_table; |
2487 | int i; | 2600 | int i; |
@@ -2505,7 +2618,7 @@ ath5k_setup_pcdac_table(struct ath5k_hw *ah) | |||
2505 | /* | 2618 | /* |
2506 | * Set the gain boundaries and create final Power to PDADC table | 2619 | * Set the gain boundaries and create final Power to PDADC table |
2507 | * | 2620 | * |
2508 | * We can have up to 4 pd curves, we need to do a simmilar process | 2621 | * We can have up to 4 pd curves, we need to do a similar process |
2509 | * as we do for RF5112. This time we don't have an edge_flag but we | 2622 | * as we do for RF5112. This time we don't have an edge_flag but we |
2510 | * set the gain boundaries on a separate register. | 2623 | * set the gain boundaries on a separate register. |
2511 | */ | 2624 | */ |
@@ -2630,10 +2743,12 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, | |||
2630 | 2743 | ||
2631 | /* Write PDADC values on hw */ | 2744 | /* Write PDADC values on hw */ |
2632 | static void | 2745 | static void |
2633 | ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, | 2746 | ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) |
2634 | u8 pdcurves, u8 *pdg_to_idx) | ||
2635 | { | 2747 | { |
2748 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
2636 | u8 *pdadc_out = ah->ah_txpower.txp_pd_table; | 2749 | u8 *pdadc_out = ah->ah_txpower.txp_pd_table; |
2750 | u8 *pdg_to_idx = ee->ee_pdc_to_idx[ee_mode]; | ||
2751 | u8 pdcurves = ee->ee_pd_gains[ee_mode]; | ||
2637 | u32 reg; | 2752 | u32 reg; |
2638 | u8 i; | 2753 | u8 i; |
2639 | 2754 | ||
@@ -2711,13 +2826,13 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2711 | u32 target = channel->center_freq; | 2826 | u32 target = channel->center_freq; |
2712 | int pdg, i; | 2827 | int pdg, i; |
2713 | 2828 | ||
2714 | /* Get surounding freq piers for this channel */ | 2829 | /* Get surrounding freq piers for this channel */ |
2715 | ath5k_get_chan_pcal_surrounding_piers(ah, channel, | 2830 | ath5k_get_chan_pcal_surrounding_piers(ah, channel, |
2716 | &pcinfo_L, | 2831 | &pcinfo_L, |
2717 | &pcinfo_R); | 2832 | &pcinfo_R); |
2718 | 2833 | ||
2719 | /* Loop over pd gain curves on | 2834 | /* Loop over pd gain curves on |
2720 | * surounding freq piers by index */ | 2835 | * surrounding freq piers by index */ |
2721 | for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { | 2836 | for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { |
2722 | 2837 | ||
2723 | /* Fill curves in reverse order | 2838 | /* Fill curves in reverse order |
@@ -2808,7 +2923,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2808 | } | 2923 | } |
2809 | 2924 | ||
2810 | /* Interpolate between curves | 2925 | /* Interpolate between curves |
2811 | * of surounding freq piers to | 2926 | * of surrounding freq piers to |
2812 | * get the final curve for this | 2927 | * get the final curve for this |
2813 | * pd gain. Re-use tmpL for interpolation | 2928 | * pd gain. Re-use tmpL for interpolation |
2814 | * output */ | 2929 | * output */ |
@@ -2832,7 +2947,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2832 | 2947 | ||
2833 | /* Fill min and max power levels for this | 2948 | /* Fill min and max power levels for this |
2834 | * channel by interpolating the values on | 2949 | * channel by interpolating the values on |
2835 | * surounding channels to complete the dataset */ | 2950 | * surrounding channels to complete the dataset */ |
2836 | ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, | 2951 | ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, |
2837 | (s16) pcinfo_L->freq, | 2952 | (s16) pcinfo_L->freq, |
2838 | (s16) pcinfo_R->freq, | 2953 | (s16) pcinfo_R->freq, |
@@ -2843,8 +2958,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2843 | (s16) pcinfo_R->freq, | 2958 | (s16) pcinfo_R->freq, |
2844 | pcinfo_L->max_pwr, pcinfo_R->max_pwr); | 2959 | pcinfo_L->max_pwr, pcinfo_R->max_pwr); |
2845 | 2960 | ||
2846 | /* We are ready to go, fill PCDAC/PDADC | 2961 | /* Fill PCDAC/PDADC table */ |
2847 | * table and write settings on hardware */ | ||
2848 | switch (type) { | 2962 | switch (type) { |
2849 | case AR5K_PWRTABLE_LINEAR_PCDAC: | 2963 | case AR5K_PWRTABLE_LINEAR_PCDAC: |
2850 | /* For RF5112 we can have one or two curves | 2964 | /* For RF5112 we can have one or two curves |
@@ -2857,9 +2971,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2857 | * match max power value with max | 2971 | * match max power value with max |
2858 | * table index */ | 2972 | * table index */ |
2859 | ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); | 2973 | ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); |
2860 | |||
2861 | /* Write settings on hw */ | ||
2862 | ath5k_setup_pcdac_table(ah); | ||
2863 | break; | 2974 | break; |
2864 | case AR5K_PWRTABLE_PWR_TO_PCDAC: | 2975 | case AR5K_PWRTABLE_PWR_TO_PCDAC: |
2865 | /* We are done for RF5111 since it has only | 2976 | /* We are done for RF5111 since it has only |
@@ -2869,9 +2980,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2869 | /* No rate powertable adjustment for RF5111 */ | 2980 | /* No rate powertable adjustment for RF5111 */ |
2870 | ah->ah_txpower.txp_min_idx = 0; | 2981 | ah->ah_txpower.txp_min_idx = 0; |
2871 | ah->ah_txpower.txp_offset = 0; | 2982 | ah->ah_txpower.txp_offset = 0; |
2872 | |||
2873 | /* Write settings on hw */ | ||
2874 | ath5k_setup_pcdac_table(ah); | ||
2875 | break; | 2983 | break; |
2876 | case AR5K_PWRTABLE_PWR_TO_PDADC: | 2984 | case AR5K_PWRTABLE_PWR_TO_PDADC: |
2877 | /* Set PDADC boundaries and fill | 2985 | /* Set PDADC boundaries and fill |
@@ -2879,9 +2987,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2879 | ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, | 2987 | ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, |
2880 | ee->ee_pd_gains[ee_mode]); | 2988 | ee->ee_pd_gains[ee_mode]); |
2881 | 2989 | ||
2882 | /* Write settings on hw */ | ||
2883 | ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx); | ||
2884 | |||
2885 | /* Set txp.offset, note that table_min | 2990 | /* Set txp.offset, note that table_min |
2886 | * can be negative */ | 2991 | * can be negative */ |
2887 | ah->ah_txpower.txp_offset = table_min[0]; | 2992 | ah->ah_txpower.txp_offset = table_min[0]; |
@@ -2890,9 +2995,20 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2890 | return -EINVAL; | 2995 | return -EINVAL; |
2891 | } | 2996 | } |
2892 | 2997 | ||
2998 | ah->ah_txpower.txp_setup = true; | ||
2999 | |||
2893 | return 0; | 3000 | return 0; |
2894 | } | 3001 | } |
2895 | 3002 | ||
3003 | /* Write power table for current channel to hw */ | ||
3004 | static void | ||
3005 | ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type) | ||
3006 | { | ||
3007 | if (type == AR5K_PWRTABLE_PWR_TO_PDADC) | ||
3008 | ath5k_write_pwr_to_pdadc_table(ah, ee_mode); | ||
3009 | else | ||
3010 | ath5k_write_pcdac_table(ah); | ||
3011 | } | ||
2896 | 3012 | ||
2897 | /* | 3013 | /* |
2898 | * Per-rate tx power setting | 3014 | * Per-rate tx power setting |
@@ -2981,19 +3097,21 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, | |||
2981 | 3097 | ||
2982 | /* Min/max in 0.25dB units */ | 3098 | /* Min/max in 0.25dB units */ |
2983 | ah->ah_txpower.txp_min_pwr = 2 * rates[7]; | 3099 | ah->ah_txpower.txp_min_pwr = 2 * rates[7]; |
2984 | ah->ah_txpower.txp_max_pwr = 2 * rates[0]; | 3100 | ah->ah_txpower.txp_cur_pwr = 2 * rates[0]; |
2985 | ah->ah_txpower.txp_ofdm = rates[7]; | 3101 | ah->ah_txpower.txp_ofdm = rates[7]; |
2986 | } | 3102 | } |
2987 | 3103 | ||
2988 | 3104 | ||
2989 | /* | 3105 | /* |
2990 | * Set transmition power | 3106 | * Set transmission power |
2991 | */ | 3107 | */ |
2992 | int | 3108 | static int |
2993 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 3109 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
2994 | u8 ee_mode, u8 txpower) | 3110 | u8 txpower) |
2995 | { | 3111 | { |
2996 | struct ath5k_rate_pcal_info rate_info; | 3112 | struct ath5k_rate_pcal_info rate_info; |
3113 | struct ieee80211_channel *curr_channel = ah->ah_current_channel; | ||
3114 | int ee_mode; | ||
2997 | u8 type; | 3115 | u8 type; |
2998 | int ret; | 3116 | int ret; |
2999 | 3117 | ||
@@ -3002,14 +3120,18 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3002 | return -EINVAL; | 3120 | return -EINVAL; |
3003 | } | 3121 | } |
3004 | 3122 | ||
3005 | /* Reset TX power values */ | 3123 | ee_mode = ath5k_eeprom_mode_from_channel(channel); |
3006 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | 3124 | if (ee_mode < 0) { |
3007 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | 3125 | ATH5K_ERR(ah->ah_sc, |
3008 | ah->ah_txpower.txp_min_pwr = 0; | 3126 | "invalid channel: %d\n", channel->center_freq); |
3009 | ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER; | 3127 | return -EINVAL; |
3128 | } | ||
3010 | 3129 | ||
3011 | /* Initialize TX power table */ | 3130 | /* Initialize TX power table */ |
3012 | switch (ah->ah_radio) { | 3131 | switch (ah->ah_radio) { |
3132 | case AR5K_RF5110: | ||
3133 | /* TODO */ | ||
3134 | return 0; | ||
3013 | case AR5K_RF5111: | 3135 | case AR5K_RF5111: |
3014 | type = AR5K_PWRTABLE_PWR_TO_PCDAC; | 3136 | type = AR5K_PWRTABLE_PWR_TO_PCDAC; |
3015 | break; | 3137 | break; |
@@ -3027,24 +3149,37 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3027 | return -EINVAL; | 3149 | return -EINVAL; |
3028 | } | 3150 | } |
3029 | 3151 | ||
3030 | /* FIXME: Only on channel/mode change */ | 3152 | /* |
3031 | ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); | 3153 | * If we don't change channel/mode skip tx powertable calculation |
3032 | if (ret) | 3154 | * and use the cached one. |
3033 | return ret; | 3155 | */ |
3156 | if (!ah->ah_txpower.txp_setup || | ||
3157 | (channel->hw_value != curr_channel->hw_value) || | ||
3158 | (channel->center_freq != curr_channel->center_freq)) { | ||
3159 | /* Reset TX power values */ | ||
3160 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | ||
3161 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | ||
3162 | |||
3163 | /* Calculate the powertable */ | ||
3164 | ret = ath5k_setup_channel_powertable(ah, channel, | ||
3165 | ee_mode, type); | ||
3166 | if (ret) | ||
3167 | return ret; | ||
3168 | } | ||
3169 | |||
3170 | /* Write table on hw */ | ||
3171 | ath5k_write_channel_powertable(ah, ee_mode, type); | ||
3034 | 3172 | ||
3035 | /* Limit max power if we have a CTL available */ | 3173 | /* Limit max power if we have a CTL available */ |
3036 | ath5k_get_max_ctl_power(ah, channel); | 3174 | ath5k_get_max_ctl_power(ah, channel); |
3037 | 3175 | ||
3038 | /* FIXME: Tx power limit for this regdomain | ||
3039 | * XXX: Mac80211/CRDA will do that anyway ? */ | ||
3040 | |||
3041 | /* FIXME: Antenna reduction stuff */ | 3176 | /* FIXME: Antenna reduction stuff */ |
3042 | 3177 | ||
3043 | /* FIXME: Limit power on turbo modes */ | 3178 | /* FIXME: Limit power on turbo modes */ |
3044 | 3179 | ||
3045 | /* FIXME: TPC scale reduction */ | 3180 | /* FIXME: TPC scale reduction */ |
3046 | 3181 | ||
3047 | /* Get surounding channels for per-rate power table | 3182 | /* Get surrounding channels for per-rate power table |
3048 | * calibration */ | 3183 | * calibration */ |
3049 | ath5k_get_rate_pcal_data(ah, channel, &rate_info); | 3184 | ath5k_get_rate_pcal_data(ah, channel, &rate_info); |
3050 | 3185 | ||
@@ -3088,31 +3223,223 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3088 | 3223 | ||
3089 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | 3224 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) |
3090 | { | 3225 | { |
3091 | /*Just a try M.F.*/ | 3226 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, |
3092 | struct ieee80211_channel *channel = ah->ah_current_channel; | 3227 | "changing txpower to %d\n", txpower); |
3093 | u8 ee_mode; | ||
3094 | 3228 | ||
3095 | switch (channel->hw_value & CHANNEL_MODES) { | 3229 | return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower); |
3096 | case CHANNEL_A: | 3230 | } |
3097 | case CHANNEL_T: | 3231 | |
3098 | case CHANNEL_XR: | 3232 | /*************\ |
3099 | ee_mode = AR5K_EEPROM_MODE_11A; | 3233 | Init function |
3100 | break; | 3234 | \*************/ |
3101 | case CHANNEL_G: | 3235 | |
3102 | case CHANNEL_TG: | 3236 | int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
3103 | ee_mode = AR5K_EEPROM_MODE_11G; | 3237 | u8 mode, bool fast) |
3104 | break; | 3238 | { |
3105 | case CHANNEL_B: | 3239 | struct ieee80211_channel *curr_channel; |
3106 | ee_mode = AR5K_EEPROM_MODE_11B; | 3240 | int ret, i; |
3107 | break; | 3241 | u32 phy_tst1; |
3108 | default: | 3242 | ret = 0; |
3109 | ATH5K_ERR(ah->ah_sc, | 3243 | |
3110 | "invalid channel: %d\n", channel->center_freq); | 3244 | /* |
3245 | * Sanity check for fast flag | ||
3246 | * Don't try fast channel change when changing modulation | ||
3247 | * mode/band. We check for chip compatibility on | ||
3248 | * ath5k_hw_reset. | ||
3249 | */ | ||
3250 | curr_channel = ah->ah_current_channel; | ||
3251 | if (fast && (channel->hw_value != curr_channel->hw_value)) | ||
3111 | return -EINVAL; | 3252 | return -EINVAL; |
3253 | |||
3254 | /* | ||
3255 | * On fast channel change we only set the synth parameters | ||
3256 | * while PHY is running, enable calibration and skip the rest. | ||
3257 | */ | ||
3258 | if (fast) { | ||
3259 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, | ||
3260 | AR5K_PHY_RFBUS_REQ_REQUEST); | ||
3261 | for (i = 0; i < 100; i++) { | ||
3262 | if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT)) | ||
3263 | break; | ||
3264 | udelay(5); | ||
3265 | } | ||
3266 | /* Failed */ | ||
3267 | if (i >= 100) | ||
3268 | return -EIO; | ||
3269 | |||
3270 | /* Set channel and wait for synth */ | ||
3271 | ret = ath5k_hw_channel(ah, channel); | ||
3272 | if (ret) | ||
3273 | return ret; | ||
3274 | |||
3275 | ath5k_hw_wait_for_synth(ah, channel); | ||
3112 | } | 3276 | } |
3113 | 3277 | ||
3114 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, | 3278 | /* |
3115 | "changing txpower to %d\n", txpower); | 3279 | * Set TX power |
3280 | * | ||
3281 | * Note: We need to do that before we set | ||
3282 | * RF buffer settings on 5211/5212+ so that we | ||
3283 | * properly set curve indices. | ||
3284 | */ | ||
3285 | ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_cur_pwr ? | ||
3286 | ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER); | ||
3287 | if (ret) | ||
3288 | return ret; | ||
3289 | |||
3290 | /* Write OFDM timings on 5212*/ | ||
3291 | if (ah->ah_version == AR5K_AR5212 && | ||
3292 | channel->hw_value & CHANNEL_OFDM) { | ||
3293 | |||
3294 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | ||
3295 | if (ret) | ||
3296 | return ret; | ||
3297 | |||
3298 | /* Spur info is available only from EEPROM versions | ||
3299 | * greater than 5.3, but the EEPROM routines will use | ||
3300 | * static values for older versions */ | ||
3301 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | ||
3302 | ath5k_hw_set_spur_mitigation_filter(ah, | ||
3303 | channel); | ||
3304 | } | ||
3305 | |||
3306 | /* If we used fast channel switching | ||
3307 | * we are done, release RF bus and | ||
3308 | * fire up NF calibration. | ||
3309 | * | ||
3310 | * Note: Only NF calibration due to | ||
3311 | * channel change, not AGC calibration | ||
3312 | * since AGC is still running ! | ||
3313 | */ | ||
3314 | if (fast) { | ||
3315 | /* | ||
3316 | * Release RF Bus grant | ||
3317 | */ | ||
3318 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, | ||
3319 | AR5K_PHY_RFBUS_REQ_REQUEST); | ||
3320 | |||
3321 | /* | ||
3322 | * Start NF calibration | ||
3323 | */ | ||
3324 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
3325 | AR5K_PHY_AGCCTL_NF); | ||
3116 | 3326 | ||
3117 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); | 3327 | return ret; |
3328 | } | ||
3329 | |||
3330 | /* | ||
3331 | * For 5210 we do all initialization using | ||
3332 | * initvals, so we don't have to modify | ||
3333 | * any settings (5210 also only supports | ||
3334 | * a/aturbo modes) | ||
3335 | */ | ||
3336 | if (ah->ah_version != AR5K_AR5210) { | ||
3337 | |||
3338 | /* | ||
3339 | * Write initial RF gain settings | ||
3340 | * This should work for both 5111/5112 | ||
3341 | */ | ||
3342 | ret = ath5k_hw_rfgain_init(ah, channel->band); | ||
3343 | if (ret) | ||
3344 | return ret; | ||
3345 | |||
3346 | mdelay(1); | ||
3347 | |||
3348 | /* | ||
3349 | * Write RF buffer | ||
3350 | */ | ||
3351 | ret = ath5k_hw_rfregs_init(ah, channel, mode); | ||
3352 | if (ret) | ||
3353 | return ret; | ||
3354 | |||
3355 | /*Enable/disable 802.11b mode on 5111 | ||
3356 | (enable 2111 frequency converter + CCK)*/ | ||
3357 | if (ah->ah_radio == AR5K_RF5111) { | ||
3358 | if (mode == AR5K_MODE_11B) | ||
3359 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | ||
3360 | AR5K_TXCFG_B_MODE); | ||
3361 | else | ||
3362 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | ||
3363 | AR5K_TXCFG_B_MODE); | ||
3364 | } | ||
3365 | |||
3366 | } else if (ah->ah_version == AR5K_AR5210) { | ||
3367 | mdelay(1); | ||
3368 | /* Disable phy and wait */ | ||
3369 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
3370 | mdelay(1); | ||
3371 | } | ||
3372 | |||
3373 | /* Set channel on PHY */ | ||
3374 | ret = ath5k_hw_channel(ah, channel); | ||
3375 | if (ret) | ||
3376 | return ret; | ||
3377 | |||
3378 | /* | ||
3379 | * Enable the PHY and wait until completion | ||
3380 | * This includes BaseBand and Synthesizer | ||
3381 | * activation. | ||
3382 | */ | ||
3383 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
3384 | |||
3385 | ath5k_hw_wait_for_synth(ah, channel); | ||
3386 | |||
3387 | /* | ||
3388 | * Perform ADC test to see if baseband is ready | ||
3389 | * Set tx hold and check adc test register | ||
3390 | */ | ||
3391 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | ||
3392 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | ||
3393 | for (i = 0; i <= 20; i++) { | ||
3394 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | ||
3395 | break; | ||
3396 | udelay(200); | ||
3397 | } | ||
3398 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); | ||
3399 | |||
3400 | /* | ||
3401 | * Start automatic gain control calibration | ||
3402 | * | ||
3403 | * During AGC calibration RX path is re-routed to | ||
3404 | * a power detector so we don't receive anything. | ||
3405 | * | ||
3406 | * This method is used to calibrate some static offsets | ||
3407 | * used together with on-the fly I/Q calibration (the | ||
3408 | * one performed via ath5k_hw_phy_calibrate), which doesn't | ||
3409 | * interrupt rx path. | ||
3410 | * | ||
3411 | * While rx path is re-routed to the power detector we also | ||
3412 | * start a noise floor calibration to measure the | ||
3413 | * card's noise floor (the noise we measure when we are not | ||
3414 | * transmitting or receiving anything). | ||
3415 | * | ||
3416 | * If we are in a noisy environment, AGC calibration may time | ||
3417 | * out and/or noise floor calibration might timeout. | ||
3418 | */ | ||
3419 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
3420 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); | ||
3421 | |||
3422 | /* At the same time start I/Q calibration for QAM constellation | ||
3423 | * -no need for CCK- */ | ||
3424 | ah->ah_calibration = false; | ||
3425 | if (!(mode == AR5K_MODE_11B)) { | ||
3426 | ah->ah_calibration = true; | ||
3427 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
3428 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
3429 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
3430 | AR5K_PHY_IQ_RUN); | ||
3431 | } | ||
3432 | |||
3433 | /* Wait for gain calibration to finish (we check for I/Q calibration | ||
3434 | * during ath5k_phy_calibrate) */ | ||
3435 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
3436 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | ||
3437 | ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", | ||
3438 | channel->center_freq); | ||
3439 | } | ||
3440 | |||
3441 | /* Restore antenna mode */ | ||
3442 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | ||
3443 | |||
3444 | return ret; | ||
3118 | } | 3445 | } |