Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /* Copyright(c) 2019-2020  Realtek Corporation
0003  */
0004 
0005 #include "debug.h"
0006 #include "sar.h"
0007 
0008 static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev,
0009                             u32 center_freq)
0010 {
0011     switch (center_freq) {
0012     default:
0013         rtw89_debug(rtwdev, RTW89_DBG_SAR,
0014                 "center freq: %u to SAR subband is unhandled\n",
0015                 center_freq);
0016         fallthrough;
0017     case 2412 ... 2484:
0018         return RTW89_SAR_2GHZ_SUBBAND;
0019     case 5180 ... 5320:
0020         return RTW89_SAR_5GHZ_SUBBAND_1_2;
0021     case 5500 ... 5720:
0022         return RTW89_SAR_5GHZ_SUBBAND_2_E;
0023     case 5745 ... 5825:
0024         return RTW89_SAR_5GHZ_SUBBAND_3;
0025     case 5955 ... 6155:
0026         return RTW89_SAR_6GHZ_SUBBAND_5_L;
0027     case 6175 ... 6415:
0028         return RTW89_SAR_6GHZ_SUBBAND_5_H;
0029     case 6435 ... 6515:
0030         return RTW89_SAR_6GHZ_SUBBAND_6;
0031     case 6535 ... 6695:
0032         return RTW89_SAR_6GHZ_SUBBAND_7_L;
0033     case 6715 ... 6855:
0034         return RTW89_SAR_6GHZ_SUBBAND_7_H;
0035 
0036     /* freq 6875 (ch 185, 20MHz) spans RTW89_SAR_6GHZ_SUBBAND_7_H
0037      * and RTW89_SAR_6GHZ_SUBBAND_8, so directly describe it with
0038      * struct rtw89_sar_span in the following.
0039      */
0040 
0041     case 6895 ... 7115:
0042         return RTW89_SAR_6GHZ_SUBBAND_8;
0043     }
0044 }
0045 
0046 struct rtw89_sar_span {
0047     enum rtw89_sar_subband subband_low;
0048     enum rtw89_sar_subband subband_high;
0049 };
0050 
0051 #define RTW89_SAR_SPAN_VALID(span) ((span)->subband_high)
0052 
0053 #define RTW89_SAR_6GHZ_SPAN_HEAD 6145
0054 #define RTW89_SAR_6GHZ_SPAN_IDX(center_freq) \
0055     ((((int)(center_freq) - RTW89_SAR_6GHZ_SPAN_HEAD) / 5) / 2)
0056 
0057 #define RTW89_DECL_SAR_6GHZ_SPAN(center_freq, subband_l, subband_h) \
0058     [RTW89_SAR_6GHZ_SPAN_IDX(center_freq)] = { \
0059         .subband_low = RTW89_SAR_6GHZ_ ## subband_l, \
0060         .subband_high = RTW89_SAR_6GHZ_ ## subband_h, \
0061     }
0062 
0063 /* Since 6GHz SAR subbands are not edge aligned, some cases span two SAR
0064  * subbands. In the following, we describe each of them with rtw89_sar_span.
0065  */
0066 static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = {
0067     RTW89_DECL_SAR_6GHZ_SPAN(6145, SUBBAND_5_L, SUBBAND_5_H),
0068     RTW89_DECL_SAR_6GHZ_SPAN(6165, SUBBAND_5_L, SUBBAND_5_H),
0069     RTW89_DECL_SAR_6GHZ_SPAN(6185, SUBBAND_5_L, SUBBAND_5_H),
0070     RTW89_DECL_SAR_6GHZ_SPAN(6505, SUBBAND_6, SUBBAND_7_L),
0071     RTW89_DECL_SAR_6GHZ_SPAN(6525, SUBBAND_6, SUBBAND_7_L),
0072     RTW89_DECL_SAR_6GHZ_SPAN(6545, SUBBAND_6, SUBBAND_7_L),
0073     RTW89_DECL_SAR_6GHZ_SPAN(6665, SUBBAND_7_L, SUBBAND_7_H),
0074     RTW89_DECL_SAR_6GHZ_SPAN(6705, SUBBAND_7_L, SUBBAND_7_H),
0075     RTW89_DECL_SAR_6GHZ_SPAN(6825, SUBBAND_7_H, SUBBAND_8),
0076     RTW89_DECL_SAR_6GHZ_SPAN(6865, SUBBAND_7_H, SUBBAND_8),
0077     RTW89_DECL_SAR_6GHZ_SPAN(6875, SUBBAND_7_H, SUBBAND_8),
0078     RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8),
0079 };
0080 
0081 static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg)
0082 {
0083     struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common;
0084     struct rtw89_hal *hal = &rtwdev->hal;
0085     enum rtw89_band band = hal->current_band_type;
0086     u32 center_freq = hal->current_freq;
0087     const struct rtw89_sar_span *span = NULL;
0088     enum rtw89_sar_subband subband_l, subband_h;
0089     int idx;
0090 
0091     if (band == RTW89_BAND_6G) {
0092         idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq);
0093         /* To decrease size of rtw89_sar_overlapping_6ghz[],
0094          * RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs
0095          * to make first span as index 0 of the table. So, if center
0096          * frequency is less than the first one, it will get netative.
0097          */
0098         if (idx >= 0 && idx < ARRAY_SIZE(rtw89_sar_overlapping_6ghz))
0099             span = &rtw89_sar_overlapping_6ghz[idx];
0100     }
0101 
0102     if (span && RTW89_SAR_SPAN_VALID(span)) {
0103         subband_l = span->subband_low;
0104         subband_h = span->subband_high;
0105     } else {
0106         subband_l = rtw89_sar_get_subband(rtwdev, center_freq);
0107         subband_h = subband_l;
0108     }
0109 
0110     rtw89_debug(rtwdev, RTW89_DBG_SAR,
0111             "for {band %u, center_freq %u}, SAR subband: {%u, %u}\n",
0112             band, center_freq, subband_l, subband_h);
0113 
0114     if (!rtwsar->set[subband_l] && !rtwsar->set[subband_h])
0115         return -ENODATA;
0116 
0117     if (!rtwsar->set[subband_l])
0118         *cfg = rtwsar->cfg[subband_h];
0119     else if (!rtwsar->set[subband_h])
0120         *cfg = rtwsar->cfg[subband_l];
0121     else
0122         *cfg = min(rtwsar->cfg[subband_l], rtwsar->cfg[subband_h]);
0123 
0124     return 0;
0125 }
0126 
0127 static const
0128 struct rtw89_sar_handler rtw89_sar_handlers[RTW89_SAR_SOURCE_NR] = {
0129     [RTW89_SAR_SOURCE_COMMON] = {
0130         .descr_sar_source = "RTW89_SAR_SOURCE_COMMON",
0131         .txpwr_factor_sar = 2,
0132         .query_sar_config = rtw89_query_sar_config_common,
0133     },
0134 };
0135 
0136 #define rtw89_sar_set_src(_dev, _src, _cfg_name, _cfg_data)     \
0137     do {                                \
0138         typeof(_src) _s = (_src);               \
0139         typeof(_dev) _d = (_dev);               \
0140         BUILD_BUG_ON(!rtw89_sar_handlers[_s].descr_sar_source); \
0141         BUILD_BUG_ON(!rtw89_sar_handlers[_s].query_sar_config); \
0142         lockdep_assert_held(&_d->mutex);            \
0143         _d->sar._cfg_name = *(_cfg_data);           \
0144         _d->sar.src = _s;                   \
0145     } while (0)
0146 
0147 static s8 rtw89_txpwr_sar_to_mac(struct rtw89_dev *rtwdev, u8 fct, s32 cfg)
0148 {
0149     const u8 fct_mac = rtwdev->chip->txpwr_factor_mac;
0150     s32 cfg_mac;
0151 
0152     cfg_mac = fct > fct_mac ?
0153           cfg >> (fct - fct_mac) : cfg << (fct_mac - fct);
0154 
0155     return (s8)clamp_t(s32, cfg_mac,
0156                RTW89_SAR_TXPWR_MAC_MIN,
0157                RTW89_SAR_TXPWR_MAC_MAX);
0158 }
0159 
0160 s8 rtw89_query_sar(struct rtw89_dev *rtwdev)
0161 {
0162     const enum rtw89_sar_sources src = rtwdev->sar.src;
0163     /* its members are protected by rtw89_sar_set_src() */
0164     const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src];
0165     int ret;
0166     s32 cfg;
0167     u8 fct;
0168 
0169     lockdep_assert_held(&rtwdev->mutex);
0170 
0171     if (src == RTW89_SAR_SOURCE_NONE)
0172         return RTW89_SAR_TXPWR_MAC_MAX;
0173 
0174     ret = sar_hdl->query_sar_config(rtwdev, &cfg);
0175     if (ret)
0176         return RTW89_SAR_TXPWR_MAC_MAX;
0177 
0178     fct = sar_hdl->txpwr_factor_sar;
0179 
0180     return rtw89_txpwr_sar_to_mac(rtwdev, fct, cfg);
0181 }
0182 
0183 void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev)
0184 {
0185     const enum rtw89_sar_sources src = rtwdev->sar.src;
0186     /* its members are protected by rtw89_sar_set_src() */
0187     const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src];
0188     const u8 fct_mac = rtwdev->chip->txpwr_factor_mac;
0189     int ret;
0190     s32 cfg;
0191     u8 fct;
0192 
0193     lockdep_assert_held(&rtwdev->mutex);
0194 
0195     if (src == RTW89_SAR_SOURCE_NONE) {
0196         seq_puts(m, "no SAR is applied\n");
0197         return;
0198     }
0199 
0200     seq_printf(m, "source: %d (%s)\n", src, sar_hdl->descr_sar_source);
0201 
0202     ret = sar_hdl->query_sar_config(rtwdev, &cfg);
0203     if (ret) {
0204         seq_printf(m, "config: return code: %d\n", ret);
0205         seq_printf(m, "assign: max setting: %d (unit: 1/%lu dBm)\n",
0206                RTW89_SAR_TXPWR_MAC_MAX, BIT(fct_mac));
0207         return;
0208     }
0209 
0210     fct = sar_hdl->txpwr_factor_sar;
0211 
0212     seq_printf(m, "config: %d (unit: 1/%lu dBm)\n", cfg, BIT(fct));
0213 }
0214 
0215 static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev,
0216                   const struct rtw89_sar_cfg_common *sar)
0217 {
0218     enum rtw89_sar_sources src;
0219     int ret = 0;
0220 
0221     mutex_lock(&rtwdev->mutex);
0222 
0223     src = rtwdev->sar.src;
0224     if (src != RTW89_SAR_SOURCE_NONE && src != RTW89_SAR_SOURCE_COMMON) {
0225         rtw89_warn(rtwdev, "SAR source: %d is in use", src);
0226         ret = -EBUSY;
0227         goto exit;
0228     }
0229 
0230     rtw89_sar_set_src(rtwdev, RTW89_SAR_SOURCE_COMMON, cfg_common, sar);
0231     rtw89_chip_set_txpwr(rtwdev);
0232 
0233 exit:
0234     mutex_unlock(&rtwdev->mutex);
0235     return ret;
0236 }
0237 
0238 static const struct cfg80211_sar_freq_ranges rtw89_common_sar_freq_ranges[] = {
0239     { .start_freq = 2412, .end_freq = 2484, },
0240     { .start_freq = 5180, .end_freq = 5320, },
0241     { .start_freq = 5500, .end_freq = 5720, },
0242     { .start_freq = 5745, .end_freq = 5825, },
0243     { .start_freq = 5955, .end_freq = 6155, },
0244     { .start_freq = 6175, .end_freq = 6415, },
0245     { .start_freq = 6435, .end_freq = 6515, },
0246     { .start_freq = 6535, .end_freq = 6695, },
0247     { .start_freq = 6715, .end_freq = 6875, },
0248     { .start_freq = 6875, .end_freq = 7115, },
0249 };
0250 
0251 static_assert(RTW89_SAR_SUBBAND_NR ==
0252           ARRAY_SIZE(rtw89_common_sar_freq_ranges));
0253 
0254 const struct cfg80211_sar_capa rtw89_sar_capa = {
0255     .type = NL80211_SAR_TYPE_POWER,
0256     .num_freq_ranges = ARRAY_SIZE(rtw89_common_sar_freq_ranges),
0257     .freq_ranges = rtw89_common_sar_freq_ranges,
0258 };
0259 
0260 int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
0261                 const struct cfg80211_sar_specs *sar)
0262 {
0263     struct rtw89_dev *rtwdev = hw->priv;
0264     struct rtw89_sar_cfg_common sar_common = {0};
0265     u8 fct;
0266     u32 freq_start;
0267     u32 freq_end;
0268     s32 power;
0269     u32 i, idx;
0270 
0271     if (sar->type != NL80211_SAR_TYPE_POWER)
0272         return -EINVAL;
0273 
0274     fct = rtw89_sar_handlers[RTW89_SAR_SOURCE_COMMON].txpwr_factor_sar;
0275 
0276     for (i = 0; i < sar->num_sub_specs; i++) {
0277         idx = sar->sub_specs[i].freq_range_index;
0278         if (idx >= ARRAY_SIZE(rtw89_common_sar_freq_ranges))
0279             return -EINVAL;
0280 
0281         freq_start = rtw89_common_sar_freq_ranges[idx].start_freq;
0282         freq_end = rtw89_common_sar_freq_ranges[idx].end_freq;
0283         power = sar->sub_specs[i].power;
0284 
0285         rtw89_debug(rtwdev, RTW89_DBG_SAR,
0286                 "On freq %u to %u, set SAR limit %d (unit: 1/%lu dBm)\n",
0287                 freq_start, freq_end, power, BIT(fct));
0288 
0289         sar_common.set[idx] = true;
0290         sar_common.cfg[idx] = power;
0291     }
0292 
0293     return rtw89_apply_sar_common(rtwdev, &sar_common);
0294 }