diff options
Diffstat (limited to 'drivers/staging/rtlwifi/phydm/phydm_acs.c')
-rw-r--r-- | drivers/staging/rtlwifi/phydm/phydm_acs.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/drivers/staging/rtlwifi/phydm/phydm_acs.c b/drivers/staging/rtlwifi/phydm/phydm_acs.c new file mode 100644 index 000000000000..eae5a0a24b9b --- /dev/null +++ b/drivers/staging/rtlwifi/phydm/phydm_acs.c @@ -0,0 +1,200 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +/* ************************************************************ + * include files + * *************************************************************/ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +u8 odm_get_auto_channel_select_result(void *dm_void, u8 band) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct acs_info *acs = &dm->dm_acs; + u8 result; + + if (band == ODM_BAND_2_4G) { + ODM_RT_TRACE( + dm, ODM_COMP_ACS, + "[struct acs_info] %s(): clean_channel_2g(%d)\n", + __func__, acs->clean_channel_2g); + result = (u8)acs->clean_channel_2g; + } else { + ODM_RT_TRACE( + dm, ODM_COMP_ACS, + "[struct acs_info] %s(): clean_channel_5g(%d)\n", + __func__, acs->clean_channel_5g); + result = (u8)acs->clean_channel_5g; + } + + return result; +} + +static void odm_auto_channel_select_setting(void *dm_void, bool is_enable) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + u16 period = 0x2710; /* 40ms in default */ + u16 nhm_type = 0x7; + + ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s()=========>\n", __func__); + + if (is_enable) { + /* 20 ms */ + period = 0x1388; + nhm_type = 0x1; + } + + if (dm->support_ic_type & ODM_IC_11AC_SERIES) { + /* PHY parameters initialize for ac series */ + + /* 0x990[31:16]=0x2710 + * Time duration for NHM unit: 4us, 0x2710=40ms + */ + odm_write_2byte(dm, ODM_REG_CCX_PERIOD_11AC + 2, period); + } else if (dm->support_ic_type & ODM_IC_11N_SERIES) { + /* PHY parameters initialize for n series */ + + /* 0x894[31:16]=0x2710 + * Time duration for NHM unit: 4us, 0x2710=40ms + */ + odm_write_2byte(dm, ODM_REG_CCX_PERIOD_11N + 2, period); + } +} + +void odm_auto_channel_select_init(void *dm_void) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct acs_info *acs = &dm->dm_acs; + u8 i; + + if (!(dm->support_ability & ODM_BB_NHM_CNT)) + return; + + if (acs->is_force_acs_result) + return; + + ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s()=========>\n", __func__); + + acs->clean_channel_2g = 1; + acs->clean_channel_5g = 36; + + for (i = 0; i < ODM_MAX_CHANNEL_2G; ++i) { + acs->channel_info_2g[0][i] = 0; + acs->channel_info_2g[1][i] = 0; + } + + if (dm->support_ic_type & ODM_IC_11AC_SERIES) { + for (i = 0; i < ODM_MAX_CHANNEL_5G; ++i) { + acs->channel_info_5g[0][i] = 0; + acs->channel_info_5g[1][i] = 0; + } + } +} + +void odm_auto_channel_select_reset(void *dm_void) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct acs_info *acs = &dm->dm_acs; + + if (!(dm->support_ability & ODM_BB_NHM_CNT)) + return; + + if (acs->is_force_acs_result) + return; + + ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s()=========>\n", __func__); + + odm_auto_channel_select_setting(dm, true); /* for 20ms measurement */ + phydm_nhm_counter_statistics_reset(dm); +} + +void odm_auto_channel_select(void *dm_void, u8 channel) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct acs_info *acs = &dm->dm_acs; + u8 channel_idx = 0, search_idx = 0; + u16 max_score = 0; + + if (!(dm->support_ability & ODM_BB_NHM_CNT)) { + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): Return: support_ability ODM_BB_NHM_CNT is disabled\n", + __func__); + return; + } + + if (acs->is_force_acs_result) { + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): Force 2G clean channel = %d, 5G clean channel = %d\n", + __func__, acs->clean_channel_2g, acs->clean_channel_5g); + return; + } + + ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s(): channel = %d=========>\n", + __func__, channel); + + phydm_get_nhm_counter_statistics(dm); + odm_auto_channel_select_setting(dm, false); + + if (channel >= 1 && channel <= 14) { + channel_idx = channel - 1; + acs->channel_info_2g[1][channel_idx]++; + + if (acs->channel_info_2g[1][channel_idx] >= 2) + acs->channel_info_2g[0][channel_idx] = + (acs->channel_info_2g[0][channel_idx] >> 1) + + (acs->channel_info_2g[0][channel_idx] >> 2) + + (dm->nhm_cnt_0 >> 2); + else + acs->channel_info_2g[0][channel_idx] = dm->nhm_cnt_0; + + ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s(): nhm_cnt_0 = %d\n", + __func__, dm->nhm_cnt_0); + ODM_RT_TRACE( + dm, ODM_COMP_ACS, + "%s(): Channel_Info[0][%d] = %d, Channel_Info[1][%d] = %d\n", + __func__, channel_idx, + acs->channel_info_2g[0][channel_idx], channel_idx, + acs->channel_info_2g[1][channel_idx]); + + for (search_idx = 0; search_idx < ODM_MAX_CHANNEL_2G; + search_idx++) { + if (acs->channel_info_2g[1][search_idx] != 0 && + acs->channel_info_2g[0][search_idx] >= max_score) { + max_score = acs->channel_info_2g[0][search_idx]; + acs->clean_channel_2g = search_idx + 1; + } + } + ODM_RT_TRACE( + dm, ODM_COMP_ACS, + "(1)%s(): 2G: clean_channel_2g = %d, max_score = %d\n", + __func__, acs->clean_channel_2g, max_score); + + } else if (channel >= 36) { + /* Need to do */ + acs->clean_channel_5g = channel; + } +} |