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