2024-04-22 11:30:50 +08:00
|
|
|
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
2025-01-13 15:48:07 +08:00
|
|
|
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
2024-04-22 11:30:50 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "core.h"
|
|
|
|
#include "acpi.h"
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func)
|
|
|
|
{
|
|
|
|
union acpi_object *obj;
|
|
|
|
acpi_handle root_handle;
|
2025-01-13 15:48:07 +08:00
|
|
|
int ret, i;
|
2024-04-22 11:30:50 +08:00
|
|
|
|
|
|
|
root_handle = ACPI_HANDLE(ab->dev);
|
|
|
|
if (!root_handle) {
|
|
|
|
ath12k_dbg(ab, ATH12K_DBG_BOOT, "invalid acpi handler\n");
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = acpi_evaluate_dsm(root_handle, ab->hw_params->acpi_guid, 0, func,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (!obj) {
|
|
|
|
ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_evaluate_dsm() failed\n");
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obj->type == ACPI_TYPE_INTEGER) {
|
2025-01-13 15:48:08 +08:00
|
|
|
switch (func) {
|
|
|
|
case ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS:
|
|
|
|
ab->acpi.func_bit = obj->integer.value;
|
|
|
|
break;
|
|
|
|
case ATH12K_ACPI_DSM_FUNC_DISABLE_FLAG:
|
|
|
|
ab->acpi.bit_flag = obj->integer.value;
|
|
|
|
break;
|
|
|
|
}
|
2025-01-13 15:48:10 +08:00
|
|
|
} else if (obj->type == ACPI_TYPE_STRING) {
|
|
|
|
switch (func) {
|
|
|
|
case ATH12K_ACPI_DSM_FUNC_BDF_EXT:
|
|
|
|
if (obj->string.length <= ATH12K_ACPI_BDF_ANCHOR_STRING_LEN ||
|
|
|
|
obj->string.length > ATH12K_ACPI_BDF_MAX_LEN ||
|
|
|
|
memcmp(obj->string.pointer, ATH12K_ACPI_BDF_ANCHOR_STRING,
|
|
|
|
ATH12K_ACPI_BDF_ANCHOR_STRING_LEN)) {
|
|
|
|
ath12k_warn(ab, "invalid ACPI DSM BDF size: %d\n",
|
|
|
|
obj->string.length);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(ab->acpi.bdf_string, obj->string.pointer,
|
|
|
|
obj->buffer.length);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2024-04-22 11:30:50 +08:00
|
|
|
} else if (obj->type == ACPI_TYPE_BUFFER) {
|
|
|
|
switch (func) {
|
2025-01-13 15:48:07 +08:00
|
|
|
case ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS:
|
|
|
|
if (obj->buffer.length < ATH12K_ACPI_DSM_FUNC_MIN_BITMAP_SIZE ||
|
|
|
|
obj->buffer.length > ATH12K_ACPI_DSM_FUNC_MAX_BITMAP_SIZE) {
|
|
|
|
ath12k_warn(ab, "invalid ACPI DSM func size: %d\n",
|
|
|
|
obj->buffer.length);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ab->acpi.func_bit = 0;
|
|
|
|
for (i = 0; i < obj->buffer.length; i++)
|
|
|
|
ab->acpi.func_bit += obj->buffer.pointer[i] << (i * 8);
|
|
|
|
|
|
|
|
break;
|
2024-04-22 11:30:50 +08:00
|
|
|
case ATH12K_ACPI_DSM_FUNC_TAS_CFG:
|
|
|
|
if (obj->buffer.length != ATH12K_ACPI_DSM_TAS_CFG_SIZE) {
|
|
|
|
ath12k_warn(ab, "invalid ACPI DSM TAS config size: %d\n",
|
|
|
|
obj->buffer.length);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&ab->acpi.tas_cfg, obj->buffer.pointer,
|
|
|
|
obj->buffer.length);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ATH12K_ACPI_DSM_FUNC_TAS_DATA:
|
|
|
|
if (obj->buffer.length != ATH12K_ACPI_DSM_TAS_DATA_SIZE) {
|
|
|
|
ath12k_warn(ab, "invalid ACPI DSM TAS data size: %d\n",
|
|
|
|
obj->buffer.length);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&ab->acpi.tas_sar_power_table, obj->buffer.pointer,
|
|
|
|
obj->buffer.length);
|
|
|
|
|
2024-04-22 16:18:44 +03:00
|
|
|
break;
|
|
|
|
case ATH12K_ACPI_DSM_FUNC_BIOS_SAR:
|
|
|
|
if (obj->buffer.length != ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE) {
|
|
|
|
ath12k_warn(ab, "invalid ACPI BIOS SAR data size: %d\n",
|
|
|
|
obj->buffer.length);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&ab->acpi.bios_sar_data, obj->buffer.pointer,
|
|
|
|
obj->buffer.length);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ATH12K_ACPI_DSM_FUNC_GEO_OFFSET:
|
|
|
|
if (obj->buffer.length != ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE) {
|
|
|
|
ath12k_warn(ab, "invalid ACPI GEO OFFSET data size: %d\n",
|
|
|
|
obj->buffer.length);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&ab->acpi.geo_offset_data, obj->buffer.pointer,
|
|
|
|
obj->buffer.length);
|
|
|
|
|
2024-04-22 16:18:45 +03:00
|
|
|
break;
|
|
|
|
case ATH12K_ACPI_DSM_FUNC_INDEX_CCA:
|
|
|
|
if (obj->buffer.length != ATH12K_ACPI_DSM_CCA_DATA_SIZE) {
|
|
|
|
ath12k_warn(ab, "invalid ACPI DSM CCA data size: %d\n",
|
|
|
|
obj->buffer.length);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&ab->acpi.cca_data, obj->buffer.pointer,
|
|
|
|
obj->buffer.length);
|
|
|
|
|
2024-04-22 16:18:45 +03:00
|
|
|
break;
|
|
|
|
case ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE:
|
|
|
|
if (obj->buffer.length != ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE) {
|
|
|
|
ath12k_warn(ab, "invalid ACPI DSM band edge data size: %d\n",
|
|
|
|
obj->buffer.length);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&ab->acpi.band_edge_power, obj->buffer.pointer,
|
|
|
|
obj->buffer.length);
|
|
|
|
|
2024-04-22 11:30:50 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ath12k_warn(ab, "ACPI DSM method returned an unsupported object type: %d\n",
|
|
|
|
obj->type);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
out:
|
|
|
|
ACPI_FREE(obj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ath12k_acpi_set_power_limit(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
const u8 *tas_sar_power_table = ab->acpi.tas_sar_power_table;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (tas_sar_power_table[0] != ATH12K_ACPI_TAS_DATA_VERSION ||
|
|
|
|
tas_sar_power_table[1] != ATH12K_ACPI_TAS_DATA_ENABLE) {
|
|
|
|
ath12k_warn(ab, "latest ACPI TAS data is invalid\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,
|
|
|
|
tas_sar_power_table,
|
|
|
|
ATH12K_ACPI_DSM_TAS_DATA_SIZE);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to send ACPI TAS data table: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-04-22 16:18:44 +03:00
|
|
|
static int ath12k_acpi_set_bios_sar_power(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (ab->acpi.bios_sar_data[0] != ATH12K_ACPI_POWER_LIMIT_VERSION ||
|
|
|
|
ab->acpi.bios_sar_data[1] != ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG) {
|
|
|
|
ath12k_warn(ab, "invalid latest ACPI BIOS SAR data\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-04-22 11:30:50 +08:00
|
|
|
static void ath12k_acpi_dsm_notify(acpi_handle handle, u32 event, void *data)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct ath12k_base *ab = data;
|
|
|
|
|
|
|
|
if (event == ATH12K_ACPI_NOTIFY_EVENT) {
|
|
|
|
ath12k_warn(ab, "unknown acpi notify %u\n", event);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ab->acpi.acpi_tas_enable) {
|
|
|
|
ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_tas_enable is false\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to update ACPI TAS data table: %d\n", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath12k_acpi_set_power_limit(ab);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to set ACPI TAS power limit data: %d", ret);
|
|
|
|
return;
|
|
|
|
}
|
2024-04-22 16:18:44 +03:00
|
|
|
|
|
|
|
if (!ab->acpi.acpi_bios_sar_enable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to update BIOS SAR: %d\n", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath12k_acpi_set_bios_sar_power(ab);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to set BIOS SAR power limit: %d\n", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ath12k_acpi_set_bios_sar_params(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath12k_wmi_set_bios_geo_cmd(ab, ab->acpi.geo_offset_data);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to set ACPI BIOS GEO table: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2024-04-22 11:30:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int ath12k_acpi_set_tas_params(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_CONFIG_TYPE,
|
|
|
|
ab->acpi.tas_cfg,
|
|
|
|
ATH12K_ACPI_DSM_TAS_CFG_SIZE);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to send ACPI TAS config table parameter: %d\n",
|
|
|
|
ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,
|
|
|
|
ab->acpi.tas_sar_power_table,
|
|
|
|
ATH12K_ACPI_DSM_TAS_DATA_SIZE);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to send ACPI TAS data table parameter: %d\n",
|
|
|
|
ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2025-01-13 15:48:08 +08:00
|
|
|
bool ath12k_acpi_get_disable_rfkill(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
return ab->acpi.acpi_disable_rfkill;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ath12k_acpi_get_disable_11be(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
return ab->acpi.acpi_disable_11be;
|
|
|
|
}
|
|
|
|
|
2025-01-13 15:48:09 +08:00
|
|
|
void ath12k_acpi_set_dsm_func(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
u8 *buf;
|
|
|
|
|
|
|
|
if (!ab->hw_params->acpi_guid)
|
|
|
|
/* not supported with this hardware */
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ab->acpi.acpi_tas_enable) {
|
|
|
|
ret = ath12k_acpi_set_tas_params(ab);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to send ACPI TAS parameters: %d\n", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ab->acpi.acpi_bios_sar_enable) {
|
|
|
|
ret = ath12k_acpi_set_bios_sar_params(ab);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to send ACPI BIOS SAR: %d\n", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ab->acpi.acpi_cca_enable) {
|
|
|
|
buf = ab->acpi.cca_data + ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET;
|
|
|
|
ret = ath12k_wmi_set_bios_cmd(ab,
|
|
|
|
WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE,
|
|
|
|
buf,
|
|
|
|
ATH12K_ACPI_CCA_THR_OFFSET_LEN);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to set ACPI DSM CCA threshold: %d\n",
|
|
|
|
ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ab->acpi.acpi_band_edge_enable) {
|
|
|
|
ret = ath12k_wmi_set_bios_cmd(ab,
|
|
|
|
WMI_BIOS_PARAM_TYPE_BANDEDGE,
|
|
|
|
ab->acpi.band_edge_power,
|
|
|
|
sizeof(ab->acpi.band_edge_power));
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab,
|
|
|
|
"failed to set ACPI DSM band edge channel power: %d\n",
|
|
|
|
ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-22 11:30:50 +08:00
|
|
|
int ath12k_acpi_start(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
acpi_status status;
|
|
|
|
int ret;
|
|
|
|
|
2025-01-13 15:48:08 +08:00
|
|
|
ab->acpi.acpi_tas_enable = false;
|
|
|
|
ab->acpi.acpi_disable_11be = false;
|
|
|
|
ab->acpi.acpi_disable_rfkill = false;
|
2025-01-13 15:48:09 +08:00
|
|
|
ab->acpi.acpi_bios_sar_enable = false;
|
|
|
|
ab->acpi.acpi_cca_enable = false;
|
|
|
|
ab->acpi.acpi_band_edge_enable = false;
|
2025-01-13 15:48:10 +08:00
|
|
|
ab->acpi.acpi_enable_bdf = false;
|
|
|
|
ab->acpi.bdf_string[0] = '\0';
|
2025-01-13 15:48:08 +08:00
|
|
|
|
2024-04-22 11:30:50 +08:00
|
|
|
if (!ab->hw_params->acpi_guid)
|
|
|
|
/* not supported with this hardware */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_dbg(ab, ATH12K_DBG_BOOT, "failed to get ACPI DSM data: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2025-01-13 15:48:08 +08:00
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_DISABLE_FLAG)) {
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_DISABLE_FLAG);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to get ACPI DISABLE FLAG: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATH12K_ACPI_CHEK_BIT_VALID(ab->acpi,
|
|
|
|
ATH12K_ACPI_DSM_DISABLE_11BE_BIT))
|
|
|
|
ab->acpi.acpi_disable_11be = true;
|
|
|
|
|
|
|
|
if (!ATH12K_ACPI_CHEK_BIT_VALID(ab->acpi,
|
|
|
|
ATH12K_ACPI_DSM_DISABLE_RFKILL_BIT))
|
|
|
|
ab->acpi.acpi_disable_rfkill = true;
|
|
|
|
}
|
|
|
|
|
2025-01-13 15:48:10 +08:00
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BDF_EXT)) {
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BDF_EXT);
|
|
|
|
if (ret || ab->acpi.bdf_string[0] == '\0') {
|
|
|
|
ath12k_warn(ab, "failed to get ACPI BDF EXT: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ab->acpi.acpi_enable_bdf = true;
|
|
|
|
}
|
|
|
|
|
2024-04-22 11:30:50 +08:00
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG)) {
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_CFG);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to get ACPI TAS config table: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_DATA)) {
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to get ACPI TAS data table: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG) &&
|
|
|
|
ab->acpi.tas_sar_power_table[0] == ATH12K_ACPI_TAS_DATA_VERSION &&
|
|
|
|
ab->acpi.tas_sar_power_table[1] == ATH12K_ACPI_TAS_DATA_ENABLE)
|
|
|
|
ab->acpi.acpi_tas_enable = true;
|
|
|
|
}
|
|
|
|
|
2024-04-22 16:18:44 +03:00
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BIOS_SAR)) {
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to get ACPI bios sar data: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_GEO_OFFSET)) {
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_GEO_OFFSET);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to get ACPI geo offset data: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BIOS_SAR) &&
|
|
|
|
ab->acpi.bios_sar_data[0] == ATH12K_ACPI_POWER_LIMIT_VERSION &&
|
|
|
|
ab->acpi.bios_sar_data[1] == ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG &&
|
|
|
|
!ab->acpi.acpi_tas_enable)
|
|
|
|
ab->acpi.acpi_bios_sar_enable = true;
|
|
|
|
}
|
|
|
|
|
2024-04-22 16:18:45 +03:00
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_CCA)) {
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_CCA);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to get ACPI DSM CCA threshold configuration: %d\n",
|
|
|
|
ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ab->acpi.cca_data[0] == ATH12K_ACPI_CCA_THR_VERSION &&
|
|
|
|
ab->acpi.cca_data[ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET] ==
|
2025-01-13 15:48:09 +08:00
|
|
|
ATH12K_ACPI_CCA_THR_ENABLE_FLAG)
|
|
|
|
ab->acpi.acpi_cca_enable = true;
|
2024-04-22 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
2024-04-22 16:18:45 +03:00
|
|
|
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi,
|
|
|
|
ATH12K_ACPI_FUNC_BIT_BAND_EDGE_CHAN_POWER)) {
|
|
|
|
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE);
|
|
|
|
if (ret) {
|
|
|
|
ath12k_warn(ab, "failed to get ACPI DSM band edge channel power: %d\n",
|
|
|
|
ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ab->acpi.band_edge_power[0] == ATH12K_ACPI_BAND_EDGE_VERSION &&
|
2025-01-13 15:48:09 +08:00
|
|
|
ab->acpi.band_edge_power[1] == ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG)
|
|
|
|
ab->acpi.acpi_band_edge_enable = true;
|
2024-04-22 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
2024-04-22 11:30:50 +08:00
|
|
|
status = acpi_install_notify_handler(ACPI_HANDLE(ab->dev),
|
|
|
|
ACPI_DEVICE_NOTIFY,
|
|
|
|
ath12k_acpi_dsm_notify, ab);
|
|
|
|
if (ACPI_FAILURE(status)) {
|
|
|
|
ath12k_warn(ab, "failed to install DSM notify callback: %d\n", status);
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
ab->acpi.started = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2025-01-13 15:48:10 +08:00
|
|
|
int ath12k_acpi_check_bdf_variant_name(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
size_t max_len = sizeof(ab->qmi.target.bdf_ext);
|
|
|
|
|
|
|
|
if (!ab->acpi.acpi_enable_bdf)
|
|
|
|
return -ENODATA;
|
|
|
|
|
|
|
|
if (strscpy(ab->qmi.target.bdf_ext, ab->acpi.bdf_string + 4, max_len) < 0)
|
|
|
|
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
|
|
|
"acpi bdf variant longer than the buffer (variant: %s)\n",
|
|
|
|
ab->acpi.bdf_string);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-04-22 11:30:50 +08:00
|
|
|
void ath12k_acpi_stop(struct ath12k_base *ab)
|
|
|
|
{
|
|
|
|
if (!ab->acpi.started)
|
|
|
|
return;
|
|
|
|
|
|
|
|
acpi_remove_notify_handler(ACPI_HANDLE(ab->dev),
|
|
|
|
ACPI_DEVICE_NOTIFY,
|
|
|
|
ath12k_acpi_dsm_notify);
|
2024-06-11 09:42:33 +03:00
|
|
|
|
|
|
|
memset(&ab->acpi, 0, sizeof(ab->acpi));
|
2024-04-22 11:30:50 +08:00
|
|
|
}
|