1cbb3ec25SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2cbb3ec25SBjoern A. Zeeb /* Copyright (C) 2023 MediaTek Inc. */
3cbb3ec25SBjoern A. Zeeb 
4cbb3ec25SBjoern A. Zeeb #include <linux/acpi.h>
5cbb3ec25SBjoern A. Zeeb #include "mt792x.h"
6cbb3ec25SBjoern A. Zeeb 
7cbb3ec25SBjoern A. Zeeb static int
mt792x_acpi_read(struct mt792x_dev * dev,u8 * method,u8 ** tbl,u32 * len)8cbb3ec25SBjoern A. Zeeb mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
9cbb3ec25SBjoern A. Zeeb {
10cbb3ec25SBjoern A. Zeeb 	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
11cbb3ec25SBjoern A. Zeeb 	struct mt76_dev *mdev = &dev->mt76;
12cbb3ec25SBjoern A. Zeeb 	union acpi_object *sar_root;
13cbb3ec25SBjoern A. Zeeb 	acpi_handle root, handle;
14cbb3ec25SBjoern A. Zeeb 	acpi_status status;
15cbb3ec25SBjoern A. Zeeb 	u32 i = 0;
16cbb3ec25SBjoern A. Zeeb 	int ret;
17cbb3ec25SBjoern A. Zeeb 
18cbb3ec25SBjoern A. Zeeb 	root = ACPI_HANDLE(mdev->dev);
19cbb3ec25SBjoern A. Zeeb 	if (!root)
20cbb3ec25SBjoern A. Zeeb 		return -EOPNOTSUPP;
21cbb3ec25SBjoern A. Zeeb 
22cbb3ec25SBjoern A. Zeeb 	status = acpi_get_handle(root, method, &handle);
23cbb3ec25SBjoern A. Zeeb 	if (ACPI_FAILURE(status))
24cbb3ec25SBjoern A. Zeeb 		return -EIO;
25cbb3ec25SBjoern A. Zeeb 
26cbb3ec25SBjoern A. Zeeb 	status = acpi_evaluate_object(handle, NULL, NULL, &buf);
27cbb3ec25SBjoern A. Zeeb 	if (ACPI_FAILURE(status))
28cbb3ec25SBjoern A. Zeeb 		return -EIO;
29cbb3ec25SBjoern A. Zeeb 
30cbb3ec25SBjoern A. Zeeb 	sar_root = buf.pointer;
31cbb3ec25SBjoern A. Zeeb 	if (sar_root->type != ACPI_TYPE_PACKAGE ||
32cbb3ec25SBjoern A. Zeeb 	    sar_root->package.count < 4 ||
33cbb3ec25SBjoern A. Zeeb 	    sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) {
34cbb3ec25SBjoern A. Zeeb 		dev_err(mdev->dev, "sar cnt = %d\n",
35cbb3ec25SBjoern A. Zeeb 			sar_root->package.count);
36cbb3ec25SBjoern A. Zeeb 		ret = -EINVAL;
37cbb3ec25SBjoern A. Zeeb 		goto free;
38cbb3ec25SBjoern A. Zeeb 	}
39cbb3ec25SBjoern A. Zeeb 
40cbb3ec25SBjoern A. Zeeb 	if (!*tbl) {
41cbb3ec25SBjoern A. Zeeb 		*tbl = devm_kzalloc(mdev->dev, sar_root->package.count,
42cbb3ec25SBjoern A. Zeeb 				    GFP_KERNEL);
43cbb3ec25SBjoern A. Zeeb 		if (!*tbl) {
44cbb3ec25SBjoern A. Zeeb 			ret = -ENOMEM;
45cbb3ec25SBjoern A. Zeeb 			goto free;
46cbb3ec25SBjoern A. Zeeb 		}
47cbb3ec25SBjoern A. Zeeb 	}
48cbb3ec25SBjoern A. Zeeb 
49cbb3ec25SBjoern A. Zeeb 	if (len)
50cbb3ec25SBjoern A. Zeeb 		*len = sar_root->package.count;
51cbb3ec25SBjoern A. Zeeb 
52cbb3ec25SBjoern A. Zeeb 	for (i = 0; i < sar_root->package.count; i++) {
53cbb3ec25SBjoern A. Zeeb 		union acpi_object *sar_unit = &sar_root->package.elements[i];
54cbb3ec25SBjoern A. Zeeb 
55cbb3ec25SBjoern A. Zeeb 		if (sar_unit->type != ACPI_TYPE_INTEGER)
56cbb3ec25SBjoern A. Zeeb 			break;
57cbb3ec25SBjoern A. Zeeb 
58cbb3ec25SBjoern A. Zeeb 		*(*tbl + i) = (u8)sar_unit->integer.value;
59cbb3ec25SBjoern A. Zeeb 	}
60cbb3ec25SBjoern A. Zeeb 
61cbb3ec25SBjoern A. Zeeb 	ret = i == sar_root->package.count ? 0 : -EINVAL;
62cbb3ec25SBjoern A. Zeeb free:
63cbb3ec25SBjoern A. Zeeb 	kfree(sar_root);
64cbb3ec25SBjoern A. Zeeb 
65cbb3ec25SBjoern A. Zeeb 	return ret;
66cbb3ec25SBjoern A. Zeeb }
67cbb3ec25SBjoern A. Zeeb 
68cbb3ec25SBjoern A. Zeeb /* MTCL : Country List Table for 6G band */
69cbb3ec25SBjoern A. Zeeb static void
mt792x_asar_acpi_read_mtcl(struct mt792x_dev * dev,u8 ** table,u8 * version)70cbb3ec25SBjoern A. Zeeb mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version)
71cbb3ec25SBjoern A. Zeeb {
72cbb3ec25SBjoern A. Zeeb 	if (mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL) < 0)
73cbb3ec25SBjoern A. Zeeb 		*version = 1;
74cbb3ec25SBjoern A. Zeeb 	else
75cbb3ec25SBjoern A. Zeeb 		*version = 2;
76cbb3ec25SBjoern A. Zeeb }
77cbb3ec25SBjoern A. Zeeb 
78cbb3ec25SBjoern A. Zeeb /* MTDS : Dynamic SAR Power Table */
79cbb3ec25SBjoern A. Zeeb static int
mt792x_asar_acpi_read_mtds(struct mt792x_dev * dev,u8 ** table,u8 version)80cbb3ec25SBjoern A. Zeeb mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version)
81cbb3ec25SBjoern A. Zeeb {
82cbb3ec25SBjoern A. Zeeb 	int len, ret, sarlen, prelen, tblcnt;
83cbb3ec25SBjoern A. Zeeb 	bool enable;
84cbb3ec25SBjoern A. Zeeb 
85cbb3ec25SBjoern A. Zeeb 	ret = mt792x_acpi_read(dev, MT792x_ACPI_MTDS, table, &len);
86cbb3ec25SBjoern A. Zeeb 	if (ret)
87cbb3ec25SBjoern A. Zeeb 		return ret;
88cbb3ec25SBjoern A. Zeeb 
89cbb3ec25SBjoern A. Zeeb 	/* Table content validation */
90cbb3ec25SBjoern A. Zeeb 	switch (version) {
91cbb3ec25SBjoern A. Zeeb 	case 1:
92cbb3ec25SBjoern A. Zeeb 		enable = ((struct mt792x_asar_dyn *)*table)->enable;
93cbb3ec25SBjoern A. Zeeb 		sarlen = sizeof(struct mt792x_asar_dyn_limit);
94cbb3ec25SBjoern A. Zeeb 		prelen = sizeof(struct mt792x_asar_dyn);
95cbb3ec25SBjoern A. Zeeb 		break;
96cbb3ec25SBjoern A. Zeeb 	case 2:
97cbb3ec25SBjoern A. Zeeb 		enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable;
98cbb3ec25SBjoern A. Zeeb 		sarlen = sizeof(struct mt792x_asar_dyn_limit_v2);
99cbb3ec25SBjoern A. Zeeb 		prelen = sizeof(struct mt792x_asar_dyn_v2);
100cbb3ec25SBjoern A. Zeeb 		break;
101cbb3ec25SBjoern A. Zeeb 	default:
102cbb3ec25SBjoern A. Zeeb 		return -EINVAL;
103cbb3ec25SBjoern A. Zeeb 	}
104cbb3ec25SBjoern A. Zeeb 
105cbb3ec25SBjoern A. Zeeb 	tblcnt = (len - prelen) / sarlen;
106cbb3ec25SBjoern A. Zeeb 	if (!enable ||
107cbb3ec25SBjoern A. Zeeb 	    tblcnt > MT792x_ASAR_MAX_DYN || tblcnt < MT792x_ASAR_MIN_DYN)
108cbb3ec25SBjoern A. Zeeb 		return -EINVAL;
109cbb3ec25SBjoern A. Zeeb 
110cbb3ec25SBjoern A. Zeeb 	return 0;
111cbb3ec25SBjoern A. Zeeb }
112cbb3ec25SBjoern A. Zeeb 
113cbb3ec25SBjoern A. Zeeb /* MTGS : Geo SAR Power Table */
114cbb3ec25SBjoern A. Zeeb static int
mt792x_asar_acpi_read_mtgs(struct mt792x_dev * dev,u8 ** table,u8 version)115cbb3ec25SBjoern A. Zeeb mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version)
116cbb3ec25SBjoern A. Zeeb {
117cbb3ec25SBjoern A. Zeeb 	int len, ret, sarlen, prelen, tblcnt;
118cbb3ec25SBjoern A. Zeeb 
119cbb3ec25SBjoern A. Zeeb 	ret = mt792x_acpi_read(dev, MT792x_ACPI_MTGS, table, &len);
120cbb3ec25SBjoern A. Zeeb 	if (ret)
121cbb3ec25SBjoern A. Zeeb 		return ret;
122cbb3ec25SBjoern A. Zeeb 
123cbb3ec25SBjoern A. Zeeb 	/* Table content validation */
124cbb3ec25SBjoern A. Zeeb 	switch (version) {
125cbb3ec25SBjoern A. Zeeb 	case 1:
126cbb3ec25SBjoern A. Zeeb 		sarlen = sizeof(struct mt792x_asar_geo_limit);
127cbb3ec25SBjoern A. Zeeb 		prelen = sizeof(struct mt792x_asar_geo);
128cbb3ec25SBjoern A. Zeeb 		break;
129cbb3ec25SBjoern A. Zeeb 	case 2:
130cbb3ec25SBjoern A. Zeeb 		sarlen = sizeof(struct mt792x_asar_geo_limit_v2);
131cbb3ec25SBjoern A. Zeeb 		prelen = sizeof(struct mt792x_asar_geo_v2);
132cbb3ec25SBjoern A. Zeeb 		break;
133cbb3ec25SBjoern A. Zeeb 	default:
134cbb3ec25SBjoern A. Zeeb 		return -EINVAL;
135cbb3ec25SBjoern A. Zeeb 	}
136cbb3ec25SBjoern A. Zeeb 
137cbb3ec25SBjoern A. Zeeb 	tblcnt = (len - prelen) / sarlen;
138cbb3ec25SBjoern A. Zeeb 	if (tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO)
139cbb3ec25SBjoern A. Zeeb 		return -EINVAL;
140cbb3ec25SBjoern A. Zeeb 
141cbb3ec25SBjoern A. Zeeb 	return 0;
142cbb3ec25SBjoern A. Zeeb }
143cbb3ec25SBjoern A. Zeeb 
144cbb3ec25SBjoern A. Zeeb /* MTFG : Flag Table */
145cbb3ec25SBjoern A. Zeeb static int
mt792x_asar_acpi_read_mtfg(struct mt792x_dev * dev,u8 ** table)146cbb3ec25SBjoern A. Zeeb mt792x_asar_acpi_read_mtfg(struct mt792x_dev *dev, u8 **table)
147cbb3ec25SBjoern A. Zeeb {
148cbb3ec25SBjoern A. Zeeb 	int len, ret;
149cbb3ec25SBjoern A. Zeeb 
150cbb3ec25SBjoern A. Zeeb 	ret = mt792x_acpi_read(dev, MT792x_ACPI_MTFG, table, &len);
151cbb3ec25SBjoern A. Zeeb 	if (ret)
152cbb3ec25SBjoern A. Zeeb 		return ret;
153cbb3ec25SBjoern A. Zeeb 
154cbb3ec25SBjoern A. Zeeb 	if (len < MT792x_ASAR_MIN_FG)
155cbb3ec25SBjoern A. Zeeb 		return -EINVAL;
156cbb3ec25SBjoern A. Zeeb 
157cbb3ec25SBjoern A. Zeeb 	return 0;
158cbb3ec25SBjoern A. Zeeb }
159cbb3ec25SBjoern A. Zeeb 
mt792x_init_acpi_sar(struct mt792x_dev * dev)160cbb3ec25SBjoern A. Zeeb int mt792x_init_acpi_sar(struct mt792x_dev *dev)
161cbb3ec25SBjoern A. Zeeb {
162cbb3ec25SBjoern A. Zeeb 	struct mt792x_acpi_sar *asar;
163cbb3ec25SBjoern A. Zeeb 	int ret;
164cbb3ec25SBjoern A. Zeeb 
165cbb3ec25SBjoern A. Zeeb 	asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL);
166cbb3ec25SBjoern A. Zeeb 	if (!asar)
167cbb3ec25SBjoern A. Zeeb 		return -ENOMEM;
168cbb3ec25SBjoern A. Zeeb 
169cbb3ec25SBjoern A. Zeeb 	mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
170cbb3ec25SBjoern A. Zeeb 
171cbb3ec25SBjoern A. Zeeb 	/* MTDS is mandatory. Return error if table is invalid */
172cbb3ec25SBjoern A. Zeeb 	ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
173cbb3ec25SBjoern A. Zeeb 	if (ret) {
174cbb3ec25SBjoern A. Zeeb 		devm_kfree(dev->mt76.dev, asar->dyn);
175cbb3ec25SBjoern A. Zeeb 		devm_kfree(dev->mt76.dev, asar->countrylist);
176cbb3ec25SBjoern A. Zeeb 		devm_kfree(dev->mt76.dev, asar);
177cbb3ec25SBjoern A. Zeeb 
178cbb3ec25SBjoern A. Zeeb 		return ret;
179cbb3ec25SBjoern A. Zeeb 	}
180cbb3ec25SBjoern A. Zeeb 
181cbb3ec25SBjoern A. Zeeb 	/* MTGS is optional */
182cbb3ec25SBjoern A. Zeeb 	ret = mt792x_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
183cbb3ec25SBjoern A. Zeeb 	if (ret) {
184cbb3ec25SBjoern A. Zeeb 		devm_kfree(dev->mt76.dev, asar->geo);
185cbb3ec25SBjoern A. Zeeb 		asar->geo = NULL;
186cbb3ec25SBjoern A. Zeeb 	}
187cbb3ec25SBjoern A. Zeeb 
188cbb3ec25SBjoern A. Zeeb 	/* MTFG is optional */
189cbb3ec25SBjoern A. Zeeb 	ret = mt792x_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg);
190cbb3ec25SBjoern A. Zeeb 	if (ret) {
191cbb3ec25SBjoern A. Zeeb 		devm_kfree(dev->mt76.dev, asar->fg);
192cbb3ec25SBjoern A. Zeeb 		asar->fg = NULL;
193cbb3ec25SBjoern A. Zeeb 	}
194cbb3ec25SBjoern A. Zeeb 	dev->phy.acpisar = asar;
195cbb3ec25SBjoern A. Zeeb 
196cbb3ec25SBjoern A. Zeeb 	return 0;
197cbb3ec25SBjoern A. Zeeb }
198cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar);
199cbb3ec25SBjoern A. Zeeb 
200cbb3ec25SBjoern A. Zeeb static s8
mt792x_asar_get_geo_pwr(struct mt792x_phy * phy,enum nl80211_band band,s8 dyn_power)201cbb3ec25SBjoern A. Zeeb mt792x_asar_get_geo_pwr(struct mt792x_phy *phy,
202cbb3ec25SBjoern A. Zeeb 			enum nl80211_band band, s8 dyn_power)
203cbb3ec25SBjoern A. Zeeb {
204cbb3ec25SBjoern A. Zeeb 	struct mt792x_acpi_sar *asar = phy->acpisar;
205cbb3ec25SBjoern A. Zeeb 	struct mt792x_asar_geo_band *band_pwr;
206cbb3ec25SBjoern A. Zeeb 	s8 geo_power;
207cbb3ec25SBjoern A. Zeeb 	u8 idx, max;
208cbb3ec25SBjoern A. Zeeb 
209cbb3ec25SBjoern A. Zeeb 	if (!asar->geo)
210cbb3ec25SBjoern A. Zeeb 		return dyn_power;
211cbb3ec25SBjoern A. Zeeb 
212cbb3ec25SBjoern A. Zeeb 	switch (phy->mt76->dev->region) {
213cbb3ec25SBjoern A. Zeeb 	case NL80211_DFS_FCC:
214cbb3ec25SBjoern A. Zeeb 		idx = 0;
215cbb3ec25SBjoern A. Zeeb 		break;
216cbb3ec25SBjoern A. Zeeb 	case NL80211_DFS_ETSI:
217cbb3ec25SBjoern A. Zeeb 		idx = 1;
218cbb3ec25SBjoern A. Zeeb 		break;
219cbb3ec25SBjoern A. Zeeb 	default: /* WW */
220cbb3ec25SBjoern A. Zeeb 		idx = 2;
221cbb3ec25SBjoern A. Zeeb 		break;
222cbb3ec25SBjoern A. Zeeb 	}
223cbb3ec25SBjoern A. Zeeb 
224cbb3ec25SBjoern A. Zeeb 	if (asar->ver == 1) {
225cbb3ec25SBjoern A. Zeeb 		band_pwr = &asar->geo->tbl[idx].band[0];
226cbb3ec25SBjoern A. Zeeb 		max = ARRAY_SIZE(asar->geo->tbl[idx].band);
227cbb3ec25SBjoern A. Zeeb 	} else {
228cbb3ec25SBjoern A. Zeeb 		band_pwr = &asar->geo_v2->tbl[idx].band[0];
229cbb3ec25SBjoern A. Zeeb 		max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band);
230cbb3ec25SBjoern A. Zeeb 	}
231cbb3ec25SBjoern A. Zeeb 
232cbb3ec25SBjoern A. Zeeb 	switch (band) {
233cbb3ec25SBjoern A. Zeeb 	case NL80211_BAND_2GHZ:
234cbb3ec25SBjoern A. Zeeb 		idx = 0;
235cbb3ec25SBjoern A. Zeeb 		break;
236cbb3ec25SBjoern A. Zeeb 	case NL80211_BAND_5GHZ:
237cbb3ec25SBjoern A. Zeeb 		idx = 1;
238cbb3ec25SBjoern A. Zeeb 		break;
239cbb3ec25SBjoern A. Zeeb 	case NL80211_BAND_6GHZ:
240cbb3ec25SBjoern A. Zeeb 		idx = 2;
241cbb3ec25SBjoern A. Zeeb 		break;
242cbb3ec25SBjoern A. Zeeb 	default:
243cbb3ec25SBjoern A. Zeeb 		return dyn_power;
244cbb3ec25SBjoern A. Zeeb 	}
245cbb3ec25SBjoern A. Zeeb 
246cbb3ec25SBjoern A. Zeeb 	if (idx >= max)
247cbb3ec25SBjoern A. Zeeb 		return dyn_power;
248cbb3ec25SBjoern A. Zeeb 
249cbb3ec25SBjoern A. Zeeb 	geo_power = (band_pwr + idx)->pwr;
250cbb3ec25SBjoern A. Zeeb 	dyn_power += (band_pwr + idx)->offset;
251cbb3ec25SBjoern A. Zeeb 
252cbb3ec25SBjoern A. Zeeb 	return min(geo_power, dyn_power);
253cbb3ec25SBjoern A. Zeeb }
254cbb3ec25SBjoern A. Zeeb 
255cbb3ec25SBjoern A. Zeeb static s8
mt792x_asar_range_pwr(struct mt792x_phy * phy,const struct cfg80211_sar_freq_ranges * range,u8 idx)256cbb3ec25SBjoern A. Zeeb mt792x_asar_range_pwr(struct mt792x_phy *phy,
257cbb3ec25SBjoern A. Zeeb 		      const struct cfg80211_sar_freq_ranges *range,
258cbb3ec25SBjoern A. Zeeb 		      u8 idx)
259cbb3ec25SBjoern A. Zeeb {
260cbb3ec25SBjoern A. Zeeb 	const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
261cbb3ec25SBjoern A. Zeeb 	struct mt792x_acpi_sar *asar = phy->acpisar;
262cbb3ec25SBjoern A. Zeeb 	u8 *limit, band, max;
263cbb3ec25SBjoern A. Zeeb 
264cbb3ec25SBjoern A. Zeeb 	if (!capa)
265cbb3ec25SBjoern A. Zeeb 		return 127;
266cbb3ec25SBjoern A. Zeeb 
267cbb3ec25SBjoern A. Zeeb 	if (asar->ver == 1) {
268cbb3ec25SBjoern A. Zeeb 		limit = &asar->dyn->tbl[0].frp[0];
269cbb3ec25SBjoern A. Zeeb 		max = ARRAY_SIZE(asar->dyn->tbl[0].frp);
270cbb3ec25SBjoern A. Zeeb 	} else {
271cbb3ec25SBjoern A. Zeeb 		limit = &asar->dyn_v2->tbl[0].frp[0];
272cbb3ec25SBjoern A. Zeeb 		max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp);
273cbb3ec25SBjoern A. Zeeb 	}
274cbb3ec25SBjoern A. Zeeb 
275cbb3ec25SBjoern A. Zeeb 	if (idx >= max)
276cbb3ec25SBjoern A. Zeeb 		return 127;
277cbb3ec25SBjoern A. Zeeb 
278cbb3ec25SBjoern A. Zeeb 	if (range->start_freq >= 5945)
279cbb3ec25SBjoern A. Zeeb 		band = NL80211_BAND_6GHZ;
280cbb3ec25SBjoern A. Zeeb 	else if (range->start_freq >= 5150)
281cbb3ec25SBjoern A. Zeeb 		band = NL80211_BAND_5GHZ;
282cbb3ec25SBjoern A. Zeeb 	else
283cbb3ec25SBjoern A. Zeeb 		band = NL80211_BAND_2GHZ;
284cbb3ec25SBjoern A. Zeeb 
285cbb3ec25SBjoern A. Zeeb 	return mt792x_asar_get_geo_pwr(phy, band, limit[idx]);
286cbb3ec25SBjoern A. Zeeb }
287cbb3ec25SBjoern A. Zeeb 
mt792x_init_acpi_sar_power(struct mt792x_phy * phy,bool set_default)288cbb3ec25SBjoern A. Zeeb int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default)
289cbb3ec25SBjoern A. Zeeb {
290cbb3ec25SBjoern A. Zeeb 	const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
291cbb3ec25SBjoern A. Zeeb 	int i;
292cbb3ec25SBjoern A. Zeeb 
293cbb3ec25SBjoern A. Zeeb 	if (!phy->acpisar)
294cbb3ec25SBjoern A. Zeeb 		return 0;
295cbb3ec25SBjoern A. Zeeb 
296cbb3ec25SBjoern A. Zeeb 	/* When ACPI SAR enabled in HW, we should apply rules for .frp
297cbb3ec25SBjoern A. Zeeb 	 * 1. w/o .sar_specs : set ACPI SAR power as the defatul value
298cbb3ec25SBjoern A. Zeeb 	 * 2. w/  .sar_specs : set power with min(.sar_specs, ACPI_SAR)
299cbb3ec25SBjoern A. Zeeb 	 */
300cbb3ec25SBjoern A. Zeeb 	for (i = 0; i < capa->num_freq_ranges; i++) {
301cbb3ec25SBjoern A. Zeeb 		struct mt76_freq_range_power *frp = &phy->mt76->frp[i];
302cbb3ec25SBjoern A. Zeeb 
303cbb3ec25SBjoern A. Zeeb 		frp->range = set_default ? &capa->freq_ranges[i] : frp->range;
304cbb3ec25SBjoern A. Zeeb 		if (!frp->range)
305cbb3ec25SBjoern A. Zeeb 			continue;
306cbb3ec25SBjoern A. Zeeb 
307cbb3ec25SBjoern A. Zeeb 		frp->power = min_t(s8, set_default ? 127 : frp->power,
308cbb3ec25SBjoern A. Zeeb 				   mt792x_asar_range_pwr(phy, frp->range, i));
309cbb3ec25SBjoern A. Zeeb 	}
310cbb3ec25SBjoern A. Zeeb 
311cbb3ec25SBjoern A. Zeeb 	return 0;
312cbb3ec25SBjoern A. Zeeb }
313cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar_power);
314cbb3ec25SBjoern A. Zeeb 
mt792x_acpi_get_flags(struct mt792x_phy * phy)315cbb3ec25SBjoern A. Zeeb u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
316cbb3ec25SBjoern A. Zeeb {
317cbb3ec25SBjoern A. Zeeb 	struct mt792x_acpi_sar *acpisar = phy->acpisar;
318cbb3ec25SBjoern A. Zeeb 	struct mt792x_asar_fg *fg;
319cbb3ec25SBjoern A. Zeeb 	struct {
320cbb3ec25SBjoern A. Zeeb 		u8 acpi_idx;
321cbb3ec25SBjoern A. Zeeb 		u8 chip_idx;
322cbb3ec25SBjoern A. Zeeb 	} map[] = {
323cbb3ec25SBjoern A. Zeeb 		{ 1, 1 },
324cbb3ec25SBjoern A. Zeeb 		{ 4, 2 },
325cbb3ec25SBjoern A. Zeeb 	};
326cbb3ec25SBjoern A. Zeeb 	u8 flags = BIT(0);
327cbb3ec25SBjoern A. Zeeb 	int i, j;
328cbb3ec25SBjoern A. Zeeb 
329cbb3ec25SBjoern A. Zeeb 	if (!acpisar)
330cbb3ec25SBjoern A. Zeeb 		return 0;
331cbb3ec25SBjoern A. Zeeb 
332cbb3ec25SBjoern A. Zeeb 	fg = acpisar->fg;
333cbb3ec25SBjoern A. Zeeb 	if (!fg)
334cbb3ec25SBjoern A. Zeeb 		return flags;
335cbb3ec25SBjoern A. Zeeb 
336cbb3ec25SBjoern A. Zeeb 	/* pickup necessary settings per device and
337cbb3ec25SBjoern A. Zeeb 	 * translate the index of bitmap for chip command.
338cbb3ec25SBjoern A. Zeeb 	 */
339cbb3ec25SBjoern A. Zeeb 	for (i = 0; i < fg->nr_flag; i++) {
340cbb3ec25SBjoern A. Zeeb 		for (j = 0; j < ARRAY_SIZE(map); j++) {
341cbb3ec25SBjoern A. Zeeb 			if (fg->flag[i] == map[j].acpi_idx) {
342cbb3ec25SBjoern A. Zeeb 				flags |= BIT(map[j].chip_idx);
343cbb3ec25SBjoern A. Zeeb 				break;
344cbb3ec25SBjoern A. Zeeb 			}
345cbb3ec25SBjoern A. Zeeb 		}
346cbb3ec25SBjoern A. Zeeb 	}
347cbb3ec25SBjoern A. Zeeb 
348cbb3ec25SBjoern A. Zeeb 	return flags;
349cbb3ec25SBjoern A. Zeeb }
350cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags);
351