Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /* Copyright(c) 2018-2021  Realtek Corporation
0003  */
0004 
0005 #include "sar.h"
0006 #include "phy.h"
0007 #include "debug.h"
0008 
0009 s8 rtw_query_sar(struct rtw_dev *rtwdev, const struct rtw_sar_arg *arg)
0010 {
0011     const struct rtw_hal *hal = &rtwdev->hal;
0012     const struct rtw_sar *sar = &hal->sar;
0013 
0014     switch (sar->src) {
0015     default:
0016         rtw_warn(rtwdev, "unknown SAR source: %d\n", sar->src);
0017         fallthrough;
0018     case RTW_SAR_SOURCE_NONE:
0019         return (s8)rtwdev->chip->max_power_index;
0020     case RTW_SAR_SOURCE_COMMON:
0021         return sar->cfg[arg->path][arg->rs].common[arg->sar_band];
0022     }
0023 }
0024 
0025 static int rtw_apply_sar(struct rtw_dev *rtwdev, const struct rtw_sar *new)
0026 {
0027     struct rtw_hal *hal = &rtwdev->hal;
0028     struct rtw_sar *sar = &hal->sar;
0029 
0030     if (sar->src != RTW_SAR_SOURCE_NONE && new->src != sar->src) {
0031         rtw_warn(rtwdev, "SAR source: %d is in use\n", sar->src);
0032         return -EBUSY;
0033     }
0034 
0035     *sar = *new;
0036     rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
0037 
0038     return 0;
0039 }
0040 
0041 static s8 rtw_sar_to_phy(struct rtw_dev *rtwdev, u8 fct, s32 sar,
0042              const struct rtw_sar_arg *arg)
0043 {
0044     struct rtw_hal *hal = &rtwdev->hal;
0045     u8 txgi = rtwdev->chip->txgi_factor;
0046     u8 max = rtwdev->chip->max_power_index;
0047     s32 tmp;
0048     s8 base;
0049 
0050     tmp = fct > txgi ? sar >> (fct - txgi) : sar << (txgi - fct);
0051     base = arg->sar_band == RTW_SAR_BAND_0 ?
0052            hal->tx_pwr_by_rate_base_2g[arg->path][arg->rs] :
0053            hal->tx_pwr_by_rate_base_5g[arg->path][arg->rs];
0054 
0055     return (s8)clamp_t(s32, tmp, -max - 1, max) - base;
0056 }
0057 
0058 static const struct cfg80211_sar_freq_ranges rtw_common_sar_freq_ranges[] = {
0059     [RTW_SAR_BAND_0] = { .start_freq = 2412, .end_freq = 2484, },
0060     [RTW_SAR_BAND_1] = { .start_freq = 5180, .end_freq = 5320, },
0061     [RTW_SAR_BAND_3] = { .start_freq = 5500, .end_freq = 5720, },
0062     [RTW_SAR_BAND_4] = { .start_freq = 5745, .end_freq = 5825, },
0063 };
0064 
0065 static_assert(ARRAY_SIZE(rtw_common_sar_freq_ranges) == RTW_SAR_BAND_NR);
0066 
0067 const struct cfg80211_sar_capa rtw_sar_capa = {
0068     .type = NL80211_SAR_TYPE_POWER,
0069     .num_freq_ranges = RTW_SAR_BAND_NR,
0070     .freq_ranges = rtw_common_sar_freq_ranges,
0071 };
0072 
0073 int rtw_set_sar_specs(struct rtw_dev *rtwdev,
0074               const struct cfg80211_sar_specs *sar)
0075 {
0076     struct rtw_sar_arg arg = {0};
0077     struct rtw_sar new = {0};
0078     u32 idx, i, j, k;
0079     s32 power;
0080     s8 val;
0081 
0082     if (sar->type != NL80211_SAR_TYPE_POWER)
0083         return -EINVAL;
0084 
0085     memset(&new, rtwdev->chip->max_power_index, sizeof(new));
0086     new.src = RTW_SAR_SOURCE_COMMON;
0087 
0088     for (i = 0; i < sar->num_sub_specs; i++) {
0089         idx = sar->sub_specs[i].freq_range_index;
0090         if (idx >= RTW_SAR_BAND_NR)
0091             return -EINVAL;
0092 
0093         power = sar->sub_specs[i].power;
0094         rtw_dbg(rtwdev, RTW_DBG_REGD, "On freq %u to %u, set SAR %d in 1/%lu dBm\n",
0095             rtw_common_sar_freq_ranges[idx].start_freq,
0096             rtw_common_sar_freq_ranges[idx].end_freq,
0097             power, BIT(RTW_COMMON_SAR_FCT));
0098 
0099         for (j = 0; j < RTW_RF_PATH_MAX; j++) {
0100             for (k = 0; k < RTW_RATE_SECTION_MAX; k++) {
0101                 arg = (struct rtw_sar_arg){
0102                     .sar_band = idx,
0103                     .path = j,
0104                     .rs = k,
0105                 };
0106                 val = rtw_sar_to_phy(rtwdev, RTW_COMMON_SAR_FCT,
0107                              power, &arg);
0108                 new.cfg[j][k].common[idx] = val;
0109             }
0110         }
0111     }
0112 
0113     return rtw_apply_sar(rtwdev, &new);
0114 }