File Index
Files and directories
Sign in
FILE

acpi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/realtek/rtw89/acpi.c C
   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
  11static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
  12					   0x82, 0xBD, 0xFE, 0x86,
  13					   0x07, 0x80, 0x3A, 0xA7);
  14
  15static 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
  69err:
  70	return 0;
  71}
  72
  73static 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
  79static struct rtw89_acpi_data *
  80rtw89_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
 125out:
 126	ACPI_FREE(obj);
 127	return data;
 128}
 129
 130static
 131int 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
 144static 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
 151static
 152int 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
 195static 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
 203static
 204int 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
 239static 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
 247static
 248int 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
 283static 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
 291static 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
 326static
 327bool 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
 335static
 336int 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
 371int 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
 407int 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
 430out:
 431	kfree(data);
 432	return ret;
 433}
 434
 435enum 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
 475enum 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
 508static 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
 519static 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
 530static 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
 544static 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
 556static
 557void 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
 579static
 580void 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
 600static
 601void 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
 623static
 624void 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
 644static 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
 653static enum rtw89_acpi_geo_sar_regd_hp
 654rtw89_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
 675static enum rtw89_acpi_geo_sar_regd_rt
 676rtw89_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
 700static
 701void 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
 712static
 713void 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
 723static
 724void 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
 764static
 765void 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
 807static
 808void 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
 848static
 849void 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) \
 892static const struct rtw89_acpi_geo_sar_handler \
 893rtw89_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
 898RTW89_ACPI_GEO_SAR_DECL_HANDLER(hp_legacy);
 899RTW89_ACPI_GEO_SAR_DECL_HANDLER(hp_has_6ghz);
 900RTW89_ACPI_GEO_SAR_DECL_HANDLER(rt_legacy);
 901RTW89_ACPI_GEO_SAR_DECL_HANDLER(rt_has_6ghz);
 902
 903static 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
 978struct rtw89_acpi_sar_rec_parm {
 979	u32 pld_len;
 980	u8 tbl_cnt;
 981	u16 cid;
 982	u8 rev;
 983};
 984
 985static const struct rtw89_acpi_sar_recognition *
 986rtw89_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
1048static const struct rtw89_acpi_sar_recognition *
1049rtw89_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
1091out:
1092	kfree(data);
1093	return rec;
1094}
1095
1096static const struct rtw89_acpi_sar_recognition *
1097rtw89_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
1143out:
1144	kfree(data);
1145	return rec;
1146}
1147
1148int 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
1201out:
1202	kfree(data);
1203	return ret;
1204}
1205
1206static
1207void 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
1231out:
1232	kfree(data);
1233}
1234
1235int 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
1253recognized:
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}
~/ Read-only file preview.