1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2023 MediaTek Inc. */
4 #include <linux/acpi.h>
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
;
18 root
= ACPI_HANDLE(mdev
->dev
);
22 status
= acpi_get_handle(root
, method
, &handle
);
23 if (ACPI_FAILURE(status
))
26 status
= acpi_evaluate_object(handle
, NULL
, NULL
, &buf
);
27 if (ACPI_FAILURE(status
))
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
);
41 *tbl
= devm_kzalloc(mdev
->dev
, sar_root
->package
.count
,
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
)
58 *(*tbl
+ i
) = (u8
)sar_unit
->integer
.value
;
61 ret
= i
== sar_root
->package
.count
? 0 : -EINVAL
;
68 /* MTCL : Country List Table for 6G band */
70 mt792x_asar_acpi_read_mtcl(struct mt792x_dev
*dev
, u8
**table
, u8
*version
)
74 *version
= ((ret
= mt792x_acpi_read(dev
, MT792x_ACPI_MTCL
, table
, NULL
)) < 0)
80 /* MTDS : Dynamic SAR Power Table */
82 mt792x_asar_acpi_read_mtds(struct mt792x_dev
*dev
, u8
**table
, u8 version
)
84 int len
, ret
, sarlen
, prelen
, tblcnt
;
87 ret
= mt792x_acpi_read(dev
, MT792x_ACPI_MTDS
, table
, &len
);
91 /* Table content validation */
94 enable
= ((struct mt792x_asar_dyn
*)*table
)->enable
;
95 sarlen
= sizeof(struct mt792x_asar_dyn_limit
);
96 prelen
= sizeof(struct mt792x_asar_dyn
);
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
);
107 tblcnt
= (len
- prelen
) / sarlen
;
109 tblcnt
> MT792x_ASAR_MAX_DYN
|| tblcnt
< MT792x_ASAR_MIN_DYN
)
115 /* MTGS : Geo SAR Power Table */
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
);
125 /* Table content validation */
128 sarlen
= sizeof(struct mt792x_asar_geo_limit
);
129 prelen
= sizeof(struct mt792x_asar_geo
);
132 sarlen
= sizeof(struct mt792x_asar_geo_limit_v2
);
133 prelen
= sizeof(struct mt792x_asar_geo_v2
);
139 tblcnt
= (len
- prelen
) / sarlen
;
140 if (tblcnt
> MT792x_ASAR_MAX_GEO
|| tblcnt
< MT792x_ASAR_MIN_GEO
)
146 /* MTFG : Flag Table */
148 mt792x_asar_acpi_read_mtfg(struct mt792x_dev
*dev
, u8
**table
)
152 ret
= mt792x_acpi_read(dev
, MT792x_ACPI_MTFG
, table
, &len
);
156 if (len
< MT792x_ASAR_MIN_FG
)
162 int mt792x_init_acpi_sar(struct mt792x_dev
*dev
)
164 struct mt792x_acpi_sar
*asar
;
167 asar
= devm_kzalloc(dev
->mt76
.dev
, sizeof(*asar
), GFP_KERNEL
);
171 ret
= mt792x_asar_acpi_read_mtcl(dev
, (u8
**)&asar
->countrylist
, &asar
->ver
);
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
);
179 devm_kfree(dev
->mt76
.dev
, asar
->dyn
);
183 /* MTGS is optional */
184 ret
= mt792x_asar_acpi_read_mtgs(dev
, (u8
**)&asar
->geo
, asar
->ver
);
186 devm_kfree(dev
->mt76
.dev
, asar
->geo
);
190 /* MTFG is optional */
191 ret
= mt792x_asar_acpi_read_mtfg(dev
, (u8
**)&asar
->fg
);
193 devm_kfree(dev
->mt76
.dev
, asar
->fg
);
196 dev
->phy
.acpisar
= asar
;
200 EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar
);
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
;
214 switch (phy
->mt76
->dev
->region
) {
215 case NL80211_DFS_FCC
:
218 case NL80211_DFS_ETSI
:
226 if (asar
->ver
== 1) {
227 band_pwr
= &asar
->geo
->tbl
[idx
].band
[0];
228 max
= ARRAY_SIZE(asar
->geo
->tbl
[idx
].band
);
230 band_pwr
= &asar
->geo_v2
->tbl
[idx
].band
[0];
231 max
= ARRAY_SIZE(asar
->geo_v2
->tbl
[idx
].band
);
235 case NL80211_BAND_2GHZ
:
238 case NL80211_BAND_5GHZ
:
241 case NL80211_BAND_6GHZ
:
251 geo_power
= (band_pwr
+ idx
)->pwr
;
252 dyn_power
+= (band_pwr
+ idx
)->offset
;
254 return min(geo_power
, dyn_power
);
258 mt792x_asar_range_pwr(struct mt792x_phy
*phy
,
259 const struct cfg80211_sar_freq_ranges
*range
,
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
;
269 if (asar
->ver
== 1) {
270 limit
= &asar
->dyn
->tbl
[0].frp
[0];
271 max
= ARRAY_SIZE(asar
->dyn
->tbl
[0].frp
);
273 limit
= &asar
->dyn_v2
->tbl
[0].frp
[0];
274 max
= ARRAY_SIZE(asar
->dyn_v2
->tbl
[0].frp
);
280 if (range
->start_freq
>= 5945)
281 band
= NL80211_BAND_6GHZ
;
282 else if (range
->start_freq
>= 5150)
283 band
= NL80211_BAND_5GHZ
;
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
;
295 if (!phy
->acpisar
|| !((struct mt792x_acpi_sar
*)phy
->acpisar
)->dyn
)
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
;
309 frp
->power
= min_t(s8
, set_default
? 127 : frp
->power
,
310 mt792x_asar_range_pwr(phy
, frp
->range
, i
));
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
;
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
);
352 EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags
);
355 mt792x_acpi_get_mtcl_map(int row
, int column
, struct mt792x_asar_cl
*cl
)
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);
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
;
392 cl
= sar
->countrylist
;
396 for (i
= 0; i
< ARRAY_SIZE(cc_list_all
); i
++) {
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
);