00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define _ATH5K_PHY
00024
00025 #include <linux/delay.h>
00026
00027 #include "ath5k.h"
00028 #include "reg.h"
00029 #include "base.h"
00030 #include "rfbuffer.h"
00031 #include "rfgain.h"
00032
00033
00034
00035
00036 static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
00037 const struct ath5k_rf_reg *rf_regs,
00038 u32 val, u8 reg_id, bool set)
00039 {
00040 const struct ath5k_rf_reg *rfreg = NULL;
00041 u8 offset, bank, num_bits, col, position;
00042 u16 entry;
00043 u32 mask, data, last_bit, bits_shifted, first_bit;
00044 u32 *rfb;
00045 s32 bits_left;
00046 int i;
00047
00048 data = 0;
00049 rfb = ah->ah_rf_banks;
00050
00051 for (i = 0; i < ah->ah_rf_regs_count; i++) {
00052 if (rf_regs[i].index == reg_id) {
00053 rfreg = &rf_regs[i];
00054 break;
00055 }
00056 }
00057
00058 if (rfb == NULL || rfreg == NULL) {
00059 ATH5K_PRINTF("Rf register not found!\n");
00060
00061 return 0;
00062 }
00063
00064 bank = rfreg->bank;
00065 num_bits = rfreg->field.len;
00066 first_bit = rfreg->field.pos;
00067 col = rfreg->field.col;
00068
00069
00070
00071
00072
00073 offset = ah->ah_offset[bank];
00074
00075
00076 if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) {
00077 ATH5K_PRINTF("invalid values at offset %u\n", offset);
00078 return 0;
00079 }
00080
00081 entry = ((first_bit - 1) / 8) + offset;
00082 position = (first_bit - 1) % 8;
00083
00084 if (set)
00085 data = ath5k_hw_bitswap(val, num_bits);
00086
00087 for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
00088 position = 0, entry++) {
00089
00090 last_bit = (position + bits_left > 8) ? 8 :
00091 position + bits_left;
00092
00093 mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) <<
00094 (col * 8);
00095
00096 if (set) {
00097 rfb[entry] &= ~mask;
00098 rfb[entry] |= ((data << position) << (col * 8)) & mask;
00099 data >>= (8 - position);
00100 } else {
00101 data |= (((rfb[entry] & mask) >> (col * 8)) >> position)
00102 << bits_shifted;
00103 bits_shifted += last_bit - position;
00104 }
00105
00106 bits_left -= 8 - position;
00107 }
00108
00109 data = set ? 1 : ath5k_hw_bitswap(data, num_bits);
00110
00111 return data;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
00144 {
00145
00146 switch (ah->ah_radio) {
00147 case AR5K_RF5111:
00148 ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
00149 ah->ah_gain.g_low = 20;
00150 ah->ah_gain.g_high = 35;
00151 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
00152 break;
00153 case AR5K_RF5112:
00154 ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
00155 ah->ah_gain.g_low = 20;
00156 ah->ah_gain.g_high = 85;
00157 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
00158 break;
00159 default:
00160 return -EINVAL;
00161 }
00162
00163 return 0;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah)
00177 {
00178
00179
00180
00181 if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE)
00182 return;
00183
00184
00185
00186 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_ofdm - 4,
00187 AR5K_PHY_PAPD_PROBE_TXPOWER) |
00188 AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
00189
00190 ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED;
00191
00192 }
00193
00194
00195
00196 static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah)
00197 {
00198 u32 mix, step;
00199 u32 *rf;
00200 const struct ath5k_gain_opt *go;
00201 const struct ath5k_gain_opt_step *g_step;
00202 const struct ath5k_rf_reg *rf_regs;
00203
00204
00205 if ((ah->ah_radio != AR5K_RF5112) ||
00206 (ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A))
00207 return 0;
00208
00209 go = &rfgain_opt_5112;
00210 rf_regs = rf_regs_5112a;
00211 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
00212
00213 g_step = &go->go_step[ah->ah_gain.g_step_idx];
00214
00215 if (ah->ah_rf_banks == NULL)
00216 return 0;
00217
00218 rf = ah->ah_rf_banks;
00219 ah->ah_gain.g_f_corr = 0;
00220
00221
00222 if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, false) != 1)
00223 return 0;
00224
00225
00226 step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, false);
00227
00228
00229 mix = g_step->gos_param[0];
00230
00231 switch (mix) {
00232 case 3:
00233 ah->ah_gain.g_f_corr = step * 2;
00234 break;
00235 case 2:
00236 ah->ah_gain.g_f_corr = (step - 5) * 2;
00237 break;
00238 case 1:
00239 ah->ah_gain.g_f_corr = step;
00240 break;
00241 default:
00242 ah->ah_gain.g_f_corr = 0;
00243 break;
00244 }
00245
00246 return ah->ah_gain.g_f_corr;
00247 }
00248
00249
00250
00251
00252
00253 static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
00254 {
00255 const struct ath5k_rf_reg *rf_regs;
00256 u32 step, mix_ovr, level[4];
00257 u32 *rf;
00258
00259 if (ah->ah_rf_banks == NULL)
00260 return false;
00261
00262 rf = ah->ah_rf_banks;
00263
00264 if (ah->ah_radio == AR5K_RF5111) {
00265
00266 rf_regs = rf_regs_5111;
00267 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
00268
00269 step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP,
00270 false);
00271
00272 level[0] = 0;
00273 level[1] = (step == 63) ? 50 : step + 4;
00274 level[2] = (step != 63) ? 64 : level[0];
00275 level[3] = level[2] + 50 ;
00276
00277 ah->ah_gain.g_high = level[3] -
00278 (step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
00279 ah->ah_gain.g_low = level[0] +
00280 (step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
00281 } else {
00282
00283 rf_regs = rf_regs_5112;
00284 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
00285
00286 mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR,
00287 false);
00288
00289 level[0] = level[2] = 0;
00290
00291 if (mix_ovr == 1) {
00292 level[1] = level[3] = 83;
00293 } else {
00294 level[1] = level[3] = 107;
00295 ah->ah_gain.g_high = 55;
00296 }
00297 }
00298
00299 return (ah->ah_gain.g_current >= level[0] &&
00300 ah->ah_gain.g_current <= level[1]) ||
00301 (ah->ah_gain.g_current >= level[2] &&
00302 ah->ah_gain.g_current <= level[3]);
00303 }
00304
00305
00306
00307 static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
00308 {
00309 const struct ath5k_gain_opt *go;
00310 const struct ath5k_gain_opt_step *g_step;
00311 int ret = 0;
00312
00313 switch (ah->ah_radio) {
00314 case AR5K_RF5111:
00315 go = &rfgain_opt_5111;
00316 break;
00317 case AR5K_RF5112:
00318 go = &rfgain_opt_5112;
00319 break;
00320 default:
00321 return 0;
00322 }
00323
00324 g_step = &go->go_step[ah->ah_gain.g_step_idx];
00325
00326 if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
00327
00328
00329 if (ah->ah_gain.g_step_idx == 0)
00330 return -1;
00331
00332 for (ah->ah_gain.g_target = ah->ah_gain.g_current;
00333 ah->ah_gain.g_target >= ah->ah_gain.g_high &&
00334 ah->ah_gain.g_step_idx > 0;
00335 g_step = &go->go_step[ah->ah_gain.g_step_idx])
00336 ah->ah_gain.g_target -= 2 *
00337 (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
00338 g_step->gos_gain);
00339
00340 ret = 1;
00341 goto done;
00342 }
00343
00344 if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
00345
00346
00347 if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
00348 return -2;
00349
00350 for (ah->ah_gain.g_target = ah->ah_gain.g_current;
00351 ah->ah_gain.g_target <= ah->ah_gain.g_low &&
00352 ah->ah_gain.g_step_idx < go->go_steps_count-1;
00353 g_step = &go->go_step[ah->ah_gain.g_step_idx])
00354 ah->ah_gain.g_target -= 2 *
00355 (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
00356 g_step->gos_gain);
00357
00358 ret = 2;
00359 goto done;
00360 }
00361
00362 done:
00363 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
00364 "ret %d, gain step %u, current gain %u, target gain %u\n",
00365 ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
00366 ah->ah_gain.g_target);
00367
00368 return ret;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377 enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
00378 {
00379 u32 data, type;
00380 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
00381
00382 ATH5K_TRACE(ah->ah_sc);
00383
00384 if (ah->ah_rf_banks == NULL ||
00385 ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
00386 return AR5K_RFGAIN_INACTIVE;
00387
00388
00389
00390 if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED)
00391 goto done;
00392
00393
00394
00395 data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE);
00396
00397
00398 if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) {
00399 ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
00400 type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE);
00401
00402
00403
00404 if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) {
00405 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
00406 ah->ah_gain.g_current +=
00407 ee->ee_cck_ofdm_gain_delta;
00408 else
00409 ah->ah_gain.g_current +=
00410 AR5K_GAIN_CCK_PROBE_CORR;
00411 }
00412
00413
00414
00415 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
00416 ath5k_hw_rf_gainf_corr(ah);
00417 ah->ah_gain.g_current =
00418 ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
00419 (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
00420 0;
00421 }
00422
00423
00424
00425
00426 if (ath5k_hw_rf_check_gainf_readback(ah) &&
00427 AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
00428 ath5k_hw_rf_gainf_adjust(ah)) {
00429 ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE;
00430 } else {
00431 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
00432 }
00433 }
00434
00435 done:
00436 return ah->ah_gain.g_state;
00437 }
00438
00439
00440
00441
00442 int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
00443 {
00444 const struct ath5k_ini_rfgain *ath5k_rfg;
00445 unsigned int i, size;
00446
00447 switch (ah->ah_radio) {
00448 case AR5K_RF5111:
00449 ath5k_rfg = rfgain_5111;
00450 size = ARRAY_SIZE(rfgain_5111);
00451 break;
00452 case AR5K_RF5112:
00453 ath5k_rfg = rfgain_5112;
00454 size = ARRAY_SIZE(rfgain_5112);
00455 break;
00456 case AR5K_RF2413:
00457 ath5k_rfg = rfgain_2413;
00458 size = ARRAY_SIZE(rfgain_2413);
00459 break;
00460 case AR5K_RF2316:
00461 ath5k_rfg = rfgain_2316;
00462 size = ARRAY_SIZE(rfgain_2316);
00463 break;
00464 case AR5K_RF5413:
00465 ath5k_rfg = rfgain_5413;
00466 size = ARRAY_SIZE(rfgain_5413);
00467 break;
00468 case AR5K_RF2317:
00469 case AR5K_RF2425:
00470 ath5k_rfg = rfgain_2425;
00471 size = ARRAY_SIZE(rfgain_2425);
00472 break;
00473 default:
00474 return -EINVAL;
00475 }
00476
00477 switch (freq) {
00478 case AR5K_INI_RFGAIN_2GHZ:
00479 case AR5K_INI_RFGAIN_5GHZ:
00480 break;
00481 default:
00482 return -EINVAL;
00483 }
00484
00485 for (i = 0; i < size; i++) {
00486 AR5K_REG_WAIT(i);
00487 ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
00488 (u32)ath5k_rfg[i].rfg_register);
00489 }
00490
00491 return 0;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
00505 unsigned int mode)
00506 {
00507 const struct ath5k_rf_reg *rf_regs;
00508 const struct ath5k_ini_rfbuffer *ini_rfb;
00509 const struct ath5k_gain_opt *go = NULL;
00510 const struct ath5k_gain_opt_step *g_step;
00511 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
00512 u8 ee_mode = 0;
00513 u32 *rfb;
00514 int i, obdb = -1, bank = -1;
00515
00516 switch (ah->ah_radio) {
00517 case AR5K_RF5111:
00518 rf_regs = rf_regs_5111;
00519 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
00520 ini_rfb = rfb_5111;
00521 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111);
00522 go = &rfgain_opt_5111;
00523 break;
00524 case AR5K_RF5112:
00525 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
00526 rf_regs = rf_regs_5112a;
00527 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
00528 ini_rfb = rfb_5112a;
00529 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a);
00530 } else {
00531 rf_regs = rf_regs_5112;
00532 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
00533 ini_rfb = rfb_5112;
00534 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112);
00535 }
00536 go = &rfgain_opt_5112;
00537 break;
00538 case AR5K_RF2413:
00539 rf_regs = rf_regs_2413;
00540 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413);
00541 ini_rfb = rfb_2413;
00542 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413);
00543 break;
00544 case AR5K_RF2316:
00545 rf_regs = rf_regs_2316;
00546 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316);
00547 ini_rfb = rfb_2316;
00548 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316);
00549 break;
00550 case AR5K_RF5413:
00551 rf_regs = rf_regs_5413;
00552 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413);
00553 ini_rfb = rfb_5413;
00554 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413);
00555 break;
00556 case AR5K_RF2317:
00557 rf_regs = rf_regs_2425;
00558 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
00559 ini_rfb = rfb_2317;
00560 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317);
00561 break;
00562 case AR5K_RF2425:
00563 rf_regs = rf_regs_2425;
00564 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
00565 if (ah->ah_mac_srev < AR5K_SREV_AR2417) {
00566 ini_rfb = rfb_2425;
00567 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425);
00568 } else {
00569 ini_rfb = rfb_2417;
00570 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417);
00571 }
00572 break;
00573 default:
00574 return -EINVAL;
00575 }
00576
00577
00578
00579
00580 if (ah->ah_rf_banks == NULL) {
00581 ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size,
00582 GFP_KERNEL);
00583 if (ah->ah_rf_banks == NULL) {
00584 ATH5K_ERR(ah->ah_sc, "out of memory\n");
00585 return -ENOMEM;
00586 }
00587 }
00588
00589
00590 rfb = ah->ah_rf_banks;
00591
00592 for (i = 0; i < ah->ah_rf_banks_size; i++) {
00593 if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
00594 ATH5K_ERR(ah->ah_sc, "invalid bank\n");
00595 return -EINVAL;
00596 }
00597
00598
00599 if (bank != ini_rfb[i].rfb_bank) {
00600 bank = ini_rfb[i].rfb_bank;
00601 ah->ah_offset[bank] = i;
00602 }
00603
00604 rfb[i] = ini_rfb[i].rfb_mode_data[mode];
00605 }
00606
00607
00608 if (channel->hw_value & CHANNEL_2GHZ) {
00609
00610 if (channel->hw_value & CHANNEL_CCK)
00611 ee_mode = AR5K_EEPROM_MODE_11B;
00612 else
00613 ee_mode = AR5K_EEPROM_MODE_11G;
00614
00615
00616
00617
00618
00619
00620
00621
00622 if ((ah->ah_radio == AR5K_RF5111) ||
00623 (ah->ah_radio == AR5K_RF5112))
00624 obdb = 0;
00625 else
00626 obdb = 1;
00627
00628 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
00629 AR5K_RF_OB_2GHZ, true);
00630
00631 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
00632 AR5K_RF_DB_2GHZ, true);
00633
00634
00635 } else if ((channel->hw_value & CHANNEL_5GHZ) ||
00636 (ah->ah_radio == AR5K_RF5111)) {
00637
00638
00639
00640 ee_mode = AR5K_EEPROM_MODE_11A;
00641 obdb = channel->center_freq >= 5725 ? 3 :
00642 (channel->center_freq >= 5500 ? 2 :
00643 (channel->center_freq >= 5260 ? 1 :
00644 (channel->center_freq > 4000 ? 0 : -1)));
00645
00646 if (obdb < 0)
00647 return -EINVAL;
00648
00649 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
00650 AR5K_RF_OB_5GHZ, true);
00651
00652 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
00653 AR5K_RF_DB_5GHZ, true);
00654 }
00655
00656 g_step = &go->go_step[ah->ah_gain.g_step_idx];
00657
00658
00659 if (ah->ah_radio == AR5K_RF5111) {
00660
00661
00662 if (channel->hw_value & CHANNEL_OFDM) {
00663
00664 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
00665 AR5K_PHY_FRAME_CTL_TX_CLIP,
00666 g_step->gos_param[0]);
00667
00668 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
00669 AR5K_RF_PWD_90, true);
00670
00671 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
00672 AR5K_RF_PWD_84, true);
00673
00674 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
00675 AR5K_RF_RFGAIN_SEL, true);
00676
00677
00678
00679 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
00680
00681 }
00682
00683
00684
00685 ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode],
00686 AR5K_RF_PWD_XPD, true);
00687
00688 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode],
00689 AR5K_RF_XPD_GAIN, true);
00690
00691 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
00692 AR5K_RF_GAIN_I, true);
00693
00694 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
00695 AR5K_RF_PLO_SEL, true);
00696
00697
00698 }
00699
00700 if (ah->ah_radio == AR5K_RF5112) {
00701
00702
00703 if (channel->hw_value & CHANNEL_OFDM) {
00704
00705 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
00706 AR5K_RF_MIXGAIN_OVR, true);
00707
00708 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
00709 AR5K_RF_PWD_138, true);
00710
00711 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
00712 AR5K_RF_PWD_137, true);
00713
00714 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
00715 AR5K_RF_PWD_136, true);
00716
00717 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4],
00718 AR5K_RF_PWD_132, true);
00719
00720 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5],
00721 AR5K_RF_PWD_131, true);
00722
00723 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6],
00724 AR5K_RF_PWD_130, true);
00725
00726
00727
00728 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
00729 }
00730
00731
00732
00733 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
00734 AR5K_RF_XPD_SEL, true);
00735
00736 if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
00737
00738 ath5k_hw_rfb_op(ah, rf_regs,
00739 ee->ee_x_gain[ee_mode],
00740 AR5K_RF_XPD_GAIN, true);
00741
00742 } else {
00743 u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
00744 if (ee->ee_pd_gains[ee_mode] > 1) {
00745 ath5k_hw_rfb_op(ah, rf_regs,
00746 pdg_curve_to_idx[0],
00747 AR5K_RF_PD_GAIN_LO, true);
00748 ath5k_hw_rfb_op(ah, rf_regs,
00749 pdg_curve_to_idx[1],
00750 AR5K_RF_PD_GAIN_HI, true);
00751 } else {
00752 ath5k_hw_rfb_op(ah, rf_regs,
00753 pdg_curve_to_idx[0],
00754 AR5K_RF_PD_GAIN_LO, true);
00755 ath5k_hw_rfb_op(ah, rf_regs,
00756 pdg_curve_to_idx[0],
00757 AR5K_RF_PD_GAIN_HI, true);
00758 }
00759
00760
00761 ath5k_hw_rfb_op(ah, rf_regs, 2,
00762 AR5K_RF_HIGH_VC_CP, true);
00763
00764 ath5k_hw_rfb_op(ah, rf_regs, 2,
00765 AR5K_RF_MID_VC_CP, true);
00766
00767 ath5k_hw_rfb_op(ah, rf_regs, 2,
00768 AR5K_RF_LOW_VC_CP, true);
00769
00770 ath5k_hw_rfb_op(ah, rf_regs, 2,
00771 AR5K_RF_PUSH_UP, true);
00772
00773
00774 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
00775 ath5k_hw_rfb_op(ah, rf_regs, 1,
00776 AR5K_RF_PAD2GND, true);
00777
00778 ath5k_hw_rfb_op(ah, rf_regs, 1,
00779 AR5K_RF_XB2_LVL, true);
00780
00781 ath5k_hw_rfb_op(ah, rf_regs, 1,
00782 AR5K_RF_XB5_LVL, true);
00783
00784 ath5k_hw_rfb_op(ah, rf_regs, 1,
00785 AR5K_RF_PWD_167, true);
00786
00787 ath5k_hw_rfb_op(ah, rf_regs, 1,
00788 AR5K_RF_PWD_166, true);
00789 }
00790 }
00791
00792 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
00793 AR5K_RF_GAIN_I, true);
00794
00795
00796
00797 }
00798
00799 if (ah->ah_radio == AR5K_RF5413 &&
00800 channel->hw_value & CHANNEL_2GHZ) {
00801
00802 ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE,
00803 true);
00804
00805
00806 if (ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
00807 ah->ah_mac_srev < AR5K_SREV_AR5413)
00808 ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3),
00809 AR5K_RF_PWD_ICLOBUF_2G, true);
00810
00811 }
00812
00813
00814 for (i = 0; i < ah->ah_rf_banks_size; i++) {
00815 AR5K_REG_WAIT(i);
00816 ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register);
00817 }
00818
00819 return 0;
00820 }
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
00831 {
00832
00833 if (flags & CHANNEL_2GHZ) {
00834 if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
00835 (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
00836 return true;
00837 } else if (flags & CHANNEL_5GHZ)
00838 if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
00839 (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
00840 return true;
00841
00842 return false;
00843 }
00844
00845
00846
00847
00848 static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
00849 {
00850 u32 athchan;
00851
00852
00853
00854
00855
00856
00857
00858 athchan = (ath5k_hw_bitswap(
00859 (ath5k_frequency_to_channel(
00860 channel->center_freq) - 24) / 2, 5)
00861 << 1) | (1 << 6) | 0x1;
00862 return athchan;
00863 }
00864
00865
00866
00867
00868 static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
00869 struct ieee80211_channel *channel)
00870 {
00871 u32 data;
00872
00873
00874
00875
00876 data = ath5k_hw_rf5110_chan2athchan(channel);
00877 ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
00878 ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
00879 mdelay(1);
00880
00881 return 0;
00882 }
00883
00884
00885
00886
00887 static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
00888 struct ath5k_athchan_2ghz *athchan)
00889 {
00890 int channel;
00891
00892
00893 channel = (int)ieee;
00894
00895
00896
00897
00898 if (channel <= 13) {
00899 athchan->a2_athchan = 115 + channel;
00900 athchan->a2_flags = 0x46;
00901 } else if (channel == 14) {
00902 athchan->a2_athchan = 124;
00903 athchan->a2_flags = 0x44;
00904 } else if (channel >= 15 && channel <= 26) {
00905 athchan->a2_athchan = ((channel - 14) * 4) + 132;
00906 athchan->a2_flags = 0x46;
00907 } else
00908 return -EINVAL;
00909
00910 return 0;
00911 }
00912
00913
00914
00915
00916 static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
00917 struct ieee80211_channel *channel)
00918 {
00919 struct ath5k_athchan_2ghz ath5k_channel_2ghz;
00920 unsigned int ath5k_channel =
00921 ath5k_frequency_to_channel(channel->center_freq);
00922 u32 data0, data1, clock;
00923 int ret;
00924
00925
00926
00927
00928 data0 = data1 = 0;
00929
00930 if (channel->hw_value & CHANNEL_2GHZ) {
00931
00932 ret = ath5k_hw_rf5111_chan2athchan(
00933 ath5k_frequency_to_channel(channel->center_freq),
00934 &ath5k_channel_2ghz);
00935 if (ret)
00936 return ret;
00937
00938 ath5k_channel = ath5k_channel_2ghz.a2_athchan;
00939 data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
00940 << 5) | (1 << 4);
00941 }
00942
00943 if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
00944 clock = 1;
00945 data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
00946 (clock << 1) | (1 << 10) | 1;
00947 } else {
00948 clock = 0;
00949 data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
00950 << 2) | (clock << 1) | (1 << 10) | 1;
00951 }
00952
00953 ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
00954 AR5K_RF_BUFFER);
00955 ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
00956 AR5K_RF_BUFFER_CONTROL_3);
00957
00958 return 0;
00959 }
00960
00961
00962
00963
00964 static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
00965 struct ieee80211_channel *channel)
00966 {
00967 u32 data, data0, data1, data2;
00968 u16 c;
00969
00970 data = data0 = data1 = data2 = 0;
00971 c = channel->center_freq;
00972
00973 if (c < 4800) {
00974 if (!((c - 2224) % 5)) {
00975 data0 = ((2 * (c - 704)) - 3040) / 10;
00976 data1 = 1;
00977 } else if (!((c - 2192) % 5)) {
00978 data0 = ((2 * (c - 672)) - 3040) / 10;
00979 data1 = 0;
00980 } else
00981 return -EINVAL;
00982
00983 data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
00984 } else if ((c - (c % 5)) != 2 || c > 5435) {
00985 if (!(c % 20) && c >= 5120) {
00986 data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
00987 data2 = ath5k_hw_bitswap(3, 2);
00988 } else if (!(c % 10)) {
00989 data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
00990 data2 = ath5k_hw_bitswap(2, 2);
00991 } else if (!(c % 5)) {
00992 data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
00993 data2 = ath5k_hw_bitswap(1, 2);
00994 } else
00995 return -EINVAL;
00996 } else {
00997 data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
00998 data2 = ath5k_hw_bitswap(0, 2);
00999 }
01000
01001 data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
01002
01003 ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
01004 ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
01005
01006 return 0;
01007 }
01008
01009
01010
01011
01012 static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
01013 struct ieee80211_channel *channel)
01014 {
01015 u32 data, data0, data2;
01016 u16 c;
01017
01018 data = data0 = data2 = 0;
01019 c = channel->center_freq;
01020
01021 if (c < 4800) {
01022 data0 = ath5k_hw_bitswap((c - 2272), 8);
01023 data2 = 0;
01024
01025 } else if ((c - (c % 5)) != 2 || c > 5435) {
01026 if (!(c % 20) && c < 5120)
01027 data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
01028 else if (!(c % 10))
01029 data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
01030 else if (!(c % 5))
01031 data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
01032 else
01033 return -EINVAL;
01034 data2 = ath5k_hw_bitswap(1, 2);
01035 } else {
01036 data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
01037 data2 = ath5k_hw_bitswap(0, 2);
01038 }
01039
01040 data = (data0 << 4) | data2 << 2 | 0x1001;
01041
01042 ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
01043 ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
01044
01045 return 0;
01046 }
01047
01048
01049
01050
01051 int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
01052 {
01053 int ret;
01054
01055
01056
01057
01058
01059 if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
01060 ATH5K_ERR(ah->ah_sc,
01061 "channel frequency (%u MHz) out of supported "
01062 "band range\n",
01063 channel->center_freq);
01064 return -EINVAL;
01065 }
01066
01067
01068
01069
01070 switch (ah->ah_radio) {
01071 case AR5K_RF5110:
01072 ret = ath5k_hw_rf5110_channel(ah, channel);
01073 break;
01074 case AR5K_RF5111:
01075 ret = ath5k_hw_rf5111_channel(ah, channel);
01076 break;
01077 case AR5K_RF2425:
01078 ret = ath5k_hw_rf2425_channel(ah, channel);
01079 break;
01080 default:
01081 ret = ath5k_hw_rf5112_channel(ah, channel);
01082 break;
01083 }
01084
01085 if (ret)
01086 return ret;
01087
01088
01089 if (channel->center_freq == 2484) {
01090 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
01091 AR5K_PHY_CCKTXCTL_JAPAN);
01092 } else {
01093 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
01094 AR5K_PHY_CCKTXCTL_WORLD);
01095 }
01096
01097 ah->ah_current_channel = channel;
01098 ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
01099
01100 return 0;
01101 }
01102
01103
01104
01105
01106
01107 void
01108 ath5k_hw_calibration_poll(struct ath5k_hw *ah)
01109 {
01110
01111 unsigned long cal_intval;
01112
01113 cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000);
01114
01115
01116 if (!ah->ah_cal_tstamp)
01117 ah->ah_cal_tstamp = jiffies;
01118
01119
01120
01121
01122 if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) {
01123 ah->ah_cal_tstamp = jiffies;
01124 ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION;
01125 AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI);
01126 }
01127
01128 }
01129
01152 int
01153 ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
01154 {
01155 int ret;
01156 unsigned int i;
01157 s32 noise_floor;
01158
01159
01160
01161
01162 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
01163 AR5K_PHY_AGCCTL_NF);
01164
01165 ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
01166 AR5K_PHY_AGCCTL_NF, 0, false);
01167 if (ret) {
01168 ATH5K_ERR(ah->ah_sc,
01169 "noise floor calibration timeout (%uMHz)\n", freq);
01170 return -EAGAIN;
01171 }
01172
01173
01174 for (i = 20; i > 0; i--) {
01175 mdelay(1);
01176 noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
01177 noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
01178 if (noise_floor & AR5K_PHY_NF_ACTIVE) {
01179 noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
01180
01181 if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
01182 break;
01183 }
01184 }
01185
01186 ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
01187 "noise floor %d\n", noise_floor);
01188
01189 if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
01190 ATH5K_ERR(ah->ah_sc,
01191 "noise floor calibration failed (%uMHz)\n", freq);
01192 return -EAGAIN;
01193 }
01194
01195 ah->ah_noise_floor = noise_floor;
01196
01197 return 0;
01198 }
01199
01200
01201
01202
01203
01204
01205 static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
01206 struct ieee80211_channel *channel)
01207 {
01208 u32 phy_sig, phy_agc, phy_sat, beacon;
01209 int ret;
01210
01211
01212
01213
01214 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
01215 AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
01216 beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
01217 ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
01218
01219 mdelay(2);
01220
01221
01222
01223
01224 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
01225 udelay(10);
01226 ret = ath5k_hw_channel(ah, channel);
01227
01228
01229
01230
01231 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
01232 mdelay(1);
01233
01234 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
01235
01236 if (ret)
01237 return ret;
01238
01239
01240
01241
01242
01243
01244 phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
01245 phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE);
01246 phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT);
01247
01248
01249 ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
01250 AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG);
01251
01252 ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI |
01253 AR5K_PHY_AGCCOARSE_LO)) |
01254 AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) |
01255 AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE);
01256
01257 ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT |
01258 AR5K_PHY_ADCSAT_THR)) |
01259 AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) |
01260 AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT);
01261
01262 udelay(20);
01263
01264 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
01265 udelay(10);
01266 ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
01267 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
01268
01269 mdelay(1);
01270
01271
01272
01273
01274 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL);
01275
01276 ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
01277 AR5K_PHY_AGCCTL_CAL, 0, false);
01278
01279
01280 ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG);
01281 ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE);
01282 ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
01283
01284 if (ret) {
01285 ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
01286 channel->center_freq);
01287 return ret;
01288 }
01289
01290 ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
01291
01292
01293
01294
01295 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
01296 AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
01297 ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
01298
01299 return 0;
01300 }
01301
01302
01303
01304
01305 static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
01306 struct ieee80211_channel *channel)
01307 {
01308 u32 i_pwr, q_pwr;
01309 s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
01310 int i;
01311 ATH5K_TRACE(ah->ah_sc);
01312
01313 if (!ah->ah_calibration ||
01314 ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
01315 goto done;
01316
01317
01318 for (i = 0; i <= 10; i++) {
01319 iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
01320 i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
01321 q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
01322 }
01323
01324 i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
01325 q_coffd = q_pwr >> 7;
01326
01327
01328 if (i_coffd == 0 || q_coffd == 0)
01329 goto done;
01330
01331 i_coff = ((-iq_corr) / i_coffd) & 0x3f;
01332
01333
01334 if (i_coff > 31)
01335 i_coff = 31;
01336 if (i_coff < -32)
01337 i_coff = -32;
01338
01339 q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f;
01340
01341
01342 if (q_coff > 15)
01343 q_coff = 15;
01344 if (q_coff < -16)
01345 q_coff = -16;
01346
01347
01348 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
01349 ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
01350
01351
01352
01353 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
01354 AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
01355 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
01356
01357 done:
01358
01359
01360
01361
01362
01363 ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
01364
01365
01366 ath5k_hw_request_rfgain_probe(ah);
01367
01368 return 0;
01369 }
01370
01371
01372
01373
01374 int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
01375 struct ieee80211_channel *channel)
01376 {
01377 int ret;
01378
01379 if (ah->ah_radio == AR5K_RF5110)
01380 ret = ath5k_hw_rf5110_calibrate(ah, channel);
01381 else
01382 ret = ath5k_hw_rf511x_calibrate(ah, channel);
01383
01384 return ret;
01385 }
01386
01387
01388
01389
01390
01391 bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
01392 struct ieee80211_channel *channel)
01393 {
01394 u8 refclk_freq;
01395
01396 if ((ah->ah_radio == AR5K_RF5112) ||
01397 (ah->ah_radio == AR5K_RF5413) ||
01398 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
01399 refclk_freq = 40;
01400 else
01401 refclk_freq = 32;
01402
01403 if ((channel->center_freq % refclk_freq != 0) &&
01404 ((channel->center_freq % refclk_freq < 10) ||
01405 (channel->center_freq % refclk_freq > 22)))
01406 return true;
01407 else
01408 return false;
01409 }
01410
01411 void
01412 ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
01413 struct ieee80211_channel *channel)
01414 {
01415 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
01416 u32 mag_mask[4] = {0, 0, 0, 0};
01417 u32 pilot_mask[2] = {0, 0};
01418
01419 u16 spur_chan_fbin, chan_fbin, symbol_width, spur_detection_window;
01420 s32 spur_delta_phase, spur_freq_sigma_delta;
01421 s32 spur_offset, num_symbols_x16;
01422 u8 num_symbol_offsets, i, freq_band;
01423
01424
01425
01426
01427 if (channel->hw_value & CHANNEL_2GHZ) {
01428 chan_fbin = (channel->center_freq - 2300) * 10;
01429 freq_band = AR5K_EEPROM_BAND_2GHZ;
01430 } else {
01431 chan_fbin = (channel->center_freq - 4900) * 10;
01432 freq_band = AR5K_EEPROM_BAND_5GHZ;
01433 }
01434
01435
01436
01437 spur_chan_fbin = AR5K_EEPROM_NO_SPUR;
01438 spur_detection_window = AR5K_SPUR_CHAN_WIDTH;
01439
01440 if (channel->hw_value & CHANNEL_TURBO)
01441 spur_detection_window *= 2;
01442
01443 for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) {
01444 spur_chan_fbin = ee->ee_spur_chans[i][freq_band];
01445
01446
01447
01448 if (spur_chan_fbin == AR5K_EEPROM_NO_SPUR) {
01449 spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK;
01450 break;
01451 }
01452
01453 if ((chan_fbin - spur_detection_window <=
01454 (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK)) &&
01455 (chan_fbin + spur_detection_window >=
01456 (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK))) {
01457 spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK;
01458 break;
01459 }
01460 }
01461
01462
01463 if (spur_chan_fbin) {
01464 spur_offset = spur_chan_fbin - chan_fbin;
01465
01466
01467
01468
01469
01470
01471
01472 switch (channel->hw_value) {
01473 case CHANNEL_A:
01474
01475 spur_delta_phase = (spur_offset << 17) / 25;
01476 spur_freq_sigma_delta = (spur_delta_phase >> 10);
01477 symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
01478 break;
01479 case CHANNEL_G:
01480
01481
01482 spur_freq_sigma_delta = (spur_offset << 8) / 55;
01483 spur_delta_phase = (spur_offset << 17) / 25;
01484 symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
01485 break;
01486 case CHANNEL_T:
01487 case CHANNEL_TG:
01488
01489 spur_delta_phase = (spur_offset << 16) / 25;
01490 spur_freq_sigma_delta = (spur_delta_phase >> 10);
01491 symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz;
01492 break;
01493 default:
01494 return;
01495 }
01496
01497
01498
01499
01500
01501
01502 num_symbols_x16 = ((spur_offset * 1000) << 4) / symbol_width;
01503
01504
01505 if (!(num_symbols_x16 & 0xF))
01506
01507 num_symbol_offsets = 3;
01508 else
01509
01510 num_symbol_offsets = 4;
01511
01512 for (i = 0; i < num_symbol_offsets; i++) {
01513
01514
01515 s32 curr_sym_off =
01516 (num_symbols_x16 / 16) + i + 25;
01517
01518
01519
01520
01521
01522
01523 u8 plt_mag_map =
01524 (i == 0 || i == (num_symbol_offsets - 1))
01525 ? 1 : 2;
01526
01527 if (curr_sym_off >= 0 && curr_sym_off <= 32) {
01528 if (curr_sym_off <= 25)
01529 pilot_mask[0] |= 1 << curr_sym_off;
01530 else if (curr_sym_off >= 27)
01531 pilot_mask[0] |= 1 << (curr_sym_off - 1);
01532 } else if (curr_sym_off >= 33 && curr_sym_off <= 52)
01533 pilot_mask[1] |= 1 << (curr_sym_off - 33);
01534
01535
01536 if (curr_sym_off >= -1 && curr_sym_off <= 14)
01537 mag_mask[0] |=
01538 plt_mag_map << (curr_sym_off + 1) * 2;
01539 else if (curr_sym_off >= 15 && curr_sym_off <= 30)
01540 mag_mask[1] |=
01541 plt_mag_map << (curr_sym_off - 15) * 2;
01542 else if (curr_sym_off >= 31 && curr_sym_off <= 46)
01543 mag_mask[2] |=
01544 plt_mag_map << (curr_sym_off - 31) * 2;
01545 else if (curr_sym_off >= 46 && curr_sym_off <= 53)
01546 mag_mask[3] |=
01547 plt_mag_map << (curr_sym_off - 47) * 2;
01548
01549 }
01550
01551
01552 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
01553 AR5K_PHY_BIN_MASK_CTL_RATE, 0xff);
01554
01555 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
01556 AR5K_PHY_IQ_PILOT_MASK_EN |
01557 AR5K_PHY_IQ_CHAN_MASK_EN |
01558 AR5K_PHY_IQ_SPUR_FILT_EN);
01559
01560
01561 ath5k_hw_reg_write(ah,
01562 AR5K_REG_SM(spur_delta_phase,
01563 AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE) |
01564 AR5K_REG_SM(spur_freq_sigma_delta,
01565 AR5K_PHY_TIMING_11_SPUR_FREQ_SD) |
01566 AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC,
01567 AR5K_PHY_TIMING_11);
01568
01569
01570 ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_7);
01571 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8,
01572 AR5K_PHY_TIMING_8_PILOT_MASK_2,
01573 pilot_mask[1]);
01574
01575 ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_9);
01576 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10,
01577 AR5K_PHY_TIMING_10_PILOT_MASK_2,
01578 pilot_mask[1]);
01579
01580
01581 ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK_1);
01582 ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK_2);
01583 ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK_3);
01584 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
01585 AR5K_PHY_BIN_MASK_CTL_MASK_4,
01586 mag_mask[3]);
01587
01588 ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK2_1);
01589 ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK2_2);
01590 ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK2_3);
01591 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4,
01592 AR5K_PHY_BIN_MASK2_4_MASK_4,
01593 mag_mask[3]);
01594
01595 } else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) &
01596 AR5K_PHY_IQ_SPUR_FILT_EN) {
01597
01598 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
01599 AR5K_PHY_BIN_MASK_CTL_RATE, 0);
01600 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ,
01601 AR5K_PHY_IQ_PILOT_MASK_EN |
01602 AR5K_PHY_IQ_CHAN_MASK_EN |
01603 AR5K_PHY_IQ_SPUR_FILT_EN);
01604 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_11);
01605
01606
01607 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_7);
01608 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8,
01609 AR5K_PHY_TIMING_8_PILOT_MASK_2,
01610 0);
01611
01612 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_9);
01613 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10,
01614 AR5K_PHY_TIMING_10_PILOT_MASK_2,
01615 0);
01616
01617
01618 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_1);
01619 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_2);
01620 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_3);
01621 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
01622 AR5K_PHY_BIN_MASK_CTL_MASK_4,
01623 0);
01624
01625 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_1);
01626 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_2);
01627 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_3);
01628 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4,
01629 AR5K_PHY_BIN_MASK2_4_MASK_4,
01630 0);
01631 }
01632 }
01633
01634
01635
01636
01637
01638 int ath5k_hw_phy_disable(struct ath5k_hw *ah)
01639 {
01640 ATH5K_TRACE(ah->ah_sc);
01641
01642 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
01643
01644 return 0;
01645 }
01646
01647
01648
01649
01650 u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
01651 {
01652 unsigned int i;
01653 u32 srev;
01654 u16 ret;
01655
01656 ATH5K_TRACE(ah->ah_sc);
01657
01658
01659
01660
01661 switch (chan) {
01662 case CHANNEL_2GHZ:
01663 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
01664 break;
01665 case CHANNEL_5GHZ:
01666 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
01667 break;
01668 default:
01669 return 0;
01670 }
01671
01672 mdelay(2);
01673
01674
01675 ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
01676
01677 for (i = 0; i < 8; i++)
01678 ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
01679
01680 if (ah->ah_version == AR5K_AR5210) {
01681 srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
01682 ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
01683 } else {
01684 srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
01685 ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
01686 ((srev & 0x0f) << 4), 8);
01687 }
01688
01689
01690 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
01691
01692 return ret;
01693 }
01694
01695
01696
01697
01698
01699 void
01700 ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant)
01701 {
01702 ATH5K_TRACE(ah->ah_sc);
01703
01704 if (ah->ah_version != AR5K_AR5210)
01705 ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA);
01706 }
01707
01708 unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
01709 {
01710 ATH5K_TRACE(ah->ah_sc);
01711
01712 if (ah->ah_version != AR5K_AR5210)
01713 return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7;
01714
01715 return false;
01716 }
01717
01718
01719
01720
01721 static void
01722 ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)
01723 {
01724 switch (ee_mode) {
01725 case AR5K_EEPROM_MODE_11G:
01726
01727
01728 case AR5K_EEPROM_MODE_11A:
01729 if (enable)
01730 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGCCTL,
01731 AR5K_PHY_AGCCTL_OFDM_DIV_DIS);
01732 else
01733 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
01734 AR5K_PHY_AGCCTL_OFDM_DIV_DIS);
01735 break;
01736 case AR5K_EEPROM_MODE_11B:
01737 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
01738 AR5K_PHY_AGCCTL_OFDM_DIV_DIS);
01739 break;
01740 default:
01741 return;
01742 }
01743
01744 if (enable) {
01745 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
01746 AR5K_PHY_RESTART_DIV_GC, 0xc);
01747
01748 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
01749 AR5K_PHY_FAST_ANT_DIV_EN);
01750 } else {
01751 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
01752 AR5K_PHY_RESTART_DIV_GC, 0x8);
01753
01754 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
01755 AR5K_PHY_FAST_ANT_DIV_EN);
01756 }
01757 }
01758
01759
01760
01761
01762 void
01763 ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
01764 {
01765 struct ieee80211_channel *channel = ah->ah_current_channel;
01766 bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div;
01767 bool use_def_for_sg;
01768 u8 def_ant, tx_ant, ee_mode;
01769 u32 sta_id1 = 0;
01770
01771 def_ant = ah->ah_def_ant;
01772
01773 ATH5K_TRACE(ah->ah_sc);
01774
01775 switch (channel->hw_value & CHANNEL_MODES) {
01776 case CHANNEL_A:
01777 case CHANNEL_T:
01778 case CHANNEL_XR:
01779 ee_mode = AR5K_EEPROM_MODE_11A;
01780 break;
01781 case CHANNEL_G:
01782 case CHANNEL_TG:
01783 ee_mode = AR5K_EEPROM_MODE_11G;
01784 break;
01785 case CHANNEL_B:
01786 ee_mode = AR5K_EEPROM_MODE_11B;
01787 break;
01788 default:
01789 ATH5K_ERR(ah->ah_sc,
01790 "invalid channel: %d\n", channel->center_freq);
01791 return;
01792 }
01793
01794 switch (ant_mode) {
01795 case AR5K_ANTMODE_DEFAULT:
01796 tx_ant = 0;
01797 use_def_for_tx = false;
01798 update_def_on_tx = false;
01799 use_def_for_rts = false;
01800 use_def_for_sg = false;
01801 fast_div = true;
01802 break;
01803 case AR5K_ANTMODE_FIXED_A:
01804 def_ant = 1;
01805 tx_ant = 0;
01806 use_def_for_tx = true;
01807 update_def_on_tx = false;
01808 use_def_for_rts = true;
01809 use_def_for_sg = true;
01810 fast_div = false;
01811 break;
01812 case AR5K_ANTMODE_FIXED_B:
01813 def_ant = 2;
01814 tx_ant = 0;
01815 use_def_for_tx = true;
01816 update_def_on_tx = false;
01817 use_def_for_rts = true;
01818 use_def_for_sg = true;
01819 fast_div = false;
01820 break;
01821 case AR5K_ANTMODE_SINGLE_AP:
01822 def_ant = 1;
01823 tx_ant = 0;
01824 use_def_for_tx = true;
01825 update_def_on_tx = true;
01826 use_def_for_rts = true;
01827 use_def_for_sg = true;
01828 fast_div = true;
01829 break;
01830 case AR5K_ANTMODE_SECTOR_AP:
01831 tx_ant = 1;
01832 use_def_for_tx = false;
01833 update_def_on_tx = false;
01834 use_def_for_rts = true;
01835 use_def_for_sg = false;
01836 fast_div = false;
01837 break;
01838 case AR5K_ANTMODE_SECTOR_STA:
01839 tx_ant = 1;
01840 use_def_for_tx = true;
01841 update_def_on_tx = false;
01842 use_def_for_rts = true;
01843 use_def_for_sg = false;
01844 fast_div = true;
01845 break;
01846 case AR5K_ANTMODE_DEBUG:
01847 def_ant = 1;
01848 tx_ant = 2;
01849 use_def_for_tx = false;
01850 update_def_on_tx = false;
01851 use_def_for_rts = false;
01852 use_def_for_sg = false;
01853 fast_div = false;
01854 break;
01855 default:
01856 return;
01857 }
01858
01859 ah->ah_tx_ant = tx_ant;
01860 ah->ah_ant_mode = ant_mode;
01861
01862 sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0;
01863 sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0;
01864 sta_id1 |= use_def_for_rts ? AR5K_STA_ID1_RTS_DEF_ANTENNA : 0;
01865 sta_id1 |= use_def_for_sg ? AR5K_STA_ID1_SELFGEN_DEF_ANT : 0;
01866
01867 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_ANTENNA_SETTINGS);
01868
01869 if (sta_id1)
01870 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1);
01871
01872
01873
01874 ath5k_hw_set_fast_div(ah, ee_mode, fast_div);
01875 ath5k_hw_set_def_antenna(ah, def_ant);
01876 }
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890 static s16
01891 ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,
01892 s16 y_left, s16 y_right)
01893 {
01894 s16 ratio, result;
01895
01896
01897
01898 if ((x_left == x_right) || (y_left == y_right))
01899 return y_left;
01900
01901
01902
01903
01904
01905
01906
01907 ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
01908
01909
01910 result = y_left + (ratio * (target - x_left) / 100);
01911
01912 return result;
01913 }
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923 static s16
01924 ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
01925 const s16 *pwrL, const s16 *pwrR)
01926 {
01927 s8 tmp;
01928 s16 min_pwrL, min_pwrR;
01929 s16 pwr_i;
01930
01931
01932 if (stepL[0] == stepL[1] || stepR[0] == stepR[1])
01933 return max(pwrL[0], pwrR[0]);
01934
01935 if (pwrL[0] == pwrL[1])
01936 min_pwrL = pwrL[0];
01937 else {
01938 pwr_i = pwrL[0];
01939 do {
01940 pwr_i--;
01941 tmp = (s8) ath5k_get_interpolated_value(pwr_i,
01942 pwrL[0], pwrL[1],
01943 stepL[0], stepL[1]);
01944 } while (tmp > 1);
01945
01946 min_pwrL = pwr_i;
01947 }
01948
01949 if (pwrR[0] == pwrR[1])
01950 min_pwrR = pwrR[0];
01951 else {
01952 pwr_i = pwrR[0];
01953 do {
01954 pwr_i--;
01955 tmp = (s8) ath5k_get_interpolated_value(pwr_i,
01956 pwrR[0], pwrR[1],
01957 stepR[0], stepR[1]);
01958 } while (tmp > 1);
01959
01960 min_pwrR = pwr_i;
01961 }
01962
01963
01964 return max(min_pwrL, min_pwrR);
01965 }
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979 static void
01980 ath5k_create_power_curve(s16 pmin, s16 pmax,
01981 const s16 *pwr, const u8 *vpd,
01982 u8 num_points,
01983 u8 *vpd_table, u8 type)
01984 {
01985 u8 idx[2] = { 0, 1 };
01986 s16 pwr_i = 2*pmin;
01987 int i;
01988
01989 if (num_points < 2)
01990 return;
01991
01992
01993
01994
01995
01996 if (type == AR5K_PWRTABLE_LINEAR_PCDAC) {
01997 pwr_i = pmin;
01998 pmin = 0;
01999 pmax = 63;
02000 }
02001
02002
02003
02004 for (i = 0; (i <= (u16) (pmax - pmin)) &&
02005 (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
02006
02007
02008
02009
02010 if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) {
02011 idx[0]++;
02012 idx[1]++;
02013 }
02014
02015 vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i,
02016 pwr[idx[0]], pwr[idx[1]],
02017 vpd[idx[0]], vpd[idx[1]]);
02018
02019
02020
02021 pwr_i += 2;
02022 }
02023 }
02024
02025
02026
02027
02028
02029
02030
02031 static void
02032 ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah,
02033 struct ieee80211_channel *channel,
02034 struct ath5k_chan_pcal_info **pcinfo_l,
02035 struct ath5k_chan_pcal_info **pcinfo_r)
02036 {
02037 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
02038 struct ath5k_chan_pcal_info *pcinfo;
02039 u8 idx_l, idx_r;
02040 u8 mode, max, i;
02041 u32 target = channel->center_freq;
02042
02043 idx_l = 0;
02044 idx_r = 0;
02045
02046 if (!(channel->hw_value & CHANNEL_OFDM)) {
02047 pcinfo = ee->ee_pwr_cal_b;
02048 mode = AR5K_EEPROM_MODE_11B;
02049 } else if (channel->hw_value & CHANNEL_2GHZ) {
02050 pcinfo = ee->ee_pwr_cal_g;
02051 mode = AR5K_EEPROM_MODE_11G;
02052 } else {
02053 pcinfo = ee->ee_pwr_cal_a;
02054 mode = AR5K_EEPROM_MODE_11A;
02055 }
02056 max = ee->ee_n_piers[mode] - 1;
02057
02058
02059
02060
02061 if (target < pcinfo[0].freq) {
02062 idx_l = idx_r = 0;
02063 goto done;
02064 }
02065
02066
02067
02068
02069 if (target > pcinfo[max].freq) {
02070 idx_l = idx_r = max;
02071 goto done;
02072 }
02073
02074
02075
02076
02077
02078 for (i = 0; i <= max; i++) {
02079
02080
02081
02082
02083 if (pcinfo[i].freq == target) {
02084 idx_l = idx_r = i;
02085 goto done;
02086 }
02087
02088
02089
02090
02091 if (target < pcinfo[i].freq) {
02092 idx_r = i;
02093 idx_l = idx_r - 1;
02094 goto done;
02095 }
02096 }
02097
02098 done:
02099 *pcinfo_l = &pcinfo[idx_l];
02100 *pcinfo_r = &pcinfo[idx_r];
02101
02102 return;
02103 }
02104
02105
02106
02107
02108
02109
02110
02111 static void
02112 ath5k_get_rate_pcal_data(struct ath5k_hw *ah,
02113 struct ieee80211_channel *channel,
02114 struct ath5k_rate_pcal_info *rates)
02115 {
02116 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
02117 struct ath5k_rate_pcal_info *rpinfo;
02118 u8 idx_l, idx_r;
02119 u8 mode, max, i;
02120 u32 target = channel->center_freq;
02121
02122 idx_l = 0;
02123 idx_r = 0;
02124
02125 if (!(channel->hw_value & CHANNEL_OFDM)) {
02126 rpinfo = ee->ee_rate_tpwr_b;
02127 mode = AR5K_EEPROM_MODE_11B;
02128 } else if (channel->hw_value & CHANNEL_2GHZ) {
02129 rpinfo = ee->ee_rate_tpwr_g;
02130 mode = AR5K_EEPROM_MODE_11G;
02131 } else {
02132 rpinfo = ee->ee_rate_tpwr_a;
02133 mode = AR5K_EEPROM_MODE_11A;
02134 }
02135 max = ee->ee_rate_target_pwr_num[mode] - 1;
02136
02137
02138
02139 if (target < rpinfo[0].freq) {
02140 idx_l = idx_r = 0;
02141 goto done;
02142 }
02143
02144 if (target > rpinfo[max].freq) {
02145 idx_l = idx_r = max;
02146 goto done;
02147 }
02148
02149 for (i = 0; i <= max; i++) {
02150
02151 if (rpinfo[i].freq == target) {
02152 idx_l = idx_r = i;
02153 goto done;
02154 }
02155
02156 if (target < rpinfo[i].freq) {
02157 idx_r = i;
02158 idx_l = idx_r - 1;
02159 goto done;
02160 }
02161 }
02162
02163 done:
02164
02165 rates->freq = target;
02166
02167 rates->target_power_6to24 =
02168 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
02169 rpinfo[idx_r].freq,
02170 rpinfo[idx_l].target_power_6to24,
02171 rpinfo[idx_r].target_power_6to24);
02172
02173 rates->target_power_36 =
02174 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
02175 rpinfo[idx_r].freq,
02176 rpinfo[idx_l].target_power_36,
02177 rpinfo[idx_r].target_power_36);
02178
02179 rates->target_power_48 =
02180 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
02181 rpinfo[idx_r].freq,
02182 rpinfo[idx_l].target_power_48,
02183 rpinfo[idx_r].target_power_48);
02184
02185 rates->target_power_54 =
02186 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
02187 rpinfo[idx_r].freq,
02188 rpinfo[idx_l].target_power_54,
02189 rpinfo[idx_r].target_power_54);
02190 }
02191
02192
02193
02194
02195
02196
02197 #if 0
02198 static void
02199 ath5k_get_max_ctl_power(struct ath5k_hw *ah,
02200 struct ieee80211_channel *channel)
02201 {
02202 struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
02203 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
02204 struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
02205 u8 *ctl_val = ee->ee_ctl;
02206 s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4;
02207 s16 edge_pwr = 0;
02208 u8 rep_idx;
02209 u8 i, ctl_mode;
02210 u8 ctl_idx = 0xFF;
02211 u32 target = channel->center_freq;
02212
02213 ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band);
02214
02215 switch (channel->hw_value & CHANNEL_MODES) {
02216 case CHANNEL_A:
02217 ctl_mode |= AR5K_CTL_11A;
02218 break;
02219 case CHANNEL_G:
02220 ctl_mode |= AR5K_CTL_11G;
02221 break;
02222 case CHANNEL_B:
02223 ctl_mode |= AR5K_CTL_11B;
02224 break;
02225 case CHANNEL_T:
02226 ctl_mode |= AR5K_CTL_TURBO;
02227 break;
02228 case CHANNEL_TG:
02229 ctl_mode |= AR5K_CTL_TURBOG;
02230 break;
02231 case CHANNEL_XR:
02232
02233 default:
02234 return;
02235 }
02236
02237 for (i = 0; i < ee->ee_ctls; i++) {
02238 if (ctl_val[i] == ctl_mode) {
02239 ctl_idx = i;
02240 break;
02241 }
02242 }
02243
02244
02245
02246 if (ctl_idx == 0xFF)
02247 return;
02248
02249
02250
02251
02252 rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES;
02253
02254
02255
02256
02257
02258
02259
02260 for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) {
02261 rep_idx += i;
02262 if (target <= rep[rep_idx].freq)
02263 edge_pwr = (s16) rep[rep_idx].edge;
02264 }
02265
02266 if (edge_pwr)
02267 ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
02268 }
02269 #endif
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282 static void
02283 ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
02284 s16 *table_max)
02285 {
02286 u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
02287 u8 *pcdac_tmp = ah->ah_txpower.tmpL[0];
02288 u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
02289 s16 min_pwr, max_pwr;
02290
02291
02292 min_pwr = table_min[0];
02293 pcdac_0 = pcdac_tmp[0];
02294
02295 max_pwr = table_max[0];
02296 pcdac_n = pcdac_tmp[table_max[0] - table_min[0]];
02297
02298
02299 pcdac_i = 0;
02300 for (i = 0; i < min_pwr; i++)
02301 pcdac_out[pcdac_i++] = pcdac_0;
02302
02303
02304 pwr_idx = min_pwr;
02305 for (i = 0 ; pwr_idx <= max_pwr &&
02306 pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
02307 pcdac_out[pcdac_i++] = pcdac_tmp[i];
02308 pwr_idx++;
02309 }
02310
02311
02312 while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE)
02313 pcdac_out[pcdac_i++] = pcdac_n;
02314
02315 }
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328 static void
02329 ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
02330 s16 *table_max, u8 pdcurves)
02331 {
02332 u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
02333 u8 *pcdac_low_pwr;
02334 u8 *pcdac_high_pwr;
02335 u8 *pcdac_tmp;
02336 u8 pwr;
02337 s16 max_pwr_idx;
02338 s16 min_pwr_idx;
02339 s16 mid_pwr_idx = 0;
02340
02341
02342
02343
02344
02345
02346 u8 edge_flag;
02347 int i;
02348
02349
02350
02351
02352
02353 if (pdcurves > 1) {
02354 pcdac_low_pwr = ah->ah_txpower.tmpL[1];
02355 pcdac_high_pwr = ah->ah_txpower.tmpL[0];
02356 mid_pwr_idx = table_max[1] - table_min[1] - 1;
02357 max_pwr_idx = (table_max[0] - table_min[0]) / 2;
02358
02359
02360
02361
02362 if (table_max[0] - table_min[1] > 126)
02363 min_pwr_idx = table_max[0] - 126;
02364 else
02365 min_pwr_idx = table_min[1];
02366
02367
02368
02369 pcdac_tmp = pcdac_high_pwr;
02370
02371 edge_flag = 0x40;
02372 #if 0
02373
02374
02375
02376
02377
02378 if (min_pwr < table_max[1] &&
02379 max_pwr < table_max[1]) {
02380 edge_flag = 0;
02381 pcdac_tmp = pcdac_low_pwr;
02382 max_pwr_idx = (table_max[1] - table_min[1])/2;
02383 }
02384 #endif
02385 } else {
02386 pcdac_low_pwr = ah->ah_txpower.tmpL[1];
02387 pcdac_high_pwr = ah->ah_txpower.tmpL[0];
02388 min_pwr_idx = table_min[0];
02389 max_pwr_idx = (table_max[0] - table_min[0]) / 2;
02390 pcdac_tmp = pcdac_high_pwr;
02391 edge_flag = 0;
02392 }
02393
02394
02395 ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
02396
02397
02398 pwr = max_pwr_idx;
02399 for (i = 63; i >= 0; i--) {
02400
02401
02402
02403 if (edge_flag == 0x40 &&
02404 (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
02405 edge_flag = 0x00;
02406 pcdac_tmp = pcdac_low_pwr;
02407 pwr = mid_pwr_idx/2;
02408 }
02409
02410
02411
02412
02413
02414 if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
02415 while (i >= 0) {
02416 pcdac_out[i] = pcdac_out[i + 1];
02417 i--;
02418 }
02419 break;
02420 }
02421
02422 pcdac_out[i] = pcdac_tmp[pwr] | edge_flag;
02423
02424
02425
02426
02427 if (pcdac_out[i] > 126)
02428 pcdac_out[i] = 126;
02429
02430
02431 pwr--;
02432 }
02433 }
02434
02435
02436 static void
02437 ath5k_setup_pcdac_table(struct ath5k_hw *ah)
02438 {
02439 u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
02440 int i;
02441
02442
02443
02444
02445 for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
02446 ath5k_hw_reg_write(ah,
02447 (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
02448 (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
02449 AR5K_PHY_PCDAC_TXPOWER(i));
02450 }
02451 }
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465 static void
02466 ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah,
02467 s16 *pwr_min, s16 *pwr_max, u8 pdcurves)
02468 {
02469 u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS];
02470 u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
02471 u8 *pdadc_tmp;
02472 s16 pdadc_0;
02473 u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size;
02474 u8 pd_gain_overlap;
02475
02476
02477
02478
02479 pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) &
02480 AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP;
02481
02482
02483 for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) {
02484 pdadc_tmp = ah->ah_txpower.tmpL[pdg];
02485
02486 if (pdg == pdcurves - 1)
02487
02488
02489 gain_boundaries[pdg] = pwr_max[pdg] + 4;
02490 else
02491
02492
02493 gain_boundaries[pdg] =
02494 (pwr_max[pdg] + pwr_min[pdg + 1]) / 2;
02495
02496
02497
02498 if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER)
02499 gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER;
02500
02501
02502
02503 if (pdg == 0)
02504 pdadc_0 = 0;
02505 else
02506
02507 pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) -
02508 pd_gain_overlap;
02509
02510
02511 if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1)
02512 pwr_step = pdadc_tmp[1] - pdadc_tmp[0];
02513 else
02514 pwr_step = 1;
02515
02516
02517
02518 while ((pdadc_0 < 0) && (pdadc_i < 128)) {
02519 s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step;
02520 pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp;
02521 pdadc_0++;
02522 }
02523
02524
02525 pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg];
02526
02527 table_size = pwr_max[pdg] - pwr_min[pdg];
02528 max_idx = (pdadc_n < table_size) ? pdadc_n : table_size;
02529
02530
02531 while (pdadc_0 < max_idx)
02532 pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++];
02533
02534
02535 if (pdadc_n <= max_idx)
02536 continue;
02537
02538
02539 if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1)
02540 pwr_step = pdadc_tmp[table_size - 1] -
02541 pdadc_tmp[table_size - 2];
02542 else
02543 pwr_step = 1;
02544
02545
02546 while ((pdadc_0 < (s16) pdadc_n) &&
02547 (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) {
02548 s16 tmp = pdadc_tmp[table_size - 1] +
02549 (pdadc_0 - max_idx) * pwr_step;
02550 pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp;
02551 pdadc_0++;
02552 }
02553 }
02554
02555 while (pdg < AR5K_EEPROM_N_PD_GAINS) {
02556 gain_boundaries[pdg] = gain_boundaries[pdg - 1];
02557 pdg++;
02558 }
02559
02560 while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) {
02561 pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1];
02562 pdadc_i++;
02563 }
02564
02565
02566 ath5k_hw_reg_write(ah,
02567 AR5K_REG_SM(pd_gain_overlap,
02568 AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) |
02569 AR5K_REG_SM(gain_boundaries[0],
02570 AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) |
02571 AR5K_REG_SM(gain_boundaries[1],
02572 AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) |
02573 AR5K_REG_SM(gain_boundaries[2],
02574 AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) |
02575 AR5K_REG_SM(gain_boundaries[3],
02576 AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4),
02577 AR5K_PHY_TPC_RG5);
02578
02579
02580 ah->ah_txpower.txp_min_idx = pwr_min[0];
02581
02582 }
02583
02584
02585 static void
02586 ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah,
02587 u8 pdcurves, u8 *pdg_to_idx)
02588 {
02589 u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
02590 u32 reg;
02591 u8 i;
02592
02593
02594
02595
02596 reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1);
02597 reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 |
02598 AR5K_PHY_TPC_RG1_PDGAIN_2 |
02599 AR5K_PHY_TPC_RG1_PDGAIN_3 |
02600 AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610 reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
02611
02612 switch (pdcurves) {
02613 case 3:
02614 reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3);
02615
02616 case 2:
02617 reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2);
02618
02619 case 1:
02620 reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1);
02621 break;
02622 }
02623 ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1);
02624
02625
02626
02627
02628 for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
02629 ath5k_hw_reg_write(ah,
02630 ((pdadc_out[4*i + 0] & 0xff) << 0) |
02631 ((pdadc_out[4*i + 1] & 0xff) << 8) |
02632 ((pdadc_out[4*i + 2] & 0xff) << 16) |
02633 ((pdadc_out[4*i + 3] & 0xff) << 24),
02634 AR5K_PHY_PDADC_TXPOWER(i));
02635 }
02636 }
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650 static int
02651 ath5k_setup_channel_powertable(struct ath5k_hw *ah,
02652 struct ieee80211_channel *channel,
02653 u8 ee_mode, u8 type)
02654 {
02655 struct ath5k_pdgain_info *pdg_L, *pdg_R;
02656 struct ath5k_chan_pcal_info *pcinfo_L;
02657 struct ath5k_chan_pcal_info *pcinfo_R;
02658 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
02659 u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
02660 s16 table_min[AR5K_EEPROM_N_PD_GAINS];
02661 s16 table_max[AR5K_EEPROM_N_PD_GAINS];
02662 u8 *tmpL;
02663 u8 *tmpR;
02664 u32 target = channel->center_freq;
02665 int pdg, i;
02666
02667
02668 ath5k_get_chan_pcal_surrounding_piers(ah, channel,
02669 &pcinfo_L,
02670 &pcinfo_R);
02671
02672
02673
02674 for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) {
02675
02676
02677
02678
02679
02680 u8 idx = pdg_curve_to_idx[pdg];
02681
02682
02683 pdg_L = &pcinfo_L->pd_curves[idx];
02684 pdg_R = &pcinfo_R->pd_curves[idx];
02685
02686
02687 tmpL = ah->ah_txpower.tmpL[pdg];
02688 tmpR = ah->ah_txpower.tmpR[pdg];
02689
02690
02691
02692
02693
02694
02695
02696 table_min[pdg] = min(pdg_L->pd_pwr[0],
02697 pdg_R->pd_pwr[0]) / 2;
02698
02699 table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
02700 pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2;
02701
02702
02703
02704
02705 switch (type) {
02706 case AR5K_PWRTABLE_LINEAR_PCDAC:
02707
02708
02709 table_min[pdg] = min(pdg_L->pd_pwr[0],
02710 pdg_R->pd_pwr[0]);
02711
02712 table_max[pdg] =
02713 max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
02714 pdg_R->pd_pwr[pdg_R->pd_points - 1]);
02715
02716
02717
02718
02719
02720
02721 if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) {
02722
02723 table_min[pdg] =
02724 ath5k_get_linear_pcdac_min(pdg_L->pd_step,
02725 pdg_R->pd_step,
02726 pdg_L->pd_pwr,
02727 pdg_R->pd_pwr);
02728
02729
02730
02731
02732
02733 if (table_max[pdg] - table_min[pdg] > 126)
02734 table_min[pdg] = table_max[pdg] - 126;
02735 }
02736
02737
02738 case AR5K_PWRTABLE_PWR_TO_PCDAC:
02739 case AR5K_PWRTABLE_PWR_TO_PDADC:
02740
02741 ath5k_create_power_curve(table_min[pdg],
02742 table_max[pdg],
02743 pdg_L->pd_pwr,
02744 pdg_L->pd_step,
02745 pdg_L->pd_points, tmpL, type);
02746
02747
02748
02749
02750 if (pcinfo_L == pcinfo_R)
02751 continue;
02752
02753 ath5k_create_power_curve(table_min[pdg],
02754 table_max[pdg],
02755 pdg_R->pd_pwr,
02756 pdg_R->pd_step,
02757 pdg_R->pd_points, tmpR, type);
02758 break;
02759 default:
02760 return -EINVAL;
02761 }
02762
02763
02764
02765
02766
02767
02768 for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) &&
02769 (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
02770 tmpL[i] = (u8) ath5k_get_interpolated_value(target,
02771 (s16) pcinfo_L->freq,
02772 (s16) pcinfo_R->freq,
02773 (s16) tmpL[i],
02774 (s16) tmpR[i]);
02775 }
02776 }
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789 ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target,
02790 (s16) pcinfo_L->freq,
02791 (s16) pcinfo_R->freq,
02792 pcinfo_L->min_pwr, pcinfo_R->min_pwr);
02793
02794 ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target,
02795 (s16) pcinfo_L->freq,
02796 (s16) pcinfo_R->freq,
02797 pcinfo_L->max_pwr, pcinfo_R->max_pwr);
02798
02799
02800
02801 switch (type) {
02802 case AR5K_PWRTABLE_LINEAR_PCDAC:
02803
02804
02805
02806 ath5k_combine_linear_pcdac_curves(ah, table_min, table_max,
02807 ee->ee_pd_gains[ee_mode]);
02808
02809
02810
02811
02812 ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2);
02813
02814
02815 ath5k_setup_pcdac_table(ah);
02816 break;
02817 case AR5K_PWRTABLE_PWR_TO_PCDAC:
02818
02819
02820 ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max);
02821
02822
02823 ah->ah_txpower.txp_min_idx = 0;
02824 ah->ah_txpower.txp_offset = 0;
02825
02826
02827 ath5k_setup_pcdac_table(ah);
02828 break;
02829 case AR5K_PWRTABLE_PWR_TO_PDADC:
02830
02831
02832 ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max,
02833 ee->ee_pd_gains[ee_mode]);
02834
02835
02836 ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx);
02837
02838
02839
02840 ah->ah_txpower.txp_offset = table_min[0];
02841 break;
02842 default:
02843 return -EINVAL;
02844 }
02845
02846 return 0;
02847 }
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872 static void
02873 ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
02874 struct ath5k_rate_pcal_info *rate_info,
02875 u8 ee_mode)
02876 {
02877 unsigned int i;
02878 u16 *rates;
02879
02880
02881
02882 max_pwr *= 2;
02883 max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2;
02884
02885
02886 rates = ah->ah_txpower.txp_rates_power_table;
02887
02888
02889 for (i = 0; i < 5; i++)
02890 rates[i] = min(max_pwr, rate_info->target_power_6to24);
02891
02892
02893 rates[5] = min(rates[0], rate_info->target_power_36);
02894 rates[6] = min(rates[0], rate_info->target_power_48);
02895 rates[7] = min(rates[0], rate_info->target_power_54);
02896
02897
02898
02899 rates[8] = min(rates[0], rate_info->target_power_6to24);
02900
02901 rates[9] = min(rates[0], rate_info->target_power_36);
02902
02903 rates[10] = min(rates[0], rate_info->target_power_36);
02904
02905 rates[11] = min(rates[0], rate_info->target_power_48);
02906
02907 rates[12] = min(rates[0], rate_info->target_power_48);
02908
02909 rates[13] = min(rates[0], rate_info->target_power_54);
02910
02911 rates[14] = min(rates[0], rate_info->target_power_54);
02912
02913
02914 rates[15] = min(rates[0], rate_info->target_power_6to24);
02915
02916
02917
02918
02919
02920 if ((ee_mode == AR5K_EEPROM_MODE_11G) &&
02921 (ah->ah_phy_revision < AR5K_SREV_PHY_5212A))
02922 for (i = 8; i <= 15; i++)
02923 rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
02924
02925
02926
02927
02928 for (i = 0; i < 16; i++) {
02929 rates[i] += ah->ah_txpower.txp_offset;
02930
02931 if (rates[i] > 63)
02932 rates[i] = 63;
02933 }
02934
02935
02936 ah->ah_txpower.txp_min_pwr = 2 * rates[7];
02937 ah->ah_txpower.txp_max_pwr = 2 * rates[0];
02938 ah->ah_txpower.txp_ofdm = rates[7];
02939 }
02940
02941
02942
02943
02944
02945 int
02946 ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
02947 u8 ee_mode, u8 txpower)
02948 {
02949 struct ath5k_rate_pcal_info rate_info;
02950 u8 type;
02951 int ret;
02952
02953 ATH5K_TRACE(ah->ah_sc);
02954 if (txpower > AR5K_TUNE_MAX_TXPOWER) {
02955 ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
02956 return -EINVAL;
02957 }
02958 if (txpower == 0)
02959 txpower = AR5K_TUNE_DEFAULT_TXPOWER;
02960
02961
02962 memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
02963 ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
02964 ah->ah_txpower.txp_min_pwr = 0;
02965 ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER;
02966
02967
02968 switch (ah->ah_radio) {
02969 case AR5K_RF5111:
02970 type = AR5K_PWRTABLE_PWR_TO_PCDAC;
02971 break;
02972 case AR5K_RF5112:
02973 type = AR5K_PWRTABLE_LINEAR_PCDAC;
02974 break;
02975 case AR5K_RF2413:
02976 case AR5K_RF5413:
02977 case AR5K_RF2316:
02978 case AR5K_RF2317:
02979 case AR5K_RF2425:
02980 type = AR5K_PWRTABLE_PWR_TO_PDADC;
02981 break;
02982 default:
02983 return -EINVAL;
02984 }
02985
02986
02987 ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type);
02988 if (ret)
02989 return ret;
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005 ath5k_get_rate_pcal_data(ah, channel, &rate_info);
03006
03007
03008 ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode);
03009
03010
03011 ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) |
03012 AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
03013 AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1);
03014
03015 ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) |
03016 AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
03017 AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2);
03018
03019 ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) |
03020 AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
03021 AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3);
03022
03023 ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) |
03024 AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
03025 AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
03026
03027
03028 if (ah->ah_txpower.txp_tpc) {
03029 ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
03030 AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
03031
03032 ath5k_hw_reg_write(ah,
03033 AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) |
03034 AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) |
03035 AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP),
03036 AR5K_TPC);
03037 } else {
03038 ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
03039 AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
03040 }
03041
03042 return 0;
03043 }
03044
03045 int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
03046 {
03047
03048 struct ieee80211_channel *channel = ah->ah_current_channel;
03049 u8 ee_mode;
03050
03051 ATH5K_TRACE(ah->ah_sc);
03052
03053 switch (channel->hw_value & CHANNEL_MODES) {
03054 case CHANNEL_A:
03055 case CHANNEL_T:
03056 case CHANNEL_XR:
03057 ee_mode = AR5K_EEPROM_MODE_11A;
03058 break;
03059 case CHANNEL_G:
03060 case CHANNEL_TG:
03061 ee_mode = AR5K_EEPROM_MODE_11G;
03062 break;
03063 case CHANNEL_B:
03064 ee_mode = AR5K_EEPROM_MODE_11B;
03065 break;
03066 default:
03067 ATH5K_ERR(ah->ah_sc,
03068 "invalid channel: %d\n", channel->center_freq);
03069 return -EINVAL;
03070 }
03071
03072 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
03073 "changing txpower to %d\n", txpower);
03074
03075 return ath5k_hw_txpower(ah, channel, ee_mode, txpower);
03076 }
03077
03078 #undef _ATH5K_PHY