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