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