Files
rtl8189ES_linux/core/rtw_rf.c
Jens Rehsack 52ee638811 Initially import rtl8189ES linux driver v4.3.18.1
Since the driver itself is licensed under GPLv2+, we can manage it in public git repository

Signed-off-by: Jens Rehsack <sno@netbsd.org>
2015-10-06 17:58:21 +02:00

225 lines
5.2 KiB
C

/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _RTW_RF_C_
#include <drv_types.h>
#include <hal_data.h>
int rtw_ch2freq(int chan)
{
/* see 802.11 17.3.8.3.2 and Annex J
* there are overlapping channel numbers in 5GHz and 2GHz bands */
/*
* RTK: don't consider the overlapping channel numbers: 5G channel <= 14,
* because we don't support it. simply judge from channel number
*/
if (chan >= 1 && chan <= 14) {
if (chan == 14)
return 2484;
else if (chan < 14)
return 2407 + chan * 5;
} else if (chan >= 36 && chan <= 177) {
return 5000 + chan * 5;
}
return 0; /* not supported */
}
int rtw_freq2ch(int freq)
{
/* see 802.11 17.3.8.3.2 and Annex J */
if (freq == 2484)
return 14;
else if (freq < 2484)
return (freq - 2407) / 5;
else if (freq >= 4910 && freq <= 4980)
return (freq - 4000) / 5;
else if (freq <= 45000) /* DMG band lower limit */
return (freq - 5000) / 5;
else if (freq >= 58320 && freq <= 64800)
return (freq - 56160) / 2160;
else
return 0;
}
bool rtw_chbw_to_freq_range(u8 ch, u8 bw, u8 offset, u32 *hi, u32 *lo)
{
u8 c_ch;
u32 freq;
u32 hi_ret = 0, lo_ret = 0;
int i;
bool valid = _FALSE;
if (hi)
*hi = 0;
if (lo)
*lo = 0;
c_ch = rtw_get_center_ch(ch, bw, offset);
freq = rtw_ch2freq(c_ch);
if (!freq) {
rtw_warn_on(1);
goto exit;
}
if (bw == CHANNEL_WIDTH_80) {
hi_ret = freq + 40;
lo_ret = freq - 40;
} else if (bw == CHANNEL_WIDTH_40) {
hi_ret = freq + 20;
lo_ret = freq - 20;
} else if (bw == CHANNEL_WIDTH_20) {
hi_ret = freq + 10;
lo_ret = freq - 10;
} else {
rtw_warn_on(1);
}
if (hi)
*hi = hi_ret;
if (lo)
*lo = lo_ret;
valid = _TRUE;
exit:
return valid;
}
int rtw_ch_to_bb_gain_sel(int ch)
{
int sel = -1;
if (ch >= 1 && ch <= 14)
sel = BB_GAIN_2G;
#ifdef CONFIG_IEEE80211_BAND_5GHZ
else if (ch >= 36 && ch < 50)
sel = BB_GAIN_5GLB1;
else if (ch >= 50 && ch <= 64)
sel = BB_GAIN_5GLB2;
else if (ch >= 100 && ch <= 118)
sel = BB_GAIN_5GMB1;
else if (ch >= 120 && ch <= 140)
sel = BB_GAIN_5GMB2;
else if (ch >= 149 && ch <= 165)
sel = BB_GAIN_5GHB;
#endif
return sel;
}
s8 rtw_rf_get_kfree_tx_gain_offset(_adapter *padapter, u8 path, u8 ch)
{
s8 kfree_offset = 0;
#ifdef CONFIG_RF_GAIN_OFFSET
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
struct kfree_data_t *kfree_data = GET_KFREE_DATA(padapter);
s8 bb_gain_sel = rtw_ch_to_bb_gain_sel(ch);
if (bb_gain_sel < BB_GAIN_2G || bb_gain_sel >= BB_GAIN_NUM) {
rtw_warn_on(1);
goto exit;
}
if (kfree_data->flag & KFREE_FLAG_ON) {
kfree_offset = kfree_data->bb_gain[bb_gain_sel][path];
if (1)
DBG_871X("%s path:%u, ch:%u, bb_gain_sel:%d, kfree_offset:%d\n"
, __func__, path, ch, bb_gain_sel, kfree_offset);
}
exit:
#endif /* CONFIG_RF_GAIN_OFFSET */
return kfree_offset;
}
void rtw_rf_set_tx_gain_offset(_adapter *adapter, u8 path, s8 offset)
{
u8 write_value;
switch (rtw_get_chip_type(adapter)) {
#ifdef CONFIG_RTL8188F
case RTL8188F:
write_value = RF_TX_GAIN_OFFSET_8188F(offset);
rtw_hal_write_rfreg(adapter, path, 0x55, 0x0fc000, write_value);
break;
#endif /* CONFIG_RTL8188F */
#ifdef CONFIG_RTL8821A
case RTL8821:
write_value = RF_TX_GAIN_OFFSET_8821A(offset);
rtw_hal_write_rfreg(adapter, path, 0x55, 0x0f8000, write_value);
break;
#endif /* CONFIG_RTL8821A */
default:
rtw_warn_on(1);
break;
}
}
void rtw_rf_apply_tx_gain_offset(_adapter *adapter, u8 ch)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
s8 kfree_offset = 0;
s8 tx_pwr_track_offset = 0; /* TODO: 8814A should consider tx pwr track when setting tx gain offset */
s8 total_offset;
int i;
for (i = 0; i < hal_data->NumTotalRFPath; i++) {
kfree_offset = rtw_rf_get_kfree_tx_gain_offset(adapter, i, ch);
total_offset = kfree_offset + tx_pwr_track_offset;
rtw_rf_set_tx_gain_offset(adapter, i, total_offset);
}
}
bool rtw_is_dfs_range(u32 hi, u32 lo)
{
return rtw_is_range_overlap(hi, lo, 5720 + 10, 5260 - 10)?_TRUE:_FALSE;
}
bool rtw_is_dfs_ch(u8 ch, u8 bw, u8 offset)
{
u32 hi, lo;
if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)
return _FALSE;
return rtw_is_dfs_range(hi, lo)?_TRUE:_FALSE;
}
bool rtw_is_long_cac_range(u32 hi, u32 lo)
{
return rtw_is_range_overlap(hi, lo, 5660 + 10, 5600 - 10)?_TRUE:_FALSE;
}
bool rtw_is_long_cac_ch(u8 ch, u8 bw, u8 offset)
{
u32 hi, lo;
if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)
return _FALSE;
return rtw_is_long_cac_range(hi, lo)?_TRUE:_FALSE;
}