📄 iwl-4965.c
字号:
return -1;}static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel){ s32 b = -1; for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) { if (priv->eeprom.calib_info.band_info[b].ch_from == 0) continue; if ((channel >= priv->eeprom.calib_info.band_info[b].ch_from) && (channel <= priv->eeprom.calib_info.band_info[b].ch_to)) break; } return b;}static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2){ s32 val; if (x2 == x1) return y1; else { iwl4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val); return val + y2; }}static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, struct iwl_eeprom_calib_ch_info *chan_info){ s32 s = -1; u32 c; u32 m; const struct iwl_eeprom_calib_measure *m1; const struct iwl_eeprom_calib_measure *m2; struct iwl_eeprom_calib_measure *omeas; u32 ch_i1; u32 ch_i2; s = iwl4965_get_sub_band(priv, channel); if (s >= EEPROM_TX_POWER_BANDS) { IWL_ERROR("Tx Power can not find channel %d ", channel); return -1; } ch_i1 = priv->eeprom.calib_info.band_info[s].ch1.ch_num; ch_i2 = priv->eeprom.calib_info.band_info[s].ch2.ch_num; chan_info->ch_num = (u8) channel; IWL_DEBUG_TXPOWER("channel %d subband %d factory cal ch %d & %d\n", channel, s, ch_i1, ch_i2); for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) { for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) { m1 = &(priv->eeprom.calib_info.band_info[s].ch1. measurements[c][m]); m2 = &(priv->eeprom.calib_info.band_info[s].ch2. measurements[c][m]); omeas = &(chan_info->measurements[c][m]); omeas->actual_pow = (u8) iwl4965_interpolate_value(channel, ch_i1, m1->actual_pow, ch_i2, m2->actual_pow); omeas->gain_idx = (u8) iwl4965_interpolate_value(channel, ch_i1, m1->gain_idx, ch_i2, m2->gain_idx); omeas->temperature = (u8) iwl4965_interpolate_value(channel, ch_i1, m1->temperature, ch_i2, m2->temperature); omeas->pa_det = (s8) iwl4965_interpolate_value(channel, ch_i1, m1->pa_det, ch_i2, m2->pa_det); IWL_DEBUG_TXPOWER ("chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m, m1->actual_pow, m2->actual_pow, omeas->actual_pow); IWL_DEBUG_TXPOWER ("chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m, m1->gain_idx, m2->gain_idx, omeas->gain_idx); IWL_DEBUG_TXPOWER ("chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m, m1->pa_det, m2->pa_det, omeas->pa_det); IWL_DEBUG_TXPOWER ("chain %d meas %d T1=%d T2=%d T=%d\n", c, m, m1->temperature, m2->temperature, omeas->temperature); } } return 0;}/* bit-rate-dependent table to prevent Tx distortion, in half-dB units, * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */static s32 back_off_table[] = { 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 20 MHz */ 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 20 MHz */ 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 40 MHz */ 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 40 MHz */ 10 /* CCK */};/* Thermal compensation values for txpower for various frequency ranges ... * ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */static struct iwl_txpower_comp_entry { s32 degrees_per_05db_a; s32 degrees_per_05db_a_denom;} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = { {9, 2}, /* group 0 5.2, ch 34-43 */ {4, 1}, /* group 1 5.2, ch 44-70 */ {4, 1}, /* group 2 5.2, ch 71-124 */ {4, 1}, /* group 3 5.2, ch 125-200 */ {3, 1} /* group 4 2.4, ch all */};static s32 get_min_power_index(s32 rate_power_index, u32 band){ if (!band) { if ((rate_power_index & 7) <= 4) return MIN_TX_GAIN_INDEX_52GHZ_EXT; } return MIN_TX_GAIN_INDEX;}struct gain_entry { u8 dsp; u8 radio;};static const struct gain_entry gain_table[2][108] = { /* 5.2GHz power gain index table */ { {123, 0x3F}, /* highest txpower */ {117, 0x3F}, {110, 0x3F}, {104, 0x3F}, {98, 0x3F}, {110, 0x3E}, {104, 0x3E}, {98, 0x3E}, {110, 0x3D}, {104, 0x3D}, {98, 0x3D}, {110, 0x3C}, {104, 0x3C}, {98, 0x3C}, {110, 0x3B}, {104, 0x3B}, {98, 0x3B}, {110, 0x3A}, {104, 0x3A}, {98, 0x3A}, {110, 0x39}, {104, 0x39}, {98, 0x39}, {110, 0x38}, {104, 0x38}, {98, 0x38}, {110, 0x37}, {104, 0x37}, {98, 0x37}, {110, 0x36}, {104, 0x36}, {98, 0x36}, {110, 0x35}, {104, 0x35}, {98, 0x35}, {110, 0x34}, {104, 0x34}, {98, 0x34}, {110, 0x33}, {104, 0x33}, {98, 0x33}, {110, 0x32}, {104, 0x32}, {98, 0x32}, {110, 0x31}, {104, 0x31}, {98, 0x31}, {110, 0x30}, {104, 0x30}, {98, 0x30}, {110, 0x25}, {104, 0x25}, {98, 0x25}, {110, 0x24}, {104, 0x24}, {98, 0x24}, {110, 0x23}, {104, 0x23}, {98, 0x23}, {110, 0x22}, {104, 0x18}, {98, 0x18}, {110, 0x17}, {104, 0x17}, {98, 0x17}, {110, 0x16}, {104, 0x16}, {98, 0x16}, {110, 0x15}, {104, 0x15}, {98, 0x15}, {110, 0x14}, {104, 0x14}, {98, 0x14}, {110, 0x13}, {104, 0x13}, {98, 0x13}, {110, 0x12}, {104, 0x08}, {98, 0x08}, {110, 0x07}, {104, 0x07}, {98, 0x07}, {110, 0x06}, {104, 0x06}, {98, 0x06}, {110, 0x05}, {104, 0x05}, {98, 0x05}, {110, 0x04}, {104, 0x04}, {98, 0x04}, {110, 0x03}, {104, 0x03}, {98, 0x03}, {110, 0x02}, {104, 0x02}, {98, 0x02}, {110, 0x01}, {104, 0x01}, {98, 0x01}, {110, 0x00}, {104, 0x00}, {98, 0x00}, {93, 0x00}, {88, 0x00}, {83, 0x00}, {78, 0x00}, }, /* 2.4GHz power gain index table */ { {110, 0x3f}, /* highest txpower */ {104, 0x3f}, {98, 0x3f}, {110, 0x3e}, {104, 0x3e}, {98, 0x3e}, {110, 0x3d}, {104, 0x3d}, {98, 0x3d}, {110, 0x3c}, {104, 0x3c}, {98, 0x3c}, {110, 0x3b}, {104, 0x3b}, {98, 0x3b}, {110, 0x3a}, {104, 0x3a}, {98, 0x3a}, {110, 0x39}, {104, 0x39}, {98, 0x39}, {110, 0x38}, {104, 0x38}, {98, 0x38}, {110, 0x37}, {104, 0x37}, {98, 0x37}, {110, 0x36}, {104, 0x36}, {98, 0x36}, {110, 0x35}, {104, 0x35}, {98, 0x35}, {110, 0x34}, {104, 0x34}, {98, 0x34}, {110, 0x33}, {104, 0x33}, {98, 0x33}, {110, 0x32}, {104, 0x32}, {98, 0x32}, {110, 0x31}, {104, 0x31}, {98, 0x31}, {110, 0x30}, {104, 0x30}, {98, 0x30}, {110, 0x6}, {104, 0x6}, {98, 0x6}, {110, 0x5}, {104, 0x5}, {98, 0x5}, {110, 0x4}, {104, 0x4}, {98, 0x4}, {110, 0x3}, {104, 0x3}, {98, 0x3}, {110, 0x2}, {104, 0x2}, {98, 0x2}, {110, 0x1}, {104, 0x1}, {98, 0x1}, {110, 0x0}, {104, 0x0}, {98, 0x0}, {97, 0}, {96, 0}, {95, 0}, {94, 0}, {93, 0}, {92, 0}, {91, 0}, {90, 0}, {89, 0}, {88, 0}, {87, 0}, {86, 0}, {85, 0}, {84, 0}, {83, 0}, {82, 0}, {81, 0}, {80, 0}, {79, 0}, {78, 0}, {77, 0}, {76, 0}, {75, 0}, {74, 0}, {73, 0}, {72, 0}, {71, 0}, {70, 0}, {69, 0}, {68, 0}, {67, 0}, {66, 0}, {65, 0}, {64, 0}, {63, 0}, {62, 0}, {61, 0}, {60, 0}, {59, 0}, }};static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, u8 is_fat, u8 ctrl_chan_high, struct iwl_tx_power_db *tx_power_tbl){ u8 saturation_power; s32 target_power; s32 user_target_power; s32 power_limit; s32 current_temp; s32 reg_limit; s32 current_regulatory; s32 txatten_grp = CALIB_CH_GROUP_MAX; int i; int c; const struct iwl_channel_info *ch_info = NULL; struct iwl_eeprom_calib_ch_info ch_eeprom_info; const struct iwl_eeprom_calib_measure *measurement; s16 voltage; s32 init_voltage; s32 voltage_compensation; s32 degrees_per_05db_num; s32 degrees_per_05db_denom; s32 factory_temp; s32 temperature_comp[2]; s32 factory_gain_index[2]; s32 factory_actual_pwr[2]; s32 power_index; /* Sanity check requested level (dBm) */ if (priv->user_txpower_limit < IWL_TX_POWER_TARGET_POWER_MIN) { IWL_WARNING("Requested user TXPOWER %d below limit.\n", priv->user_txpower_limit); return -EINVAL; } if (priv->user_txpower_limit > IWL_TX_POWER_TARGET_POWER_MAX) { IWL_WARNING("Requested user TXPOWER %d above limit.\n", priv->user_txpower_limit); return -EINVAL; } /* user_txpower_limit is in dBm, convert to half-dBm (half-dB units * are used for indexing into txpower table) */ user_target_power = 2 * priv->user_txpower_limit; /* Get current (RXON) channel, band, width */ ch_info = iwl4965_get_channel_txpower_info(priv, priv->phymode, channel); IWL_DEBUG_TXPOWER("chan %d band %d is_fat %d\n", channel, band, is_fat); if (!ch_info) return -EINVAL; /* get txatten group, used to select 1) thermal txpower adjustment * and 2) mimo txpower balance between Tx chains. */ txatten_grp = iwl4965_get_tx_atten_grp(channel); if (txatten_grp < 0) return -EINVAL; IWL_DEBUG_TXPOWER("channel %d belongs to txatten group %d\n", channel, txatten_grp); if (is_fat) { if (ctrl_chan_high) channel -= 2; else channel += 2; } /* hardware txpower limits ... * saturation (clipping distortion) txpowers are in half-dBm */ if (band) saturation_power = priv->eeprom.calib_info.saturation_power24; else saturation_power = priv->eeprom.calib_info.saturation_power52; if (saturation_power < IWL_TX_POWER_SATURATION_MIN || saturation_power > IWL_TX_POWER_SATURATION_MAX) { if (band) saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_24; else saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_52; } /* regulatory txpower limits ... reg_limit values are in half-dBm, * max_power_avg values are in dBm, convert * 2 */ if (is_fat) reg_limit = ch_info->fat_max_power_avg * 2; else reg_limit = ch_info->max_power_avg * 2; if ((reg_limit < IWL_TX_POWER_REGULATORY_MIN) || (reg_limit > IWL_TX_POWER_REGULATORY_MAX)) { if (band) reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_24; else reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_52; } /* Interpolate txpower calibration values for this channel, * based on factory calibration tests on spaced channels. */ iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); /* calculate tx gain adjustment based on power supply voltage */ voltage = priv->eeprom.calib_info.voltage; init_vo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -