1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
11 static int ath12k_acpi_dsm_get_data(struct ath12k_base
*ab
, int func
)
13 union acpi_object
*obj
;
14 acpi_handle root_handle
;
17 root_handle
= ACPI_HANDLE(ab
->dev
);
19 ath12k_dbg(ab
, ATH12K_DBG_BOOT
, "invalid acpi handler\n");
23 obj
= acpi_evaluate_dsm(root_handle
, ab
->hw_params
->acpi_guid
, 0, func
,
27 ath12k_dbg(ab
, ATH12K_DBG_BOOT
, "acpi_evaluate_dsm() failed\n");
31 if (obj
->type
== ACPI_TYPE_INTEGER
) {
32 ab
->acpi
.func_bit
= obj
->integer
.value
;
33 } else if (obj
->type
== ACPI_TYPE_BUFFER
) {
35 case ATH12K_ACPI_DSM_FUNC_TAS_CFG
:
36 if (obj
->buffer
.length
!= ATH12K_ACPI_DSM_TAS_CFG_SIZE
) {
37 ath12k_warn(ab
, "invalid ACPI DSM TAS config size: %d\n",
43 memcpy(&ab
->acpi
.tas_cfg
, obj
->buffer
.pointer
,
47 case ATH12K_ACPI_DSM_FUNC_TAS_DATA
:
48 if (obj
->buffer
.length
!= ATH12K_ACPI_DSM_TAS_DATA_SIZE
) {
49 ath12k_warn(ab
, "invalid ACPI DSM TAS data size: %d\n",
55 memcpy(&ab
->acpi
.tas_sar_power_table
, obj
->buffer
.pointer
,
59 case ATH12K_ACPI_DSM_FUNC_BIOS_SAR
:
60 if (obj
->buffer
.length
!= ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE
) {
61 ath12k_warn(ab
, "invalid ACPI BIOS SAR data size: %d\n",
67 memcpy(&ab
->acpi
.bios_sar_data
, obj
->buffer
.pointer
,
71 case ATH12K_ACPI_DSM_FUNC_GEO_OFFSET
:
72 if (obj
->buffer
.length
!= ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE
) {
73 ath12k_warn(ab
, "invalid ACPI GEO OFFSET data size: %d\n",
79 memcpy(&ab
->acpi
.geo_offset_data
, obj
->buffer
.pointer
,
83 case ATH12K_ACPI_DSM_FUNC_INDEX_CCA
:
84 if (obj
->buffer
.length
!= ATH12K_ACPI_DSM_CCA_DATA_SIZE
) {
85 ath12k_warn(ab
, "invalid ACPI DSM CCA data size: %d\n",
91 memcpy(&ab
->acpi
.cca_data
, obj
->buffer
.pointer
,
95 case ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE
:
96 if (obj
->buffer
.length
!= ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE
) {
97 ath12k_warn(ab
, "invalid ACPI DSM band edge data size: %d\n",
103 memcpy(&ab
->acpi
.band_edge_power
, obj
->buffer
.pointer
,
109 ath12k_warn(ab
, "ACPI DSM method returned an unsupported object type: %d\n",
122 static int ath12k_acpi_set_power_limit(struct ath12k_base
*ab
)
124 const u8
*tas_sar_power_table
= ab
->acpi
.tas_sar_power_table
;
127 if (tas_sar_power_table
[0] != ATH12K_ACPI_TAS_DATA_VERSION
||
128 tas_sar_power_table
[1] != ATH12K_ACPI_TAS_DATA_ENABLE
) {
129 ath12k_warn(ab
, "latest ACPI TAS data is invalid\n");
133 ret
= ath12k_wmi_set_bios_cmd(ab
, WMI_BIOS_PARAM_TAS_DATA_TYPE
,
135 ATH12K_ACPI_DSM_TAS_DATA_SIZE
);
137 ath12k_warn(ab
, "failed to send ACPI TAS data table: %d\n", ret
);
144 static int ath12k_acpi_set_bios_sar_power(struct ath12k_base
*ab
)
148 if (ab
->acpi
.bios_sar_data
[0] != ATH12K_ACPI_POWER_LIMIT_VERSION
||
149 ab
->acpi
.bios_sar_data
[1] != ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG
) {
150 ath12k_warn(ab
, "invalid latest ACPI BIOS SAR data\n");
154 ret
= ath12k_wmi_set_bios_sar_cmd(ab
, ab
->acpi
.bios_sar_data
);
156 ath12k_warn(ab
, "failed to set ACPI BIOS SAR table: %d\n", ret
);
163 static void ath12k_acpi_dsm_notify(acpi_handle handle
, u32 event
, void *data
)
166 struct ath12k_base
*ab
= data
;
168 if (event
== ATH12K_ACPI_NOTIFY_EVENT
) {
169 ath12k_warn(ab
, "unknown acpi notify %u\n", event
);
173 if (!ab
->acpi
.acpi_tas_enable
) {
174 ath12k_dbg(ab
, ATH12K_DBG_BOOT
, "acpi_tas_enable is false\n");
178 ret
= ath12k_acpi_dsm_get_data(ab
, ATH12K_ACPI_DSM_FUNC_TAS_DATA
);
180 ath12k_warn(ab
, "failed to update ACPI TAS data table: %d\n", ret
);
184 ret
= ath12k_acpi_set_power_limit(ab
);
186 ath12k_warn(ab
, "failed to set ACPI TAS power limit data: %d", ret
);
190 if (!ab
->acpi
.acpi_bios_sar_enable
)
193 ret
= ath12k_acpi_dsm_get_data(ab
, ATH12K_ACPI_DSM_FUNC_BIOS_SAR
);
195 ath12k_warn(ab
, "failed to update BIOS SAR: %d\n", ret
);
199 ret
= ath12k_acpi_set_bios_sar_power(ab
);
201 ath12k_warn(ab
, "failed to set BIOS SAR power limit: %d\n", ret
);
206 static int ath12k_acpi_set_bios_sar_params(struct ath12k_base
*ab
)
210 ret
= ath12k_wmi_set_bios_sar_cmd(ab
, ab
->acpi
.bios_sar_data
);
212 ath12k_warn(ab
, "failed to set ACPI BIOS SAR table: %d\n", ret
);
216 ret
= ath12k_wmi_set_bios_geo_cmd(ab
, ab
->acpi
.geo_offset_data
);
218 ath12k_warn(ab
, "failed to set ACPI BIOS GEO table: %d\n", ret
);
225 static int ath12k_acpi_set_tas_params(struct ath12k_base
*ab
)
229 ret
= ath12k_wmi_set_bios_cmd(ab
, WMI_BIOS_PARAM_TAS_CONFIG_TYPE
,
231 ATH12K_ACPI_DSM_TAS_CFG_SIZE
);
233 ath12k_warn(ab
, "failed to send ACPI TAS config table parameter: %d\n",
238 ret
= ath12k_wmi_set_bios_cmd(ab
, WMI_BIOS_PARAM_TAS_DATA_TYPE
,
239 ab
->acpi
.tas_sar_power_table
,
240 ATH12K_ACPI_DSM_TAS_DATA_SIZE
);
242 ath12k_warn(ab
, "failed to send ACPI TAS data table parameter: %d\n",
250 int ath12k_acpi_start(struct ath12k_base
*ab
)
256 if (!ab
->hw_params
->acpi_guid
)
257 /* not supported with this hardware */
260 ab
->acpi
.acpi_tas_enable
= false;
262 ret
= ath12k_acpi_dsm_get_data(ab
, ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS
);
264 ath12k_dbg(ab
, ATH12K_DBG_BOOT
, "failed to get ACPI DSM data: %d\n", ret
);
268 if (ATH12K_ACPI_FUNC_BIT_VALID(ab
->acpi
, ATH12K_ACPI_FUNC_BIT_TAS_CFG
)) {
269 ret
= ath12k_acpi_dsm_get_data(ab
, ATH12K_ACPI_DSM_FUNC_TAS_CFG
);
271 ath12k_warn(ab
, "failed to get ACPI TAS config table: %d\n", ret
);
276 if (ATH12K_ACPI_FUNC_BIT_VALID(ab
->acpi
, ATH12K_ACPI_FUNC_BIT_TAS_DATA
)) {
277 ret
= ath12k_acpi_dsm_get_data(ab
, ATH12K_ACPI_DSM_FUNC_TAS_DATA
);
279 ath12k_warn(ab
, "failed to get ACPI TAS data table: %d\n", ret
);
283 if (ATH12K_ACPI_FUNC_BIT_VALID(ab
->acpi
, ATH12K_ACPI_FUNC_BIT_TAS_CFG
) &&
284 ab
->acpi
.tas_sar_power_table
[0] == ATH12K_ACPI_TAS_DATA_VERSION
&&
285 ab
->acpi
.tas_sar_power_table
[1] == ATH12K_ACPI_TAS_DATA_ENABLE
)
286 ab
->acpi
.acpi_tas_enable
= true;
289 if (ATH12K_ACPI_FUNC_BIT_VALID(ab
->acpi
, ATH12K_ACPI_FUNC_BIT_BIOS_SAR
)) {
290 ret
= ath12k_acpi_dsm_get_data(ab
, ATH12K_ACPI_DSM_FUNC_BIOS_SAR
);
292 ath12k_warn(ab
, "failed to get ACPI bios sar data: %d\n", ret
);
297 if (ATH12K_ACPI_FUNC_BIT_VALID(ab
->acpi
, ATH12K_ACPI_FUNC_BIT_GEO_OFFSET
)) {
298 ret
= ath12k_acpi_dsm_get_data(ab
, ATH12K_ACPI_DSM_FUNC_GEO_OFFSET
);
300 ath12k_warn(ab
, "failed to get ACPI geo offset data: %d\n", ret
);
304 if (ATH12K_ACPI_FUNC_BIT_VALID(ab
->acpi
, ATH12K_ACPI_FUNC_BIT_BIOS_SAR
) &&
305 ab
->acpi
.bios_sar_data
[0] == ATH12K_ACPI_POWER_LIMIT_VERSION
&&
306 ab
->acpi
.bios_sar_data
[1] == ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG
&&
307 !ab
->acpi
.acpi_tas_enable
)
308 ab
->acpi
.acpi_bios_sar_enable
= true;
311 if (ab
->acpi
.acpi_tas_enable
) {
312 ret
= ath12k_acpi_set_tas_params(ab
);
314 ath12k_warn(ab
, "failed to send ACPI parameters: %d\n", ret
);
319 if (ab
->acpi
.acpi_bios_sar_enable
) {
320 ret
= ath12k_acpi_set_bios_sar_params(ab
);
325 if (ATH12K_ACPI_FUNC_BIT_VALID(ab
->acpi
, ATH12K_ACPI_FUNC_BIT_CCA
)) {
326 ret
= ath12k_acpi_dsm_get_data(ab
, ATH12K_ACPI_DSM_FUNC_INDEX_CCA
);
328 ath12k_warn(ab
, "failed to get ACPI DSM CCA threshold configuration: %d\n",
333 if (ab
->acpi
.cca_data
[0] == ATH12K_ACPI_CCA_THR_VERSION
&&
334 ab
->acpi
.cca_data
[ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET
] ==
335 ATH12K_ACPI_CCA_THR_ENABLE_FLAG
) {
336 buf
= ab
->acpi
.cca_data
+ ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET
;
337 ret
= ath12k_wmi_set_bios_cmd(ab
,
338 WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE
,
340 ATH12K_ACPI_CCA_THR_OFFSET_LEN
);
342 ath12k_warn(ab
, "failed to set ACPI DSM CCA threshold: %d\n",
349 if (ATH12K_ACPI_FUNC_BIT_VALID(ab
->acpi
,
350 ATH12K_ACPI_FUNC_BIT_BAND_EDGE_CHAN_POWER
)) {
351 ret
= ath12k_acpi_dsm_get_data(ab
, ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE
);
353 ath12k_warn(ab
, "failed to get ACPI DSM band edge channel power: %d\n",
358 if (ab
->acpi
.band_edge_power
[0] == ATH12K_ACPI_BAND_EDGE_VERSION
&&
359 ab
->acpi
.band_edge_power
[1] == ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG
) {
360 ret
= ath12k_wmi_set_bios_cmd(ab
,
361 WMI_BIOS_PARAM_TYPE_BANDEDGE
,
362 ab
->acpi
.band_edge_power
,
363 sizeof(ab
->acpi
.band_edge_power
));
366 "failed to set ACPI DSM band edge channel power: %d\n",
373 status
= acpi_install_notify_handler(ACPI_HANDLE(ab
->dev
),
375 ath12k_acpi_dsm_notify
, ab
);
376 if (ACPI_FAILURE(status
)) {
377 ath12k_warn(ab
, "failed to install DSM notify callback: %d\n", status
);
381 ab
->acpi
.started
= true;
386 void ath12k_acpi_stop(struct ath12k_base
*ab
)
388 if (!ab
->acpi
.started
)
391 acpi_remove_notify_handler(ACPI_HANDLE(ab
->dev
),
393 ath12k_acpi_dsm_notify
);
395 memset(&ab
->acpi
, 0, sizeof(ab
->acpi
));