0001
0002
0003
0004 #include <linux/acpi.h>
0005 #include "mt7921.h"
0006
0007 static int
0008 mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len)
0009 {
0010 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
0011 union acpi_object *sar_root, *sar_unit;
0012 struct mt76_dev *mdev = &dev->mt76;
0013 acpi_handle root, handle;
0014 acpi_status status;
0015 u32 i = 0;
0016
0017 root = ACPI_HANDLE(mdev->dev);
0018 if (!root)
0019 return -EOPNOTSUPP;
0020
0021 status = acpi_get_handle(root, method, &handle);
0022 if (ACPI_FAILURE(status))
0023 return -EIO;
0024
0025 status = acpi_evaluate_object(handle, NULL, NULL, &buf);
0026 if (ACPI_FAILURE(status))
0027 return -EIO;
0028
0029 sar_root = buf.pointer;
0030 if (sar_root->type != ACPI_TYPE_PACKAGE ||
0031 sar_root->package.count < 4 ||
0032 sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) {
0033 dev_err(mdev->dev, "sar cnt = %d\n",
0034 sar_root->package.count);
0035 goto free;
0036 }
0037
0038 if (!*tbl) {
0039 *tbl = devm_kzalloc(mdev->dev, sar_root->package.count,
0040 GFP_KERNEL);
0041 if (!*tbl)
0042 goto free;
0043 }
0044 if (len)
0045 *len = sar_root->package.count;
0046
0047 for (i = 0; i < sar_root->package.count; i++) {
0048 sar_unit = &sar_root->package.elements[i];
0049
0050 if (sar_unit->type != ACPI_TYPE_INTEGER)
0051 break;
0052 *(*tbl + i) = (u8)sar_unit->integer.value;
0053 }
0054 free:
0055 kfree(sar_root);
0056
0057 return (i == sar_root->package.count) ? 0 : -EINVAL;
0058 }
0059
0060
0061 static int
0062 mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version)
0063 {
0064 *version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0)
0065 ? 1 : 2;
0066 return 0;
0067 }
0068
0069
0070 static int
0071 mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version)
0072 {
0073 int len, ret, sarlen, prelen, tblcnt;
0074 bool enable;
0075
0076 ret = mt7921_acpi_read(dev, MT7921_ACPI_MTDS, table, &len);
0077 if (ret)
0078 return ret;
0079
0080
0081 switch (version) {
0082 case 1:
0083 enable = ((struct mt7921_asar_dyn *)*table)->enable;
0084 sarlen = sizeof(struct mt7921_asar_dyn_limit);
0085 prelen = sizeof(struct mt7921_asar_dyn);
0086 break;
0087 case 2:
0088 enable = ((struct mt7921_asar_dyn_v2 *)*table)->enable;
0089 sarlen = sizeof(struct mt7921_asar_dyn_limit_v2);
0090 prelen = sizeof(struct mt7921_asar_dyn_v2);
0091 break;
0092 default:
0093 return -EINVAL;
0094 }
0095
0096 tblcnt = (len - prelen) / sarlen;
0097 if (!enable ||
0098 tblcnt > MT7921_ASAR_MAX_DYN || tblcnt < MT7921_ASAR_MIN_DYN)
0099 ret = -EINVAL;
0100
0101 return ret;
0102 }
0103
0104
0105 static int
0106 mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version)
0107 {
0108 int len, ret = 0, sarlen, prelen, tblcnt;
0109
0110 ret = mt7921_acpi_read(dev, MT7921_ACPI_MTGS, table, &len);
0111 if (ret)
0112 return ret;
0113
0114
0115 switch (version) {
0116 case 1:
0117 sarlen = sizeof(struct mt7921_asar_geo_limit);
0118 prelen = sizeof(struct mt7921_asar_geo);
0119 break;
0120 case 2:
0121 sarlen = sizeof(struct mt7921_asar_geo_limit_v2);
0122 prelen = sizeof(struct mt7921_asar_geo_v2);
0123 break;
0124 default:
0125 return -EINVAL;
0126 }
0127
0128 tblcnt = (len - prelen) / sarlen;
0129 if (tblcnt > MT7921_ASAR_MAX_GEO || tblcnt < MT7921_ASAR_MIN_GEO)
0130 ret = -EINVAL;
0131
0132 return ret;
0133 }
0134
0135 int mt7921_init_acpi_sar(struct mt7921_dev *dev)
0136 {
0137 struct mt7921_acpi_sar *asar;
0138 int ret;
0139
0140 asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL);
0141 if (!asar)
0142 return -ENOMEM;
0143
0144 mt7921_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
0145
0146
0147 ret = mt7921_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
0148 if (ret) {
0149 devm_kfree(dev->mt76.dev, asar->dyn);
0150 devm_kfree(dev->mt76.dev, asar->countrylist);
0151 devm_kfree(dev->mt76.dev, asar);
0152 return ret;
0153 }
0154
0155
0156 ret = mt7921_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
0157 if (ret) {
0158 devm_kfree(dev->mt76.dev, asar->geo);
0159 asar->geo = NULL;
0160 }
0161
0162 dev->phy.acpisar = asar;
0163
0164 return 0;
0165 }
0166
0167 static s8
0168 mt7921_asar_get_geo_pwr(struct mt7921_phy *phy,
0169 enum nl80211_band band, s8 dyn_power)
0170 {
0171 struct mt7921_acpi_sar *asar = phy->acpisar;
0172 struct mt7921_asar_geo_band *band_pwr;
0173 s8 geo_power;
0174 u8 idx, max;
0175
0176 if (!asar->geo)
0177 return dyn_power;
0178
0179 switch (phy->mt76->dev->region) {
0180 case NL80211_DFS_FCC:
0181 idx = 0;
0182 break;
0183 case NL80211_DFS_ETSI:
0184 idx = 1;
0185 break;
0186 default:
0187 idx = 2;
0188 break;
0189 }
0190
0191 if (asar->ver == 1) {
0192 band_pwr = &asar->geo->tbl[idx].band[0];
0193 max = ARRAY_SIZE(asar->geo->tbl[idx].band);
0194 } else {
0195 band_pwr = &asar->geo_v2->tbl[idx].band[0];
0196 max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band);
0197 }
0198
0199 switch (band) {
0200 case NL80211_BAND_2GHZ:
0201 idx = 0;
0202 break;
0203 case NL80211_BAND_5GHZ:
0204 idx = 1;
0205 break;
0206 case NL80211_BAND_6GHZ:
0207 idx = 2;
0208 break;
0209 default:
0210 return dyn_power;
0211 }
0212
0213 if (idx >= max)
0214 return dyn_power;
0215
0216 geo_power = (band_pwr + idx)->pwr;
0217 dyn_power += (band_pwr + idx)->offset;
0218
0219 return min(geo_power, dyn_power);
0220 }
0221
0222 static s8
0223 mt7921_asar_range_pwr(struct mt7921_phy *phy,
0224 const struct cfg80211_sar_freq_ranges *range,
0225 u8 idx)
0226 {
0227 const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
0228 struct mt7921_acpi_sar *asar = phy->acpisar;
0229 u8 *limit, band, max;
0230
0231 if (!capa)
0232 return 127;
0233
0234 if (asar->ver == 1) {
0235 limit = &asar->dyn->tbl[0].frp[0];
0236 max = ARRAY_SIZE(asar->dyn->tbl[0].frp);
0237 } else {
0238 limit = &asar->dyn_v2->tbl[0].frp[0];
0239 max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp);
0240 }
0241
0242 if (idx >= max)
0243 return 127;
0244
0245 if (range->start_freq >= 5945)
0246 band = NL80211_BAND_6GHZ;
0247 else if (range->start_freq >= 5150)
0248 band = NL80211_BAND_5GHZ;
0249 else
0250 band = NL80211_BAND_2GHZ;
0251
0252 return mt7921_asar_get_geo_pwr(phy, band, limit[idx]);
0253 }
0254
0255 int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
0256 {
0257 const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
0258 int i;
0259
0260 if (!phy->acpisar)
0261 return 0;
0262
0263
0264
0265
0266
0267 for (i = 0; i < capa->num_freq_ranges; i++) {
0268 struct mt76_freq_range_power *frp = &phy->mt76->frp[i];
0269
0270 frp->range = set_default ? &capa->freq_ranges[i] : frp->range;
0271 if (!frp->range)
0272 continue;
0273
0274 frp->power = min_t(s8, set_default ? 127 : frp->power,
0275 mt7921_asar_range_pwr(phy, frp->range, i));
0276 }
0277
0278 return 0;
0279 }