linux/drivers/staging/rtlwifi/phydm/phydm_acs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2016  Realtek Corporation.
   5 *
   6 * Contact Information:
   7 * wlanfae <wlanfae@realtek.com>
   8 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
   9 * Hsinchu 300, Taiwan.
  10 *
  11 * Larry Finger <Larry.Finger@lwfinger.net>
  12 *
  13 *****************************************************************************/
  14
  15/* ************************************************************
  16 * include files
  17 * *************************************************************/
  18#include "mp_precomp.h"
  19#include "phydm_precomp.h"
  20
  21u8 odm_get_auto_channel_select_result(void *dm_void, u8 band)
  22{
  23        struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
  24        struct acs_info *acs = &dm->dm_acs;
  25        u8 result;
  26
  27        if (band == ODM_BAND_2_4G) {
  28                ODM_RT_TRACE(
  29                        dm, ODM_COMP_ACS,
  30                        "[struct acs_info] %s(): clean_channel_2g(%d)\n",
  31                        __func__, acs->clean_channel_2g);
  32                result = (u8)acs->clean_channel_2g;
  33        } else {
  34                ODM_RT_TRACE(
  35                        dm, ODM_COMP_ACS,
  36                        "[struct acs_info] %s(): clean_channel_5g(%d)\n",
  37                        __func__, acs->clean_channel_5g);
  38                result = (u8)acs->clean_channel_5g;
  39        }
  40
  41        return result;
  42}
  43
  44static void odm_auto_channel_select_setting(void *dm_void, bool is_enable)
  45{
  46        struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
  47        u16 period = 0x2710; /* 40ms in default */
  48        u16 nhm_type = 0x7;
  49
  50        ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s()=========>\n", __func__);
  51
  52        if (is_enable) {
  53                /* 20 ms */
  54                period = 0x1388;
  55                nhm_type = 0x1;
  56        }
  57
  58        if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  59                /* PHY parameters initialize for ac series */
  60
  61                /* 0x990[31:16]=0x2710
  62                 * Time duration for NHM unit: 4us, 0x2710=40ms
  63                 */
  64                odm_write_2byte(dm, ODM_REG_CCX_PERIOD_11AC + 2, period);
  65        } else if (dm->support_ic_type & ODM_IC_11N_SERIES) {
  66                /* PHY parameters initialize for n series */
  67
  68                /* 0x894[31:16]=0x2710
  69                 * Time duration for NHM unit: 4us, 0x2710=40ms
  70                 */
  71                odm_write_2byte(dm, ODM_REG_CCX_PERIOD_11N + 2, period);
  72        }
  73}
  74
  75void odm_auto_channel_select_init(void *dm_void)
  76{
  77        struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
  78        struct acs_info *acs = &dm->dm_acs;
  79        u8 i;
  80
  81        if (!(dm->support_ability & ODM_BB_NHM_CNT))
  82                return;
  83
  84        if (acs->is_force_acs_result)
  85                return;
  86
  87        ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s()=========>\n", __func__);
  88
  89        acs->clean_channel_2g = 1;
  90        acs->clean_channel_5g = 36;
  91
  92        for (i = 0; i < ODM_MAX_CHANNEL_2G; ++i) {
  93                acs->channel_info_2g[0][i] = 0;
  94                acs->channel_info_2g[1][i] = 0;
  95        }
  96
  97        if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  98                for (i = 0; i < ODM_MAX_CHANNEL_5G; ++i) {
  99                        acs->channel_info_5g[0][i] = 0;
 100                        acs->channel_info_5g[1][i] = 0;
 101                }
 102        }
 103}
 104
 105void odm_auto_channel_select_reset(void *dm_void)
 106{
 107        struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
 108        struct acs_info *acs = &dm->dm_acs;
 109
 110        if (!(dm->support_ability & ODM_BB_NHM_CNT))
 111                return;
 112
 113        if (acs->is_force_acs_result)
 114                return;
 115
 116        ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s()=========>\n", __func__);
 117
 118        odm_auto_channel_select_setting(dm, true); /* for 20ms measurement */
 119        phydm_nhm_counter_statistics_reset(dm);
 120}
 121
 122void odm_auto_channel_select(void *dm_void, u8 channel)
 123{
 124        struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
 125        struct acs_info *acs = &dm->dm_acs;
 126        u8 channel_idx = 0, search_idx = 0;
 127        u16 max_score = 0;
 128
 129        if (!(dm->support_ability & ODM_BB_NHM_CNT)) {
 130                ODM_RT_TRACE(
 131                        dm, ODM_COMP_DIG,
 132                        "%s(): Return: support_ability ODM_BB_NHM_CNT is disabled\n",
 133                        __func__);
 134                return;
 135        }
 136
 137        if (acs->is_force_acs_result) {
 138                ODM_RT_TRACE(
 139                        dm, ODM_COMP_DIG,
 140                        "%s(): Force 2G clean channel = %d, 5G clean channel = %d\n",
 141                        __func__, acs->clean_channel_2g, acs->clean_channel_5g);
 142                return;
 143        }
 144
 145        ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s(): channel = %d=========>\n",
 146                     __func__, channel);
 147
 148        phydm_get_nhm_counter_statistics(dm);
 149        odm_auto_channel_select_setting(dm, false);
 150
 151        if (channel >= 1 && channel <= 14) {
 152                channel_idx = channel - 1;
 153                acs->channel_info_2g[1][channel_idx]++;
 154
 155                if (acs->channel_info_2g[1][channel_idx] >= 2)
 156                        acs->channel_info_2g[0][channel_idx] =
 157                                (acs->channel_info_2g[0][channel_idx] >> 1) +
 158                                (acs->channel_info_2g[0][channel_idx] >> 2) +
 159                                (dm->nhm_cnt_0 >> 2);
 160                else
 161                        acs->channel_info_2g[0][channel_idx] = dm->nhm_cnt_0;
 162
 163                ODM_RT_TRACE(dm, ODM_COMP_ACS, "%s(): nhm_cnt_0 = %d\n",
 164                             __func__, dm->nhm_cnt_0);
 165                ODM_RT_TRACE(
 166                        dm, ODM_COMP_ACS,
 167                        "%s(): Channel_Info[0][%d] = %d, Channel_Info[1][%d] = %d\n",
 168                        __func__, channel_idx,
 169                        acs->channel_info_2g[0][channel_idx], channel_idx,
 170                        acs->channel_info_2g[1][channel_idx]);
 171
 172                for (search_idx = 0; search_idx < ODM_MAX_CHANNEL_2G;
 173                     search_idx++) {
 174                        if (acs->channel_info_2g[1][search_idx] != 0 &&
 175                            acs->channel_info_2g[0][search_idx] >= max_score) {
 176                                max_score = acs->channel_info_2g[0][search_idx];
 177                                acs->clean_channel_2g = search_idx + 1;
 178                        }
 179                }
 180                ODM_RT_TRACE(
 181                        dm, ODM_COMP_ACS,
 182                        "(1)%s(): 2G: clean_channel_2g = %d, max_score = %d\n",
 183                        __func__, acs->clean_channel_2g, max_score);
 184
 185        } else if (channel >= 36) {
 186                /* Need to do */
 187                acs->clean_channel_5g = channel;
 188        }
 189}
 190