xref: /linux/drivers/net/wireless/realtek/rtw89/acpi.c (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2021-2023  Realtek Corporation
3  */
4 
5 #include <linux/acpi.h>
6 #include <linux/uuid.h>
7 
8 #include "acpi.h"
9 #include "debug.h"
10 
11 static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
12 					   0x82, 0xBD, 0xFE, 0x86,
13 					   0x07, 0x80, 0x3A, 0xA7);
14 
rtw89_acpi_traversal_object(struct rtw89_dev * rtwdev,const union acpi_object * obj,u8 * pos)15 static u32 rtw89_acpi_traversal_object(struct rtw89_dev *rtwdev,
16 				       const union acpi_object *obj, u8 *pos)
17 {
18 	const union acpi_object *elm;
19 	unsigned int i;
20 	u32 sub_len;
21 	u32 len = 0;
22 	u8 *tmp;
23 
24 	switch (obj->type) {
25 	case ACPI_TYPE_INTEGER:
26 		if (pos)
27 			pos[len] = obj->integer.value;
28 
29 		len++;
30 		break;
31 	case ACPI_TYPE_BUFFER:
32 		if (unlikely(obj->buffer.length == 0)) {
33 			rtw89_debug(rtwdev, RTW89_DBG_ACPI,
34 				    "%s: invalid buffer type\n", __func__);
35 			goto err;
36 		}
37 
38 		if (pos)
39 			memcpy(pos, obj->buffer.pointer, obj->buffer.length);
40 
41 		len += obj->buffer.length;
42 		break;
43 	case ACPI_TYPE_PACKAGE:
44 		if (unlikely(obj->package.count == 0)) {
45 			rtw89_debug(rtwdev, RTW89_DBG_ACPI,
46 				    "%s: invalid package type\n", __func__);
47 			goto err;
48 		}
49 
50 		for (i = 0; i < obj->package.count; i++) {
51 			elm = &obj->package.elements[i];
52 			tmp = pos ? pos + len : NULL;
53 
54 			sub_len = rtw89_acpi_traversal_object(rtwdev, elm, tmp);
55 			if (unlikely(sub_len == 0))
56 				goto err;
57 
58 			len += sub_len;
59 		}
60 		break;
61 	default:
62 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: unhandled type: %d\n",
63 			    __func__, obj->type);
64 		goto err;
65 	}
66 
67 	return len;
68 
69 err:
70 	return 0;
71 }
72 
rtw89_acpi_calculate_object_length(struct rtw89_dev * rtwdev,const union acpi_object * obj)73 static u32 rtw89_acpi_calculate_object_length(struct rtw89_dev *rtwdev,
74 					      const union acpi_object *obj)
75 {
76 	return rtw89_acpi_traversal_object(rtwdev, obj, NULL);
77 }
78 
79 static struct rtw89_acpi_data *
rtw89_acpi_evaluate_method(struct rtw89_dev * rtwdev,const char * method)80 rtw89_acpi_evaluate_method(struct rtw89_dev *rtwdev, const char *method)
81 {
82 	struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
83 	struct rtw89_acpi_data *data = NULL;
84 	acpi_handle root, handle;
85 	union acpi_object *obj;
86 	acpi_status status;
87 	u32 len;
88 
89 	root = ACPI_HANDLE(rtwdev->dev);
90 	if (!root) {
91 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
92 			    "acpi (%s): failed to get root\n", method);
93 		return NULL;
94 	}
95 
96 	status = acpi_get_handle(root, (acpi_string)method, &handle);
97 	if (ACPI_FAILURE(status)) {
98 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
99 			    "acpi (%s): failed to get handle\n", method);
100 		return NULL;
101 	}
102 
103 	status = acpi_evaluate_object(handle, NULL, NULL, &buf);
104 	if (ACPI_FAILURE(status)) {
105 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
106 			    "acpi (%s): failed to evaluate object\n", method);
107 		return NULL;
108 	}
109 
110 	obj = buf.pointer;
111 	len = rtw89_acpi_calculate_object_length(rtwdev, obj);
112 	if (unlikely(len == 0)) {
113 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
114 			    "acpi (%s): failed to traversal obj len\n", method);
115 		goto out;
116 	}
117 
118 	data = kzalloc(struct_size(data, buf, len), GFP_KERNEL);
119 	if (!data)
120 		goto out;
121 
122 	data->len = len;
123 	rtw89_acpi_traversal_object(rtwdev, obj, data->buf);
124 
125 out:
126 	ACPI_FREE(obj);
127 	return data;
128 }
129 
130 static
rtw89_acpi_dsm_get_value(struct rtw89_dev * rtwdev,union acpi_object * obj,u8 * value)131 int rtw89_acpi_dsm_get_value(struct rtw89_dev *rtwdev, union acpi_object *obj,
132 			     u8 *value)
133 {
134 	if (obj->type != ACPI_TYPE_INTEGER) {
135 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
136 			    "acpi: expect integer but type: %d\n", obj->type);
137 		return -EINVAL;
138 	}
139 
140 	*value = (u8)obj->integer.value;
141 	return 0;
142 }
143 
chk_acpi_policy_6ghz_sig(const struct rtw89_acpi_policy_6ghz * p)144 static bool chk_acpi_policy_6ghz_sig(const struct rtw89_acpi_policy_6ghz *p)
145 {
146 	return p->signature[0] == 0x00 &&
147 	       p->signature[1] == 0xE0 &&
148 	       p->signature[2] == 0x4C;
149 }
150 
151 static
rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_6ghz ** policy_6ghz)152 int rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev *rtwdev,
153 				   union acpi_object *obj,
154 				   struct rtw89_acpi_policy_6ghz **policy_6ghz)
155 {
156 	const struct rtw89_acpi_policy_6ghz *ptr;
157 	u32 expect_len;
158 	u32 len;
159 
160 	if (obj->type != ACPI_TYPE_BUFFER) {
161 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
162 			    "acpi: expect buffer but type: %d\n", obj->type);
163 		return -EINVAL;
164 	}
165 
166 	len = obj->buffer.length;
167 	if (len < sizeof(*ptr)) {
168 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
169 			    __func__, len);
170 		return -EINVAL;
171 	}
172 
173 	ptr = (typeof(ptr))obj->buffer.pointer;
174 	if (!chk_acpi_policy_6ghz_sig(ptr)) {
175 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
176 		return -EINVAL;
177 	}
178 
179 	expect_len = struct_size(ptr, country_list, ptr->country_count);
180 	if (len < expect_len) {
181 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: expect %u but length: %u\n",
182 			    __func__, expect_len, len);
183 		return -EINVAL;
184 	}
185 
186 	*policy_6ghz = kmemdup(ptr, expect_len, GFP_KERNEL);
187 	if (!*policy_6ghz)
188 		return -ENOMEM;
189 
190 	rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz: ", *policy_6ghz,
191 		       expect_len);
192 	return 0;
193 }
194 
chk_acpi_policy_6ghz_sp_sig(const struct rtw89_acpi_policy_6ghz_sp * p)195 static bool chk_acpi_policy_6ghz_sp_sig(const struct rtw89_acpi_policy_6ghz_sp *p)
196 {
197 	return p->signature[0] == 0x52 &&
198 	       p->signature[1] == 0x54 &&
199 	       p->signature[2] == 0x4B &&
200 	       p->signature[3] == 0x07;
201 }
202 
203 static
rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_6ghz_sp ** policy)204 int rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev *rtwdev,
205 				      union acpi_object *obj,
206 				      struct rtw89_acpi_policy_6ghz_sp **policy)
207 {
208 	const struct rtw89_acpi_policy_6ghz_sp *ptr;
209 	u32 buf_len;
210 
211 	if (obj->type != ACPI_TYPE_BUFFER) {
212 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
213 			    "acpi: expect buffer but type: %d\n", obj->type);
214 		return -EINVAL;
215 	}
216 
217 	buf_len = obj->buffer.length;
218 	if (buf_len < sizeof(*ptr)) {
219 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
220 			    __func__, buf_len);
221 		return -EINVAL;
222 	}
223 
224 	ptr = (typeof(ptr))obj->buffer.pointer;
225 	if (!chk_acpi_policy_6ghz_sp_sig(ptr)) {
226 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
227 		return -EINVAL;
228 	}
229 
230 	*policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
231 	if (!*policy)
232 		return -ENOMEM;
233 
234 	rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz_sp: ", *policy,
235 		       sizeof(*ptr));
236 	return 0;
237 }
238 
chk_acpi_policy_6ghz_vlp_sig(const struct rtw89_acpi_policy_6ghz_vlp * p)239 static bool chk_acpi_policy_6ghz_vlp_sig(const struct rtw89_acpi_policy_6ghz_vlp *p)
240 {
241 	return p->signature[0] == 0x52 &&
242 	       p->signature[1] == 0x54 &&
243 	       p->signature[2] == 0x4B &&
244 	       p->signature[3] == 0x0B;
245 }
246 
247 static
rtw89_acpi_dsm_get_policy_6ghz_vlp(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_6ghz_vlp ** policy)248 int rtw89_acpi_dsm_get_policy_6ghz_vlp(struct rtw89_dev *rtwdev,
249 				       union acpi_object *obj,
250 				       struct rtw89_acpi_policy_6ghz_vlp **policy)
251 {
252 	const struct rtw89_acpi_policy_6ghz_vlp *ptr;
253 	u32 buf_len;
254 
255 	if (obj->type != ACPI_TYPE_BUFFER) {
256 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
257 			    "acpi: expect buffer but type: %d\n", obj->type);
258 		return -EINVAL;
259 	}
260 
261 	buf_len = obj->buffer.length;
262 	if (buf_len < sizeof(*ptr)) {
263 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
264 			    __func__, buf_len);
265 		return -EINVAL;
266 	}
267 
268 	ptr = (typeof(ptr))obj->buffer.pointer;
269 	if (!chk_acpi_policy_6ghz_vlp_sig(ptr)) {
270 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
271 		return -EINVAL;
272 	}
273 
274 	*policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
275 	if (!*policy)
276 		return -ENOMEM;
277 
278 	rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz_vlp: ", *policy,
279 		       sizeof(*ptr));
280 	return 0;
281 }
282 
chk_acpi_policy_tas_sig(const struct rtw89_acpi_policy_tas * p)283 static bool chk_acpi_policy_tas_sig(const struct rtw89_acpi_policy_tas *p)
284 {
285 	return p->signature[0] == 0x52 &&
286 	       p->signature[1] == 0x54 &&
287 	       p->signature[2] == 0x4B &&
288 	       p->signature[3] == 0x05;
289 }
290 
rtw89_acpi_dsm_get_policy_tas(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_tas ** policy)291 static int rtw89_acpi_dsm_get_policy_tas(struct rtw89_dev *rtwdev,
292 					 union acpi_object *obj,
293 					 struct rtw89_acpi_policy_tas **policy)
294 {
295 	const struct rtw89_acpi_policy_tas *ptr;
296 	u32 buf_len;
297 
298 	if (obj->type != ACPI_TYPE_BUFFER) {
299 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
300 			    "acpi: expect buffer but type: %d\n", obj->type);
301 		return -EINVAL;
302 	}
303 
304 	buf_len = obj->buffer.length;
305 	if (buf_len < sizeof(*ptr)) {
306 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
307 			    __func__, buf_len);
308 		return -EINVAL;
309 	}
310 
311 	ptr = (typeof(ptr))obj->buffer.pointer;
312 	if (!chk_acpi_policy_tas_sig(ptr)) {
313 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
314 		return -EINVAL;
315 	}
316 
317 	*policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
318 	if (!*policy)
319 		return -ENOMEM;
320 
321 	rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_tas: ", *policy,
322 		       sizeof(*ptr));
323 	return 0;
324 }
325 
326 static
chk_acpi_policy_reg_rules_sig(const struct rtw89_acpi_policy_reg_rules * p)327 bool chk_acpi_policy_reg_rules_sig(const struct rtw89_acpi_policy_reg_rules *p)
328 {
329 	return p->signature[0] == 0x52 &&
330 	       p->signature[1] == 0x54 &&
331 	       p->signature[2] == 0x4B &&
332 	       p->signature[3] == 0x0A;
333 }
334 
335 static
rtw89_acpi_dsm_get_policy_reg_rules(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_reg_rules ** policy)336 int rtw89_acpi_dsm_get_policy_reg_rules(struct rtw89_dev *rtwdev,
337 					union acpi_object *obj,
338 					struct rtw89_acpi_policy_reg_rules **policy)
339 {
340 	const struct rtw89_acpi_policy_reg_rules *ptr;
341 	u32 buf_len;
342 
343 	if (obj->type != ACPI_TYPE_BUFFER) {
344 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
345 			    "acpi: expect buffer but type: %d\n", obj->type);
346 		return -EINVAL;
347 	}
348 
349 	buf_len = obj->buffer.length;
350 	if (buf_len < sizeof(*ptr)) {
351 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
352 			    __func__, buf_len);
353 		return -EINVAL;
354 	}
355 
356 	ptr = (typeof(ptr))obj->buffer.pointer;
357 	if (!chk_acpi_policy_reg_rules_sig(ptr)) {
358 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
359 		return -EINVAL;
360 	}
361 
362 	*policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
363 	if (!*policy)
364 		return -ENOMEM;
365 
366 	rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_reg_rules: ", *policy,
367 		       sizeof(*ptr));
368 	return 0;
369 }
370 
rtw89_acpi_evaluate_dsm(struct rtw89_dev * rtwdev,enum rtw89_acpi_dsm_func func,struct rtw89_acpi_dsm_result * res)371 int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
372 			    enum rtw89_acpi_dsm_func func,
373 			    struct rtw89_acpi_dsm_result *res)
374 {
375 	union acpi_object *obj;
376 	int ret;
377 
378 	obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid,
379 				0, func, NULL);
380 	if (!obj) {
381 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
382 			    "acpi dsm fail to evaluate func: %d\n", func);
383 		return -ENOENT;
384 	}
385 
386 	if (func == RTW89_ACPI_DSM_FUNC_6G_BP)
387 		ret = rtw89_acpi_dsm_get_policy_6ghz(rtwdev, obj,
388 						     &res->u.policy_6ghz);
389 	else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP)
390 		ret = rtw89_acpi_dsm_get_policy_6ghz_sp(rtwdev, obj,
391 							&res->u.policy_6ghz_sp);
392 	else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_VLP_SUP)
393 		ret = rtw89_acpi_dsm_get_policy_6ghz_vlp(rtwdev, obj,
394 							 &res->u.policy_6ghz_vlp);
395 	else if (func == RTW89_ACPI_DSM_FUNC_TAS_EN)
396 		ret = rtw89_acpi_dsm_get_policy_tas(rtwdev, obj, &res->u.policy_tas);
397 	else if (func == RTW89_ACPI_DSM_FUNC_REG_RULES_EN)
398 		ret = rtw89_acpi_dsm_get_policy_reg_rules(rtwdev, obj,
399 							  &res->u.policy_reg_rules);
400 	else
401 		ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value);
402 
403 	ACPI_FREE(obj);
404 	return ret;
405 }
406 
rtw89_acpi_evaluate_rtag(struct rtw89_dev * rtwdev,struct rtw89_acpi_rtag_result * res)407 int rtw89_acpi_evaluate_rtag(struct rtw89_dev *rtwdev,
408 			     struct rtw89_acpi_rtag_result *res)
409 {
410 	const struct rtw89_acpi_data *data;
411 	u32 buf_len;
412 	int ret = 0;
413 
414 	data = rtw89_acpi_evaluate_method(rtwdev, "RTAG");
415 	if (!data)
416 		return -EIO;
417 
418 	buf_len = data->len;
419 	if (buf_len != sizeof(*res)) {
420 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
421 			    __func__, buf_len);
422 		ret = -EINVAL;
423 		goto out;
424 	}
425 
426 	*res = *(struct rtw89_acpi_rtag_result *)data->buf;
427 
428 	rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "antenna_gain: ", res, sizeof(*res));
429 
430 out:
431 	kfree(data);
432 	return ret;
433 }
434 
rtw89_acpi_sar_get_subband(struct rtw89_dev * rtwdev,u32 center_freq)435 enum rtw89_acpi_sar_subband rtw89_acpi_sar_get_subband(struct rtw89_dev *rtwdev,
436 						       u32 center_freq)
437 {
438 	switch (center_freq) {
439 	default:
440 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
441 			    "center freq %u to ACPI SAR subband is unhandled\n",
442 			    center_freq);
443 		fallthrough;
444 	case 2412 ... 2484:
445 		return RTW89_ACPI_SAR_2GHZ_SUBBAND;
446 	case 5180 ... 5240:
447 		return RTW89_ACPI_SAR_5GHZ_SUBBAND_1;
448 	case 5250 ... 5320:
449 		return RTW89_ACPI_SAR_5GHZ_SUBBAND_2;
450 	case 5500 ... 5720:
451 		return RTW89_ACPI_SAR_5GHZ_SUBBAND_2E;
452 	case 5745 ... 5885:
453 		return RTW89_ACPI_SAR_5GHZ_SUBBAND_3_4;
454 	case 5955 ... 6155:
455 		return RTW89_ACPI_SAR_6GHZ_SUBBAND_5_L;
456 	case 6175 ... 6415:
457 		return RTW89_ACPI_SAR_6GHZ_SUBBAND_5_H;
458 	case 6435 ... 6515:
459 		return RTW89_ACPI_SAR_6GHZ_SUBBAND_6;
460 	case 6535 ... 6695:
461 		return RTW89_ACPI_SAR_6GHZ_SUBBAND_7_L;
462 	case 6715 ... 6855:
463 		return RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H;
464 
465 	/* freq 6875 (ch 185, 20MHz) spans RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H
466 	 * and RTW89_ACPI_SAR_6GHZ_SUBBAND_8, so directly describe it with
467 	 * struct rtw89_6ghz_span.
468 	 */
469 
470 	case 6895 ... 7115:
471 		return RTW89_ACPI_SAR_6GHZ_SUBBAND_8;
472 	}
473 }
474 
rtw89_acpi_sar_subband_to_band(struct rtw89_dev * rtwdev,enum rtw89_acpi_sar_subband subband)475 enum rtw89_band rtw89_acpi_sar_subband_to_band(struct rtw89_dev *rtwdev,
476 					       enum rtw89_acpi_sar_subband subband)
477 {
478 	switch (subband) {
479 	default:
480 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
481 			    "ACPI SAR subband %u to band is unhandled\n", subband);
482 		fallthrough;
483 	case RTW89_ACPI_SAR_2GHZ_SUBBAND:
484 		return RTW89_BAND_2G;
485 	case RTW89_ACPI_SAR_5GHZ_SUBBAND_1:
486 		return RTW89_BAND_5G;
487 	case RTW89_ACPI_SAR_5GHZ_SUBBAND_2:
488 		return RTW89_BAND_5G;
489 	case RTW89_ACPI_SAR_5GHZ_SUBBAND_2E:
490 		return RTW89_BAND_5G;
491 	case RTW89_ACPI_SAR_5GHZ_SUBBAND_3_4:
492 		return RTW89_BAND_5G;
493 	case RTW89_ACPI_SAR_6GHZ_SUBBAND_5_L:
494 		return RTW89_BAND_6G;
495 	case RTW89_ACPI_SAR_6GHZ_SUBBAND_5_H:
496 		return RTW89_BAND_6G;
497 	case RTW89_ACPI_SAR_6GHZ_SUBBAND_6:
498 		return RTW89_BAND_6G;
499 	case RTW89_ACPI_SAR_6GHZ_SUBBAND_7_L:
500 		return RTW89_BAND_6G;
501 	case RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H:
502 		return RTW89_BAND_6G;
503 	case RTW89_ACPI_SAR_6GHZ_SUBBAND_8:
504 		return RTW89_BAND_6G;
505 	}
506 }
507 
rtw89_acpi_sar_rfpath_to_hp_antidx(enum rtw89_rf_path rfpath)508 static u8 rtw89_acpi_sar_rfpath_to_hp_antidx(enum rtw89_rf_path rfpath)
509 {
510 	switch (rfpath) {
511 	default:
512 	case RF_PATH_B:
513 		return 0;
514 	case RF_PATH_A:
515 		return 1;
516 	}
517 }
518 
rtw89_acpi_sar_rfpath_to_rt_antidx(enum rtw89_rf_path rfpath)519 static u8 rtw89_acpi_sar_rfpath_to_rt_antidx(enum rtw89_rf_path rfpath)
520 {
521 	switch (rfpath) {
522 	default:
523 	case RF_PATH_A:
524 		return 0;
525 	case RF_PATH_B:
526 		return 1;
527 	}
528 }
529 
rtw89_acpi_sar_normalize_hp_val(u8 v)530 static s16 rtw89_acpi_sar_normalize_hp_val(u8 v)
531 {
532 	static const u8 bias = 10;
533 	static const u8 fct = 1;
534 	u16 res;
535 
536 	BUILD_BUG_ON(fct > TXPWR_FACTOR_OF_RTW89_ACPI_SAR);
537 
538 	res = (bias << TXPWR_FACTOR_OF_RTW89_ACPI_SAR) +
539 	      (v << (TXPWR_FACTOR_OF_RTW89_ACPI_SAR - fct));
540 
541 	return min_t(s32, res, MAX_VAL_OF_RTW89_ACPI_SAR);
542 }
543 
rtw89_acpi_sar_normalize_rt_val(u8 v)544 static s16 rtw89_acpi_sar_normalize_rt_val(u8 v)
545 {
546 	static const u8 fct = 3;
547 	u16 res;
548 
549 	BUILD_BUG_ON(fct > TXPWR_FACTOR_OF_RTW89_ACPI_SAR);
550 
551 	res = v << (TXPWR_FACTOR_OF_RTW89_ACPI_SAR - fct);
552 
553 	return min_t(s32, res, MAX_VAL_OF_RTW89_ACPI_SAR);
554 }
555 
556 static
rtw89_acpi_sar_load_std_legacy(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_recognition * rec,const void * content,struct rtw89_sar_entry_from_acpi * ent)557 void rtw89_acpi_sar_load_std_legacy(struct rtw89_dev *rtwdev,
558 				    const struct rtw89_acpi_sar_recognition *rec,
559 				    const void *content,
560 				    struct rtw89_sar_entry_from_acpi *ent)
561 {
562 	const struct rtw89_acpi_sar_std_legacy *ptr = content;
563 	enum rtw89_acpi_sar_subband subband;
564 	enum rtw89_rf_path path;
565 
566 	for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
567 		for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
568 			u8 antidx = rec->rfpath_to_antidx(path);
569 
570 			if (subband < RTW89_ACPI_SAR_SUBBAND_NR_LEGACY)
571 				ent->v[subband][path] =
572 					rec->normalize(ptr->v[antidx][subband]);
573 			else
574 				ent->v[subband][path] = MAX_VAL_OF_RTW89_ACPI_SAR;
575 		}
576 	}
577 }
578 
579 static
rtw89_acpi_sar_load_std_has_6ghz(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_recognition * rec,const void * content,struct rtw89_sar_entry_from_acpi * ent)580 void rtw89_acpi_sar_load_std_has_6ghz(struct rtw89_dev *rtwdev,
581 				      const struct rtw89_acpi_sar_recognition *rec,
582 				      const void *content,
583 				      struct rtw89_sar_entry_from_acpi *ent)
584 {
585 	const struct rtw89_acpi_sar_std_has_6ghz *ptr = content;
586 	enum rtw89_acpi_sar_subband subband;
587 	enum rtw89_rf_path path;
588 
589 	BUILD_BUG_ON(RTW89_ACPI_SAR_SUBBAND_NR_HAS_6GHZ != NUM_OF_RTW89_ACPI_SAR_SUBBAND);
590 
591 	for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
592 		for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
593 			u8 antidx = rec->rfpath_to_antidx(path);
594 
595 			ent->v[subband][path] = rec->normalize(ptr->v[antidx][subband]);
596 		}
597 	}
598 }
599 
600 static
rtw89_acpi_sar_load_sml_legacy(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_recognition * rec,const void * content,struct rtw89_sar_entry_from_acpi * ent)601 void rtw89_acpi_sar_load_sml_legacy(struct rtw89_dev *rtwdev,
602 				    const struct rtw89_acpi_sar_recognition *rec,
603 				    const void *content,
604 				    struct rtw89_sar_entry_from_acpi *ent)
605 {
606 	const struct rtw89_acpi_sar_sml_legacy *ptr = content;
607 	enum rtw89_acpi_sar_subband subband;
608 	enum rtw89_rf_path path;
609 
610 	for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
611 		for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
612 			u8 antidx = rec->rfpath_to_antidx(path);
613 
614 			if (subband < RTW89_ACPI_SAR_SUBBAND_NR_LEGACY)
615 				ent->v[subband][path] =
616 					rec->normalize(ptr->v[antidx][subband]);
617 			else
618 				ent->v[subband][path] = MAX_VAL_OF_RTW89_ACPI_SAR;
619 		}
620 	}
621 }
622 
623 static
rtw89_acpi_sar_load_sml_has_6ghz(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_recognition * rec,const void * content,struct rtw89_sar_entry_from_acpi * ent)624 void rtw89_acpi_sar_load_sml_has_6ghz(struct rtw89_dev *rtwdev,
625 				      const struct rtw89_acpi_sar_recognition *rec,
626 				      const void *content,
627 				      struct rtw89_sar_entry_from_acpi *ent)
628 {
629 	const struct rtw89_acpi_sar_sml_has_6ghz *ptr = content;
630 	enum rtw89_acpi_sar_subband subband;
631 	enum rtw89_rf_path path;
632 
633 	BUILD_BUG_ON(RTW89_ACPI_SAR_SUBBAND_NR_HAS_6GHZ != NUM_OF_RTW89_ACPI_SAR_SUBBAND);
634 
635 	for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
636 		for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
637 			u8 antidx = rec->rfpath_to_antidx(path);
638 
639 			ent->v[subband][path] = rec->normalize(ptr->v[antidx][subband]);
640 		}
641 	}
642 }
643 
rtw89_acpi_geo_sar_normalize_delta(s8 delta)644 static s16 rtw89_acpi_geo_sar_normalize_delta(s8 delta)
645 {
646 	static const u8 fct = 1;
647 
648 	BUILD_BUG_ON(fct > TXPWR_FACTOR_OF_RTW89_ACPI_SAR);
649 
650 	return delta << (TXPWR_FACTOR_OF_RTW89_ACPI_SAR - fct);
651 }
652 
653 static enum rtw89_acpi_geo_sar_regd_hp
rtw89_acpi_geo_sar_regd_convert_hp_idx(enum rtw89_regulation_type regd)654 rtw89_acpi_geo_sar_regd_convert_hp_idx(enum rtw89_regulation_type regd)
655 {
656 	switch (regd) {
657 	case RTW89_FCC:
658 	case RTW89_IC:
659 	case RTW89_NCC:
660 	case RTW89_CHILE:
661 	case RTW89_MEXICO:
662 		return RTW89_ACPI_GEO_SAR_REGD_HP_FCC;
663 	case RTW89_ETSI:
664 	case RTW89_MKK:
665 	case RTW89_ACMA:
666 		return RTW89_ACPI_GEO_SAR_REGD_HP_ETSI;
667 	default:
668 	case RTW89_WW:
669 	case RTW89_NA:
670 	case RTW89_KCC:
671 		return RTW89_ACPI_GEO_SAR_REGD_HP_WW;
672 	}
673 }
674 
675 static enum rtw89_acpi_geo_sar_regd_rt
rtw89_acpi_geo_sar_regd_convert_rt_idx(enum rtw89_regulation_type regd)676 rtw89_acpi_geo_sar_regd_convert_rt_idx(enum rtw89_regulation_type regd)
677 {
678 	switch (regd) {
679 	case RTW89_FCC:
680 	case RTW89_NCC:
681 	case RTW89_CHILE:
682 	case RTW89_MEXICO:
683 		return RTW89_ACPI_GEO_SAR_REGD_RT_FCC;
684 	case RTW89_ETSI:
685 	case RTW89_ACMA:
686 		return RTW89_ACPI_GEO_SAR_REGD_RT_ETSI;
687 	case RTW89_MKK:
688 		return RTW89_ACPI_GEO_SAR_REGD_RT_MKK;
689 	case RTW89_IC:
690 		return RTW89_ACPI_GEO_SAR_REGD_RT_IC;
691 	case RTW89_KCC:
692 		return RTW89_ACPI_GEO_SAR_REGD_RT_KCC;
693 	default:
694 	case RTW89_WW:
695 	case RTW89_NA:
696 		return RTW89_ACPI_GEO_SAR_REGD_RT_WW;
697 	}
698 }
699 
700 static
rtw89_acpi_geo_sar_load_by_hp(struct rtw89_dev * rtwdev,const struct rtw89_acpi_geo_sar_hp_val * ptr,enum rtw89_rf_path path,s16 * val)701 void rtw89_acpi_geo_sar_load_by_hp(struct rtw89_dev *rtwdev,
702 				   const struct rtw89_acpi_geo_sar_hp_val *ptr,
703 				   enum rtw89_rf_path path, s16 *val)
704 {
705 	u8 antidx = rtw89_acpi_sar_rfpath_to_hp_antidx(path);
706 	s16 delta = rtw89_acpi_geo_sar_normalize_delta(ptr->delta[antidx]);
707 	s16 max = rtw89_acpi_sar_normalize_hp_val(ptr->max);
708 
709 	*val = clamp_t(s32, (*val) + delta, MIN_VAL_OF_RTW89_ACPI_SAR, max);
710 }
711 
712 static
rtw89_acpi_geo_sar_load_by_rt(struct rtw89_dev * rtwdev,const struct rtw89_acpi_geo_sar_rt_val * ptr,s16 * val)713 void rtw89_acpi_geo_sar_load_by_rt(struct rtw89_dev *rtwdev,
714 				   const struct rtw89_acpi_geo_sar_rt_val *ptr,
715 				   s16 *val)
716 {
717 	s16 delta = rtw89_acpi_geo_sar_normalize_delta(ptr->delta);
718 	s16 max = rtw89_acpi_sar_normalize_rt_val(ptr->max);
719 
720 	*val = clamp_t(s32, (*val) + delta, MIN_VAL_OF_RTW89_ACPI_SAR, max);
721 }
722 
723 static
rtw89_acpi_geo_sar_load_hp_legacy(struct rtw89_dev * rtwdev,const void * content,enum rtw89_regulation_type regd,struct rtw89_sar_entry_from_acpi * ent)724 void rtw89_acpi_geo_sar_load_hp_legacy(struct rtw89_dev *rtwdev,
725 				       const void *content,
726 				       enum rtw89_regulation_type regd,
727 				       struct rtw89_sar_entry_from_acpi *ent)
728 {
729 	const struct rtw89_acpi_geo_sar_hp_legacy *ptr = content;
730 	const struct rtw89_acpi_geo_sar_hp_legacy_entry *ptr_ent;
731 	const struct rtw89_acpi_geo_sar_hp_val *ptr_ent_val;
732 	enum rtw89_acpi_geo_sar_regd_hp geo_idx =
733 		rtw89_acpi_geo_sar_regd_convert_hp_idx(regd);
734 	enum rtw89_acpi_sar_subband subband;
735 	enum rtw89_rf_path path;
736 	enum rtw89_band band;
737 
738 	ptr_ent = &ptr->entries[geo_idx];
739 
740 	for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
741 		band = rtw89_acpi_sar_subband_to_band(rtwdev, subband);
742 		switch (band) {
743 		case RTW89_BAND_2G:
744 			ptr_ent_val = &ptr_ent->val_2ghz;
745 			break;
746 		case RTW89_BAND_5G:
747 			ptr_ent_val = &ptr_ent->val_5ghz;
748 			break;
749 		default:
750 		case RTW89_BAND_6G:
751 			ptr_ent_val = NULL;
752 			break;
753 		}
754 
755 		if (!ptr_ent_val)
756 			continue;
757 
758 		for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++)
759 			rtw89_acpi_geo_sar_load_by_hp(rtwdev, ptr_ent_val, path,
760 						      &ent->v[subband][path]);
761 	}
762 }
763 
764 static
rtw89_acpi_geo_sar_load_hp_has_6ghz(struct rtw89_dev * rtwdev,const void * content,enum rtw89_regulation_type regd,struct rtw89_sar_entry_from_acpi * ent)765 void rtw89_acpi_geo_sar_load_hp_has_6ghz(struct rtw89_dev *rtwdev,
766 					 const void *content,
767 					 enum rtw89_regulation_type regd,
768 					 struct rtw89_sar_entry_from_acpi *ent)
769 {
770 	const struct rtw89_acpi_geo_sar_hp_has_6ghz *ptr = content;
771 	const struct rtw89_acpi_geo_sar_hp_has_6ghz_entry *ptr_ent;
772 	const struct rtw89_acpi_geo_sar_hp_val *ptr_ent_val;
773 	enum rtw89_acpi_geo_sar_regd_hp geo_idx =
774 		rtw89_acpi_geo_sar_regd_convert_hp_idx(regd);
775 	enum rtw89_acpi_sar_subband subband;
776 	enum rtw89_rf_path path;
777 	enum rtw89_band band;
778 
779 	ptr_ent = &ptr->entries[geo_idx];
780 
781 	for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
782 		band = rtw89_acpi_sar_subband_to_band(rtwdev, subband);
783 		switch (band) {
784 		case RTW89_BAND_2G:
785 			ptr_ent_val = &ptr_ent->val_2ghz;
786 			break;
787 		case RTW89_BAND_5G:
788 			ptr_ent_val = &ptr_ent->val_5ghz;
789 			break;
790 		case RTW89_BAND_6G:
791 			ptr_ent_val = &ptr_ent->val_6ghz;
792 			break;
793 		default:
794 			ptr_ent_val = NULL;
795 			break;
796 		}
797 
798 		if (!ptr_ent_val)
799 			continue;
800 
801 		for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++)
802 			rtw89_acpi_geo_sar_load_by_hp(rtwdev, ptr_ent_val, path,
803 						      &ent->v[subband][path]);
804 	}
805 }
806 
807 static
rtw89_acpi_geo_sar_load_rt_legacy(struct rtw89_dev * rtwdev,const void * content,enum rtw89_regulation_type regd,struct rtw89_sar_entry_from_acpi * ent)808 void rtw89_acpi_geo_sar_load_rt_legacy(struct rtw89_dev *rtwdev,
809 				       const void *content,
810 				       enum rtw89_regulation_type regd,
811 				       struct rtw89_sar_entry_from_acpi *ent)
812 {
813 	const struct rtw89_acpi_geo_sar_rt_legacy *ptr = content;
814 	const struct rtw89_acpi_geo_sar_rt_legacy_entry *ptr_ent;
815 	const struct rtw89_acpi_geo_sar_rt_val *ptr_ent_val;
816 	enum rtw89_acpi_geo_sar_regd_rt geo_idx =
817 		rtw89_acpi_geo_sar_regd_convert_rt_idx(regd);
818 	enum rtw89_acpi_sar_subband subband;
819 	enum rtw89_rf_path path;
820 	enum rtw89_band band;
821 
822 	ptr_ent = &ptr->entries[geo_idx];
823 
824 	for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
825 		band = rtw89_acpi_sar_subband_to_band(rtwdev, subband);
826 		switch (band) {
827 		case RTW89_BAND_2G:
828 			ptr_ent_val = &ptr_ent->val_2ghz;
829 			break;
830 		case RTW89_BAND_5G:
831 			ptr_ent_val = &ptr_ent->val_5ghz;
832 			break;
833 		default:
834 		case RTW89_BAND_6G:
835 			ptr_ent_val = NULL;
836 			break;
837 		}
838 
839 		if (!ptr_ent_val)
840 			continue;
841 
842 		for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++)
843 			rtw89_acpi_geo_sar_load_by_rt(rtwdev, ptr_ent_val,
844 						      &ent->v[subband][path]);
845 	}
846 }
847 
848 static
rtw89_acpi_geo_sar_load_rt_has_6ghz(struct rtw89_dev * rtwdev,const void * content,enum rtw89_regulation_type regd,struct rtw89_sar_entry_from_acpi * ent)849 void rtw89_acpi_geo_sar_load_rt_has_6ghz(struct rtw89_dev *rtwdev,
850 					 const void *content,
851 					 enum rtw89_regulation_type regd,
852 					 struct rtw89_sar_entry_from_acpi *ent)
853 {
854 	const struct rtw89_acpi_geo_sar_rt_has_6ghz *ptr = content;
855 	const struct rtw89_acpi_geo_sar_rt_has_6ghz_entry *ptr_ent;
856 	const struct rtw89_acpi_geo_sar_rt_val *ptr_ent_val;
857 	enum rtw89_acpi_geo_sar_regd_rt geo_idx =
858 		rtw89_acpi_geo_sar_regd_convert_rt_idx(regd);
859 	enum rtw89_acpi_sar_subband subband;
860 	enum rtw89_rf_path path;
861 	enum rtw89_band band;
862 
863 	ptr_ent = &ptr->entries[geo_idx];
864 
865 	for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
866 		band = rtw89_acpi_sar_subband_to_band(rtwdev, subband);
867 		switch (band) {
868 		case RTW89_BAND_2G:
869 			ptr_ent_val = &ptr_ent->val_2ghz;
870 			break;
871 		case RTW89_BAND_5G:
872 			ptr_ent_val = &ptr_ent->val_5ghz;
873 			break;
874 		case RTW89_BAND_6G:
875 			ptr_ent_val = &ptr_ent->val_6ghz;
876 			break;
877 		default:
878 			ptr_ent_val = NULL;
879 			break;
880 		}
881 
882 		if (!ptr_ent_val)
883 			continue;
884 
885 		for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++)
886 			rtw89_acpi_geo_sar_load_by_rt(rtwdev, ptr_ent_val,
887 						      &ent->v[subband][path]);
888 	}
889 }
890 
891 #define RTW89_ACPI_GEO_SAR_DECL_HANDLER(type) \
892 static const struct rtw89_acpi_geo_sar_handler \
893 rtw89_acpi_geo_sar_handler_ ## type = { \
894 	.data_size = RTW89_ACPI_GEO_SAR_SIZE_OF(type), \
895 	.load = rtw89_acpi_geo_sar_load_ ## type, \
896 }
897 
898 RTW89_ACPI_GEO_SAR_DECL_HANDLER(hp_legacy);
899 RTW89_ACPI_GEO_SAR_DECL_HANDLER(hp_has_6ghz);
900 RTW89_ACPI_GEO_SAR_DECL_HANDLER(rt_legacy);
901 RTW89_ACPI_GEO_SAR_DECL_HANDLER(rt_has_6ghz);
902 
903 static const struct rtw89_acpi_sar_recognition rtw89_acpi_sar_recs[] = {
904 	{
905 		.id = {
906 			.cid = RTW89_ACPI_SAR_CID_HP,
907 			.rev = RTW89_ACPI_SAR_REV_LEGACY,
908 			.size = RTW89_ACPI_SAR_SIZE_OF(std_legacy),
909 		},
910 		.geo = &rtw89_acpi_geo_sar_handler_hp_legacy,
911 
912 		.rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_hp_antidx,
913 		.normalize = rtw89_acpi_sar_normalize_hp_val,
914 		.load = rtw89_acpi_sar_load_std_legacy,
915 	},
916 	{
917 		.id = {
918 			.cid = RTW89_ACPI_SAR_CID_HP,
919 			.rev = RTW89_ACPI_SAR_REV_HAS_6GHZ,
920 			.size = RTW89_ACPI_SAR_SIZE_OF(std_has_6ghz),
921 		},
922 		.geo = &rtw89_acpi_geo_sar_handler_hp_has_6ghz,
923 
924 		.rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_hp_antidx,
925 		.normalize = rtw89_acpi_sar_normalize_hp_val,
926 		.load = rtw89_acpi_sar_load_std_has_6ghz,
927 	},
928 	{
929 		.id = {
930 			.cid = RTW89_ACPI_SAR_CID_RT,
931 			.rev = RTW89_ACPI_SAR_REV_LEGACY,
932 			.size = RTW89_ACPI_SAR_SIZE_OF(std_legacy),
933 		},
934 		.geo = &rtw89_acpi_geo_sar_handler_rt_legacy,
935 
936 		.rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_rt_antidx,
937 		.normalize = rtw89_acpi_sar_normalize_rt_val,
938 		.load = rtw89_acpi_sar_load_std_legacy,
939 	},
940 	{
941 		.id = {
942 			.cid = RTW89_ACPI_SAR_CID_RT,
943 			.rev = RTW89_ACPI_SAR_REV_HAS_6GHZ,
944 			.size = RTW89_ACPI_SAR_SIZE_OF(std_has_6ghz),
945 		},
946 		.geo = &rtw89_acpi_geo_sar_handler_rt_has_6ghz,
947 
948 		.rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_rt_antidx,
949 		.normalize = rtw89_acpi_sar_normalize_rt_val,
950 		.load = rtw89_acpi_sar_load_std_has_6ghz,
951 	},
952 	{
953 		.id = {
954 			.cid = RTW89_ACPI_SAR_CID_RT,
955 			.rev = RTW89_ACPI_SAR_REV_LEGACY,
956 			.size = RTW89_ACPI_SAR_SIZE_OF(sml_legacy),
957 		},
958 		.geo = &rtw89_acpi_geo_sar_handler_rt_legacy,
959 
960 		.rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_rt_antidx,
961 		.normalize = rtw89_acpi_sar_normalize_rt_val,
962 		.load = rtw89_acpi_sar_load_sml_legacy,
963 	},
964 	{
965 		.id = {
966 			.cid = RTW89_ACPI_SAR_CID_RT,
967 			.rev = RTW89_ACPI_SAR_REV_HAS_6GHZ,
968 			.size = RTW89_ACPI_SAR_SIZE_OF(sml_has_6ghz),
969 		},
970 		.geo = &rtw89_acpi_geo_sar_handler_rt_has_6ghz,
971 
972 		.rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_rt_antidx,
973 		.normalize = rtw89_acpi_sar_normalize_rt_val,
974 		.load = rtw89_acpi_sar_load_sml_has_6ghz,
975 	},
976 };
977 
978 struct rtw89_acpi_sar_rec_parm {
979 	u32 pld_len;
980 	u8 tbl_cnt;
981 	u16 cid;
982 	u8 rev;
983 };
984 
985 static const struct rtw89_acpi_sar_recognition *
rtw89_acpi_sar_recognize(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_rec_parm * parm)986 rtw89_acpi_sar_recognize(struct rtw89_dev *rtwdev,
987 			 const struct rtw89_acpi_sar_rec_parm *parm)
988 {
989 	const u32 tbl_len = parm->pld_len / parm->tbl_cnt;
990 	const struct rtw89_acpi_sar_recognition *rec;
991 	struct rtw89_acpi_sar_identifier id = {};
992 
993 	rtw89_debug(rtwdev, RTW89_DBG_ACPI,
994 		    "%s: cid %u, rev %u, tbl len %u, tbl cnt %u\n",
995 		    __func__, parm->cid, parm->rev, tbl_len, parm->tbl_cnt);
996 
997 	if (unlikely(parm->pld_len % parm->tbl_cnt)) {
998 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid pld len %u\n",
999 			    parm->pld_len);
1000 		return NULL;
1001 	}
1002 
1003 	if (unlikely(tbl_len > RTW89_ACPI_SAR_SIZE_MAX)) {
1004 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid tbl len %u\n",
1005 			    tbl_len);
1006 		return NULL;
1007 	}
1008 
1009 	if (unlikely(parm->tbl_cnt > MAX_NUM_OF_RTW89_ACPI_SAR_TBL)) {
1010 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid tbl cnt %u\n",
1011 			    parm->tbl_cnt);
1012 		return NULL;
1013 	}
1014 
1015 	switch (parm->cid) {
1016 	case RTW89_ACPI_SAR_CID_HP:
1017 	case RTW89_ACPI_SAR_CID_RT:
1018 		id.cid = parm->cid;
1019 		break;
1020 	default:
1021 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid cid 0x%x\n",
1022 			    parm->cid);
1023 		return NULL;
1024 	}
1025 
1026 	switch (parm->rev) {
1027 	case RTW89_ACPI_SAR_REV_LEGACY:
1028 	case RTW89_ACPI_SAR_REV_HAS_6GHZ:
1029 		id.rev = parm->rev;
1030 		break;
1031 	default:
1032 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid rev %u\n",
1033 			    parm->rev);
1034 		return NULL;
1035 	}
1036 
1037 	id.size = tbl_len;
1038 	for (unsigned int i = 0; i < ARRAY_SIZE(rtw89_acpi_sar_recs); i++) {
1039 		rec = &rtw89_acpi_sar_recs[i];
1040 		if (memcmp(&rec->id, &id, sizeof(rec->id)) == 0)
1041 			return rec;
1042 	}
1043 
1044 	rtw89_debug(rtwdev, RTW89_DBG_ACPI, "failed to recognize\n");
1045 	return NULL;
1046 }
1047 
1048 static const struct rtw89_acpi_sar_recognition *
rtw89_acpi_evaluate_static_sar(struct rtw89_dev * rtwdev,struct rtw89_sar_cfg_acpi * cfg)1049 rtw89_acpi_evaluate_static_sar(struct rtw89_dev *rtwdev,
1050 			       struct rtw89_sar_cfg_acpi *cfg)
1051 {
1052 	const struct rtw89_acpi_sar_recognition *rec = NULL;
1053 	const struct rtw89_acpi_static_sar_hdr *hdr;
1054 	struct rtw89_sar_entry_from_acpi tmp = {};
1055 	struct rtw89_acpi_sar_rec_parm parm = {};
1056 	struct rtw89_sar_table_from_acpi *tbl;
1057 	const struct rtw89_acpi_data *data;
1058 	u32 len;
1059 
1060 	data = rtw89_acpi_evaluate_method(rtwdev, RTW89_ACPI_METHOD_STATIC_SAR);
1061 	if (!data)
1062 		return NULL;
1063 
1064 	rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi load static sar\n");
1065 
1066 	len = data->len;
1067 	if (len <= sizeof(*hdr)) {
1068 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid buf len %u\n", len);
1069 		goto out;
1070 	}
1071 
1072 	hdr = (typeof(hdr))data->buf;
1073 
1074 	parm.cid = le16_to_cpu(hdr->cid);
1075 	parm.rev = hdr->rev;
1076 	parm.tbl_cnt = 1;
1077 	parm.pld_len = len - sizeof(*hdr);
1078 
1079 	rec = rtw89_acpi_sar_recognize(rtwdev, &parm);
1080 	if (!rec)
1081 		goto out;
1082 
1083 	rec->load(rtwdev, rec, hdr->content, &tmp);
1084 
1085 	tbl = &cfg->tables[0];
1086 	for (u8 regd = 0; regd < RTW89_REGD_NUM; regd++)
1087 		tbl->entries[regd] = tmp;
1088 
1089 	cfg->valid_num = 1;
1090 
1091 out:
1092 	kfree(data);
1093 	return rec;
1094 }
1095 
1096 static const struct rtw89_acpi_sar_recognition *
rtw89_acpi_evaluate_dynamic_sar(struct rtw89_dev * rtwdev,struct rtw89_sar_cfg_acpi * cfg)1097 rtw89_acpi_evaluate_dynamic_sar(struct rtw89_dev *rtwdev,
1098 				struct rtw89_sar_cfg_acpi *cfg)
1099 {
1100 	const struct rtw89_acpi_sar_recognition *rec = NULL;
1101 	const struct rtw89_acpi_dynamic_sar_hdr *hdr;
1102 	struct rtw89_acpi_sar_rec_parm parm = {};
1103 	struct rtw89_sar_table_from_acpi *tbl;
1104 	const struct rtw89_acpi_data *data;
1105 	u32 len;
1106 
1107 	data = rtw89_acpi_evaluate_method(rtwdev, RTW89_ACPI_METHOD_DYNAMIC_SAR);
1108 	if (!data)
1109 		return NULL;
1110 
1111 	rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi load dynamic sar\n");
1112 
1113 	len = data->len;
1114 	if (len <= sizeof(*hdr)) {
1115 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid buf len %u\n", len);
1116 		goto out;
1117 	}
1118 
1119 	hdr = (typeof(hdr))data->buf;
1120 
1121 	parm.cid = le16_to_cpu(hdr->cid);
1122 	parm.rev = hdr->rev;
1123 	parm.tbl_cnt = hdr->cnt;
1124 	parm.pld_len = len - sizeof(*hdr);
1125 
1126 	rec = rtw89_acpi_sar_recognize(rtwdev, &parm);
1127 	if (!rec)
1128 		goto out;
1129 
1130 	for (unsigned int i = 0; i < hdr->cnt; i++) {
1131 		const u8 *content = hdr->content + rec->id.size * i;
1132 		struct rtw89_sar_entry_from_acpi tmp = {};
1133 
1134 		rec->load(rtwdev, rec, content, &tmp);
1135 
1136 		tbl = &cfg->tables[i];
1137 		for (u8 regd = 0; regd < RTW89_REGD_NUM; regd++)
1138 			tbl->entries[regd] = tmp;
1139 	}
1140 
1141 	cfg->valid_num = hdr->cnt;
1142 
1143 out:
1144 	kfree(data);
1145 	return rec;
1146 }
1147 
rtw89_acpi_evaluate_dynamic_sar_indicator(struct rtw89_dev * rtwdev,struct rtw89_sar_cfg_acpi * cfg,bool * poll_changed)1148 int rtw89_acpi_evaluate_dynamic_sar_indicator(struct rtw89_dev *rtwdev,
1149 					      struct rtw89_sar_cfg_acpi *cfg,
1150 					      bool *poll_changed)
1151 {
1152 	struct rtw89_sar_indicator_from_acpi *ind = &cfg->indicator;
1153 	struct rtw89_sar_indicator_from_acpi tmp = *ind;
1154 	const struct rtw89_acpi_data *data;
1155 	const u8 *tbl_base1_by_ant;
1156 	enum rtw89_rf_path path;
1157 	int ret = 0;
1158 	u32 len;
1159 
1160 	data = rtw89_acpi_evaluate_method(rtwdev, RTW89_ACPI_METHOD_DYNAMIC_SAR_INDICATOR);
1161 	if (!data)
1162 		return -EFAULT;
1163 
1164 	if (!poll_changed)
1165 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi load dynamic sar indicator\n");
1166 
1167 	len = data->len;
1168 	if (len != ind->fields) {
1169 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid buf len %u\n", len);
1170 		ret = -EINVAL;
1171 		goto out;
1172 	}
1173 
1174 	tbl_base1_by_ant = data->buf;
1175 
1176 	for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
1177 		u8 antidx = ind->rfpath_to_antidx(path);
1178 		u8 sel;
1179 
1180 		if (antidx >= ind->fields)
1181 			antidx = 0;
1182 
1183 		/* convert the table index from 1-based to 0-based */
1184 		sel = tbl_base1_by_ant[antidx] - 1;
1185 		if (sel >= cfg->valid_num)
1186 			sel = 0;
1187 
1188 		tmp.tblsel[path] = sel;
1189 	}
1190 
1191 	if (memcmp(ind, &tmp, sizeof(*ind)) == 0) {
1192 		if (poll_changed)
1193 			*poll_changed = false;
1194 	} else {
1195 		if (poll_changed)
1196 			*poll_changed = true;
1197 
1198 		*ind = tmp;
1199 	}
1200 
1201 out:
1202 	kfree(data);
1203 	return ret;
1204 }
1205 
1206 static
rtw89_acpi_evaluate_geo_sar(struct rtw89_dev * rtwdev,const struct rtw89_acpi_geo_sar_handler * hdl,struct rtw89_sar_cfg_acpi * cfg)1207 void rtw89_acpi_evaluate_geo_sar(struct rtw89_dev *rtwdev,
1208 				 const struct rtw89_acpi_geo_sar_handler *hdl,
1209 				 struct rtw89_sar_cfg_acpi *cfg)
1210 {
1211 	const struct rtw89_acpi_data *data;
1212 	u32 len;
1213 
1214 	data = rtw89_acpi_evaluate_method(rtwdev, RTW89_ACPI_METHOD_GEO_SAR);
1215 	if (!data)
1216 		return;
1217 
1218 	rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi load geo sar\n");
1219 
1220 	len = data->len;
1221 	if (len != hdl->data_size) {
1222 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid buf len %u (expected %u)\n",
1223 			    len, hdl->data_size);
1224 		goto out;
1225 	}
1226 
1227 	for (unsigned int i = 0; i < cfg->valid_num; i++)
1228 		for (u8 regd = 0; regd < RTW89_REGD_NUM; regd++)
1229 			hdl->load(rtwdev, data->buf, regd, &cfg->tables[i].entries[regd]);
1230 
1231 out:
1232 	kfree(data);
1233 }
1234 
rtw89_acpi_evaluate_sar(struct rtw89_dev * rtwdev,struct rtw89_sar_cfg_acpi * cfg)1235 int rtw89_acpi_evaluate_sar(struct rtw89_dev *rtwdev,
1236 			    struct rtw89_sar_cfg_acpi *cfg)
1237 {
1238 	struct rtw89_sar_indicator_from_acpi *ind = &cfg->indicator;
1239 	const struct rtw89_acpi_sar_recognition *rec;
1240 	bool fetch_indicator = false;
1241 	int ret;
1242 
1243 	rec = rtw89_acpi_evaluate_static_sar(rtwdev, cfg);
1244 	if (rec)
1245 		goto recognized;
1246 
1247 	rec = rtw89_acpi_evaluate_dynamic_sar(rtwdev, cfg);
1248 	if (!rec)
1249 		return -ENOENT;
1250 
1251 	fetch_indicator = true;
1252 
1253 recognized:
1254 	rtw89_acpi_evaluate_geo_sar(rtwdev, rec->geo, cfg);
1255 
1256 	switch (rec->id.cid) {
1257 	case RTW89_ACPI_SAR_CID_HP:
1258 		cfg->downgrade_2tx = 3 << TXPWR_FACTOR_OF_RTW89_ACPI_SAR;
1259 		ind->fields = RTW89_ACPI_SAR_ANT_NR_STD;
1260 		break;
1261 	case RTW89_ACPI_SAR_CID_RT:
1262 		cfg->downgrade_2tx = 0;
1263 		ind->fields = 1;
1264 		break;
1265 	default:
1266 		return -EFAULT;
1267 	}
1268 
1269 	if (fetch_indicator) {
1270 		ind->rfpath_to_antidx = rec->rfpath_to_antidx;
1271 		ret = rtw89_acpi_evaluate_dynamic_sar_indicator(rtwdev, cfg, NULL);
1272 		if (ret)
1273 			fetch_indicator = false;
1274 	}
1275 
1276 	if (!fetch_indicator)
1277 		memset(ind->tblsel, 0, sizeof(ind->tblsel));
1278 
1279 	ind->enable_sync = fetch_indicator;
1280 	return 0;
1281 }
1282