drm: bridge: adv7511: remove s32 format from i2s capabilities
[drm/drm-misc.git] / drivers / net / wireless / ath / ath12k / acpi.c
blob0555d35aab477a5f42906b4bf367f1db3dd5ee94
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
5 */
7 #include "core.h"
8 #include "acpi.h"
9 #include "debug.h"
11 static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func)
13 union acpi_object *obj;
14 acpi_handle root_handle;
15 int ret;
17 root_handle = ACPI_HANDLE(ab->dev);
18 if (!root_handle) {
19 ath12k_dbg(ab, ATH12K_DBG_BOOT, "invalid acpi handler\n");
20 return -EOPNOTSUPP;
23 obj = acpi_evaluate_dsm(root_handle, ab->hw_params->acpi_guid, 0, func,
24 NULL);
26 if (!obj) {
27 ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_evaluate_dsm() failed\n");
28 return -ENOENT;
31 if (obj->type == ACPI_TYPE_INTEGER) {
32 ab->acpi.func_bit = obj->integer.value;
33 } else if (obj->type == ACPI_TYPE_BUFFER) {
34 switch (func) {
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",
38 obj->buffer.length);
39 ret = -EINVAL;
40 goto out;
43 memcpy(&ab->acpi.tas_cfg, obj->buffer.pointer,
44 obj->buffer.length);
46 break;
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",
50 obj->buffer.length);
51 ret = -EINVAL;
52 goto out;
55 memcpy(&ab->acpi.tas_sar_power_table, obj->buffer.pointer,
56 obj->buffer.length);
58 break;
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",
62 obj->buffer.length);
63 ret = -EINVAL;
64 goto out;
67 memcpy(&ab->acpi.bios_sar_data, obj->buffer.pointer,
68 obj->buffer.length);
70 break;
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",
74 obj->buffer.length);
75 ret = -EINVAL;
76 goto out;
79 memcpy(&ab->acpi.geo_offset_data, obj->buffer.pointer,
80 obj->buffer.length);
82 break;
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",
86 obj->buffer.length);
87 ret = -EINVAL;
88 goto out;
91 memcpy(&ab->acpi.cca_data, obj->buffer.pointer,
92 obj->buffer.length);
94 break;
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",
98 obj->buffer.length);
99 ret = -EINVAL;
100 goto out;
103 memcpy(&ab->acpi.band_edge_power, obj->buffer.pointer,
104 obj->buffer.length);
106 break;
108 } else {
109 ath12k_warn(ab, "ACPI DSM method returned an unsupported object type: %d\n",
110 obj->type);
111 ret = -EINVAL;
112 goto out;
115 ret = 0;
117 out:
118 ACPI_FREE(obj);
119 return ret;
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;
125 int ret;
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");
130 return -EINVAL;
133 ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,
134 tas_sar_power_table,
135 ATH12K_ACPI_DSM_TAS_DATA_SIZE);
136 if (ret) {
137 ath12k_warn(ab, "failed to send ACPI TAS data table: %d\n", ret);
138 return ret;
141 return ret;
144 static int ath12k_acpi_set_bios_sar_power(struct ath12k_base *ab)
146 int ret;
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");
151 return -EINVAL;
154 ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
155 if (ret) {
156 ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
157 return ret;
160 return 0;
163 static void ath12k_acpi_dsm_notify(acpi_handle handle, u32 event, void *data)
165 int ret;
166 struct ath12k_base *ab = data;
168 if (event == ATH12K_ACPI_NOTIFY_EVENT) {
169 ath12k_warn(ab, "unknown acpi notify %u\n", event);
170 return;
173 if (!ab->acpi.acpi_tas_enable) {
174 ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_tas_enable is false\n");
175 return;
178 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);
179 if (ret) {
180 ath12k_warn(ab, "failed to update ACPI TAS data table: %d\n", ret);
181 return;
184 ret = ath12k_acpi_set_power_limit(ab);
185 if (ret) {
186 ath12k_warn(ab, "failed to set ACPI TAS power limit data: %d", ret);
187 return;
190 if (!ab->acpi.acpi_bios_sar_enable)
191 return;
193 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);
194 if (ret) {
195 ath12k_warn(ab, "failed to update BIOS SAR: %d\n", ret);
196 return;
199 ret = ath12k_acpi_set_bios_sar_power(ab);
200 if (ret) {
201 ath12k_warn(ab, "failed to set BIOS SAR power limit: %d\n", ret);
202 return;
206 static int ath12k_acpi_set_bios_sar_params(struct ath12k_base *ab)
208 int ret;
210 ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
211 if (ret) {
212 ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
213 return ret;
216 ret = ath12k_wmi_set_bios_geo_cmd(ab, ab->acpi.geo_offset_data);
217 if (ret) {
218 ath12k_warn(ab, "failed to set ACPI BIOS GEO table: %d\n", ret);
219 return ret;
222 return 0;
225 static int ath12k_acpi_set_tas_params(struct ath12k_base *ab)
227 int ret;
229 ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_CONFIG_TYPE,
230 ab->acpi.tas_cfg,
231 ATH12K_ACPI_DSM_TAS_CFG_SIZE);
232 if (ret) {
233 ath12k_warn(ab, "failed to send ACPI TAS config table parameter: %d\n",
234 ret);
235 return ret;
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);
241 if (ret) {
242 ath12k_warn(ab, "failed to send ACPI TAS data table parameter: %d\n",
243 ret);
244 return ret;
247 return 0;
250 int ath12k_acpi_start(struct ath12k_base *ab)
252 acpi_status status;
253 u8 *buf;
254 int ret;
256 if (!ab->hw_params->acpi_guid)
257 /* not supported with this hardware */
258 return 0;
260 ab->acpi.acpi_tas_enable = false;
262 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS);
263 if (ret) {
264 ath12k_dbg(ab, ATH12K_DBG_BOOT, "failed to get ACPI DSM data: %d\n", ret);
265 return 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);
270 if (ret) {
271 ath12k_warn(ab, "failed to get ACPI TAS config table: %d\n", ret);
272 return 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);
278 if (ret) {
279 ath12k_warn(ab, "failed to get ACPI TAS data table: %d\n", ret);
280 return 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);
291 if (ret) {
292 ath12k_warn(ab, "failed to get ACPI bios sar data: %d\n", ret);
293 return 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);
299 if (ret) {
300 ath12k_warn(ab, "failed to get ACPI geo offset data: %d\n", ret);
301 return 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);
313 if (ret) {
314 ath12k_warn(ab, "failed to send ACPI parameters: %d\n", ret);
315 return ret;
319 if (ab->acpi.acpi_bios_sar_enable) {
320 ret = ath12k_acpi_set_bios_sar_params(ab);
321 if (ret)
322 return ret;
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);
327 if (ret) {
328 ath12k_warn(ab, "failed to get ACPI DSM CCA threshold configuration: %d\n",
329 ret);
330 return ret;
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,
339 buf,
340 ATH12K_ACPI_CCA_THR_OFFSET_LEN);
341 if (ret) {
342 ath12k_warn(ab, "failed to set ACPI DSM CCA threshold: %d\n",
343 ret);
344 return ret;
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);
352 if (ret) {
353 ath12k_warn(ab, "failed to get ACPI DSM band edge channel power: %d\n",
354 ret);
355 return ret;
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));
364 if (ret) {
365 ath12k_warn(ab,
366 "failed to set ACPI DSM band edge channel power: %d\n",
367 ret);
368 return ret;
373 status = acpi_install_notify_handler(ACPI_HANDLE(ab->dev),
374 ACPI_DEVICE_NOTIFY,
375 ath12k_acpi_dsm_notify, ab);
376 if (ACPI_FAILURE(status)) {
377 ath12k_warn(ab, "failed to install DSM notify callback: %d\n", status);
378 return -EIO;
381 ab->acpi.started = true;
383 return 0;
386 void ath12k_acpi_stop(struct ath12k_base *ab)
388 if (!ab->acpi.started)
389 return;
391 acpi_remove_notify_handler(ACPI_HANDLE(ab->dev),
392 ACPI_DEVICE_NOTIFY,
393 ath12k_acpi_dsm_notify);
395 memset(&ab->acpi, 0, sizeof(ab->acpi));