drm: bridge: adv7511: remove s32 format from i2s capabilities
[drm/drm-misc.git] / drivers / net / wireless / mediatek / mt76 / mt792x_acpi_sar.c
blob9317f8ff2070fda56ebcfbd8677ed4aff8ebdcb3
1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2023 MediaTek Inc. */
4 #include <linux/acpi.h>
5 #include "mt792x.h"
7 static int
8 mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
10 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
11 struct mt76_dev *mdev = &dev->mt76;
12 union acpi_object *sar_root;
13 acpi_handle root, handle;
14 acpi_status status;
15 u32 i = 0;
16 int ret;
18 root = ACPI_HANDLE(mdev->dev);
19 if (!root)
20 return -EOPNOTSUPP;
22 status = acpi_get_handle(root, method, &handle);
23 if (ACPI_FAILURE(status))
24 return -EIO;
26 status = acpi_evaluate_object(handle, NULL, NULL, &buf);
27 if (ACPI_FAILURE(status))
28 return -EIO;
30 sar_root = buf.pointer;
31 if (sar_root->type != ACPI_TYPE_PACKAGE ||
32 sar_root->package.count < 4 ||
33 sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) {
34 dev_err(mdev->dev, "sar cnt = %d\n",
35 sar_root->package.count);
36 ret = -EINVAL;
37 goto free;
40 if (!*tbl) {
41 *tbl = devm_kzalloc(mdev->dev, sar_root->package.count,
42 GFP_KERNEL);
43 if (!*tbl) {
44 ret = -ENOMEM;
45 goto free;
49 if (len)
50 *len = sar_root->package.count;
52 for (i = 0; i < sar_root->package.count; i++) {
53 union acpi_object *sar_unit = &sar_root->package.elements[i];
55 if (sar_unit->type != ACPI_TYPE_INTEGER)
56 break;
58 *(*tbl + i) = (u8)sar_unit->integer.value;
61 ret = i == sar_root->package.count ? 0 : -EINVAL;
62 free:
63 kfree(sar_root);
65 return ret;
68 /* MTCL : Country List Table for 6G band */
69 static int
70 mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version)
72 int ret;
74 *version = ((ret = mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL)) < 0)
75 ? 1 : 2;
77 return ret;
80 /* MTDS : Dynamic SAR Power Table */
81 static int
82 mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version)
84 int len, ret, sarlen, prelen, tblcnt;
85 bool enable;
87 ret = mt792x_acpi_read(dev, MT792x_ACPI_MTDS, table, &len);
88 if (ret)
89 return ret;
91 /* Table content validation */
92 switch (version) {
93 case 1:
94 enable = ((struct mt792x_asar_dyn *)*table)->enable;
95 sarlen = sizeof(struct mt792x_asar_dyn_limit);
96 prelen = sizeof(struct mt792x_asar_dyn);
97 break;
98 case 2:
99 enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable;
100 sarlen = sizeof(struct mt792x_asar_dyn_limit_v2);
101 prelen = sizeof(struct mt792x_asar_dyn_v2);
102 break;
103 default:
104 return -EINVAL;
107 tblcnt = (len - prelen) / sarlen;
108 if (!enable ||
109 tblcnt > MT792x_ASAR_MAX_DYN || tblcnt < MT792x_ASAR_MIN_DYN)
110 return -EINVAL;
112 return 0;
115 /* MTGS : Geo SAR Power Table */
116 static int
117 mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version)
119 int len, ret, sarlen, prelen, tblcnt;
121 ret = mt792x_acpi_read(dev, MT792x_ACPI_MTGS, table, &len);
122 if (ret)
123 return ret;
125 /* Table content validation */
126 switch (version) {
127 case 1:
128 sarlen = sizeof(struct mt792x_asar_geo_limit);
129 prelen = sizeof(struct mt792x_asar_geo);
130 break;
131 case 2:
132 sarlen = sizeof(struct mt792x_asar_geo_limit_v2);
133 prelen = sizeof(struct mt792x_asar_geo_v2);
134 break;
135 default:
136 return -EINVAL;
139 tblcnt = (len - prelen) / sarlen;
140 if (tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO)
141 return -EINVAL;
143 return 0;
146 /* MTFG : Flag Table */
147 static int
148 mt792x_asar_acpi_read_mtfg(struct mt792x_dev *dev, u8 **table)
150 int len, ret;
152 ret = mt792x_acpi_read(dev, MT792x_ACPI_MTFG, table, &len);
153 if (ret)
154 return ret;
156 if (len < MT792x_ASAR_MIN_FG)
157 return -EINVAL;
159 return 0;
162 int mt792x_init_acpi_sar(struct mt792x_dev *dev)
164 struct mt792x_acpi_sar *asar;
165 int ret;
167 asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL);
168 if (!asar)
169 return -ENOMEM;
171 ret = mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
172 if (ret) {
173 devm_kfree(dev->mt76.dev, asar->countrylist);
174 asar->countrylist = NULL;
177 ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
178 if (ret) {
179 devm_kfree(dev->mt76.dev, asar->dyn);
180 asar->dyn = NULL;
183 /* MTGS is optional */
184 ret = mt792x_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
185 if (ret) {
186 devm_kfree(dev->mt76.dev, asar->geo);
187 asar->geo = NULL;
190 /* MTFG is optional */
191 ret = mt792x_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg);
192 if (ret) {
193 devm_kfree(dev->mt76.dev, asar->fg);
194 asar->fg = NULL;
196 dev->phy.acpisar = asar;
198 return 0;
200 EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar);
202 static s8
203 mt792x_asar_get_geo_pwr(struct mt792x_phy *phy,
204 enum nl80211_band band, s8 dyn_power)
206 struct mt792x_acpi_sar *asar = phy->acpisar;
207 struct mt792x_asar_geo_band *band_pwr;
208 s8 geo_power;
209 u8 idx, max;
211 if (!asar->geo)
212 return dyn_power;
214 switch (phy->mt76->dev->region) {
215 case NL80211_DFS_FCC:
216 idx = 0;
217 break;
218 case NL80211_DFS_ETSI:
219 idx = 1;
220 break;
221 default: /* WW */
222 idx = 2;
223 break;
226 if (asar->ver == 1) {
227 band_pwr = &asar->geo->tbl[idx].band[0];
228 max = ARRAY_SIZE(asar->geo->tbl[idx].band);
229 } else {
230 band_pwr = &asar->geo_v2->tbl[idx].band[0];
231 max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band);
234 switch (band) {
235 case NL80211_BAND_2GHZ:
236 idx = 0;
237 break;
238 case NL80211_BAND_5GHZ:
239 idx = 1;
240 break;
241 case NL80211_BAND_6GHZ:
242 idx = 2;
243 break;
244 default:
245 return dyn_power;
248 if (idx >= max)
249 return dyn_power;
251 geo_power = (band_pwr + idx)->pwr;
252 dyn_power += (band_pwr + idx)->offset;
254 return min(geo_power, dyn_power);
257 static s8
258 mt792x_asar_range_pwr(struct mt792x_phy *phy,
259 const struct cfg80211_sar_freq_ranges *range,
260 u8 idx)
262 const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
263 struct mt792x_acpi_sar *asar = phy->acpisar;
264 u8 *limit, band, max;
266 if (!capa)
267 return 127;
269 if (asar->ver == 1) {
270 limit = &asar->dyn->tbl[0].frp[0];
271 max = ARRAY_SIZE(asar->dyn->tbl[0].frp);
272 } else {
273 limit = &asar->dyn_v2->tbl[0].frp[0];
274 max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp);
277 if (idx >= max)
278 return 127;
280 if (range->start_freq >= 5945)
281 band = NL80211_BAND_6GHZ;
282 else if (range->start_freq >= 5150)
283 band = NL80211_BAND_5GHZ;
284 else
285 band = NL80211_BAND_2GHZ;
287 return mt792x_asar_get_geo_pwr(phy, band, limit[idx]);
290 int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default)
292 const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
293 int i;
295 if (!phy->acpisar || !((struct mt792x_acpi_sar *)phy->acpisar)->dyn)
296 return 0;
298 /* When ACPI SAR enabled in HW, we should apply rules for .frp
299 * 1. w/o .sar_specs : set ACPI SAR power as the defatul value
300 * 2. w/ .sar_specs : set power with min(.sar_specs, ACPI_SAR)
302 for (i = 0; i < capa->num_freq_ranges; i++) {
303 struct mt76_freq_range_power *frp = &phy->mt76->frp[i];
305 frp->range = set_default ? &capa->freq_ranges[i] : frp->range;
306 if (!frp->range)
307 continue;
309 frp->power = min_t(s8, set_default ? 127 : frp->power,
310 mt792x_asar_range_pwr(phy, frp->range, i));
313 return 0;
315 EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar_power);
317 u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
319 struct mt792x_acpi_sar *acpisar = phy->acpisar;
320 struct mt792x_asar_fg *fg;
321 struct {
322 u8 acpi_idx;
323 u8 chip_idx;
324 } map[] = {
325 { 1, 1 },
326 { 4, 2 },
328 u8 flags = BIT(0);
329 int i, j;
331 if (!acpisar)
332 return 0;
334 fg = acpisar->fg;
335 if (!fg)
336 return flags;
338 /* pickup necessary settings per device and
339 * translate the index of bitmap for chip command.
341 for (i = 0; i < fg->nr_flag; i++) {
342 for (j = 0; j < ARRAY_SIZE(map); j++) {
343 if (fg->flag[i] == map[j].acpi_idx) {
344 flags |= BIT(map[j].chip_idx);
345 break;
350 return flags;
352 EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags);
354 static u8
355 mt792x_acpi_get_mtcl_map(int row, int column, struct mt792x_asar_cl *cl)
357 u8 config = 0;
358 u8 mode_6g, mode_5g9;
360 mode_6g = (cl->mode_6g > 0x02) ? 0 : cl->mode_6g;
361 mode_5g9 = (cl->mode_5g9 > 0x01) ? 0 : cl->mode_5g9;
363 if ((cl->cl6g[row] & BIT(column)) || cl->mode_6g == 0x02)
364 config |= (mode_6g & 0x3) << 2;
365 if (cl->version > 1 && cl->cl5g9[row] & BIT(column))
366 config |= (mode_5g9 & 0x3);
368 return config;
371 u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
373 static const char * const cc_list_all[] = {
374 "00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR",
375 "CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME",
376 "MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR",
377 "TW", "TH", "UA", "GB", "US", "VN", "KH", "PY",
379 static const char * const cc_list_eu[] = {
380 "AT", "BE", "BG", "CY", "CZ", "HR", "DK", "EE",
381 "FI", "FR", "DE", "GR", "HU", "IS", "IE", "IT",
382 "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL",
383 "PT", "RO", "SK", "SI", "ES", "SE", "CH",
385 struct mt792x_acpi_sar *sar = phy->acpisar;
386 struct mt792x_asar_cl *cl;
387 int col, row, i;
389 if (!sar)
390 return 0xf;
392 cl = sar->countrylist;
393 if (!cl)
394 return 0xc;
396 for (i = 0; i < ARRAY_SIZE(cc_list_all); i++) {
397 col = 7 - i % 8;
398 row = i / 8;
399 if (!memcmp(cc_list_all[i], alpha2, 2))
400 return mt792x_acpi_get_mtcl_map(row, col, cl);
403 for (i = 0; i < ARRAY_SIZE(cc_list_eu); i++)
404 if (!memcmp(cc_list_eu[i], alpha2, 2))
405 return mt792x_acpi_get_mtcl_map(0, 6, cl);
407 return mt792x_acpi_get_mtcl_map(0, 7, cl);
409 EXPORT_SYMBOL_GPL(mt792x_acpi_get_mtcl_conf);