xref: /openbsd-src/sys/dev/pci/drm/amd/amdgpu/amdgpu_acpi.c (revision 8ac6d3a757067b779a093bb8b9a8e87ffa66fe7e)
11bb76ff1Sjsg // SPDX-License-Identifier: MIT
2fb4d8502Sjsg /*
3fb4d8502Sjsg  * Copyright 2012 Advanced Micro Devices, Inc.
4fb4d8502Sjsg  *
5fb4d8502Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
6fb4d8502Sjsg  * copy of this software and associated documentation files (the "Software"),
7fb4d8502Sjsg  * to deal in the Software without restriction, including without limitation
8fb4d8502Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9fb4d8502Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
10fb4d8502Sjsg  * Software is furnished to do so, subject to the following conditions:
11fb4d8502Sjsg  *
12fb4d8502Sjsg  * The above copyright notice and this permission notice shall be included in
13fb4d8502Sjsg  * all copies or substantial portions of the Software.
14fb4d8502Sjsg  *
15fb4d8502Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16fb4d8502Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17fb4d8502Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18fb4d8502Sjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19fb4d8502Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20fb4d8502Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21fb4d8502Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
22fb4d8502Sjsg  *
23fb4d8502Sjsg  */
24fb4d8502Sjsg 
25fb4d8502Sjsg #include <linux/pci.h>
26fb4d8502Sjsg #include <linux/acpi.h>
27f005ef32Sjsg #include <linux/backlight.h>
28fb4d8502Sjsg #include <linux/slab.h>
29f005ef32Sjsg #include <linux/xarray.h>
30fb4d8502Sjsg #include <linux/power_supply.h>
31fb4d8502Sjsg #include <linux/pm_runtime.h>
325ca02815Sjsg #include <linux/suspend.h>
33fb4d8502Sjsg #include <acpi/video.h>
345ca02815Sjsg #include <acpi/actbl.h>
35c349dbc7Sjsg 
36fb4d8502Sjsg #include "amdgpu.h"
37fb4d8502Sjsg #include "amdgpu_pm.h"
38c349dbc7Sjsg #include "amdgpu_display.h"
39fb4d8502Sjsg #include "amd_acpi.h"
40fb4d8502Sjsg #include "atom.h"
41fb4d8502Sjsg 
42f005ef32Sjsg /* Declare GUID for AMD _DSM method for XCCs */
43f005ef32Sjsg #ifdef notyet
44f005ef32Sjsg static const guid_t amd_xcc_dsm_guid = GUID_INIT(0x8267f5d5, 0xa556, 0x44f2,
45f005ef32Sjsg 						 0xb8, 0xb4, 0x45, 0x56, 0x2e,
46f005ef32Sjsg 						 0x8c, 0x5b, 0xec);
47f005ef32Sjsg #endif
48f005ef32Sjsg 
49f005ef32Sjsg #define AMD_XCC_HID_START 3000
50f005ef32Sjsg #define AMD_XCC_DSM_GET_NUM_FUNCS 0
51f005ef32Sjsg #define AMD_XCC_DSM_GET_SUPP_MODE 1
52f005ef32Sjsg #define AMD_XCC_DSM_GET_XCP_MODE 2
53f005ef32Sjsg #define AMD_XCC_DSM_GET_VF_XCC_MAPPING 4
54f005ef32Sjsg #define AMD_XCC_DSM_GET_TMR_INFO 5
55f005ef32Sjsg #define AMD_XCC_DSM_NUM_FUNCS 5
56f005ef32Sjsg 
57f005ef32Sjsg #define AMD_XCC_MAX_HID 24
58f005ef32Sjsg 
59f005ef32Sjsg struct xarray numa_info_xa;
60f005ef32Sjsg 
61f005ef32Sjsg /* Encapsulates the XCD acpi object information */
62f005ef32Sjsg struct amdgpu_acpi_xcc_info {
63f005ef32Sjsg 	struct list_head list;
64f005ef32Sjsg 	struct amdgpu_numa_info *numa_info;
65f005ef32Sjsg 	uint8_t xcp_node;
66f005ef32Sjsg 	uint8_t phy_id;
67f005ef32Sjsg 	acpi_handle handle;
68f005ef32Sjsg };
69f005ef32Sjsg 
70f005ef32Sjsg struct amdgpu_acpi_dev_info {
71f005ef32Sjsg 	struct list_head list;
72f005ef32Sjsg 	struct list_head xcc_list;
73f005ef32Sjsg 	uint16_t bdf;
74f005ef32Sjsg 	uint16_t supp_xcp_mode;
75f005ef32Sjsg 	uint16_t xcp_mode;
76f005ef32Sjsg 	uint16_t mem_mode;
77f005ef32Sjsg 	uint64_t tmr_base;
78f005ef32Sjsg 	uint64_t tmr_size;
79f005ef32Sjsg };
80f005ef32Sjsg 
81f005ef32Sjsg struct list_head amdgpu_acpi_dev_list;
82f005ef32Sjsg 
83fb4d8502Sjsg struct amdgpu_atif_notification_cfg {
84fb4d8502Sjsg 	bool enabled;
85fb4d8502Sjsg 	int command_code;
86fb4d8502Sjsg };
87fb4d8502Sjsg 
88fb4d8502Sjsg struct amdgpu_atif_notifications {
89fb4d8502Sjsg 	bool thermal_state;
90fb4d8502Sjsg 	bool forced_power_state;
91fb4d8502Sjsg 	bool system_power_state;
92fb4d8502Sjsg 	bool brightness_change;
93fb4d8502Sjsg 	bool dgpu_display_event;
94c349dbc7Sjsg 	bool gpu_package_power_limit;
95fb4d8502Sjsg };
96fb4d8502Sjsg 
97fb4d8502Sjsg struct amdgpu_atif_functions {
98fb4d8502Sjsg 	bool system_params;
99fb4d8502Sjsg 	bool sbios_requests;
100fb4d8502Sjsg 	bool temperature_change;
101c349dbc7Sjsg 	bool query_backlight_transfer_characteristics;
102c349dbc7Sjsg 	bool ready_to_undock;
103c349dbc7Sjsg 	bool external_gpu_information;
104fb4d8502Sjsg };
105fb4d8502Sjsg 
106fb4d8502Sjsg struct amdgpu_atif {
107fb4d8502Sjsg 	acpi_handle handle;
108fb4d8502Sjsg 
109fb4d8502Sjsg 	struct amdgpu_atif_notifications notifications;
110fb4d8502Sjsg 	struct amdgpu_atif_functions functions;
111fb4d8502Sjsg 	struct amdgpu_atif_notification_cfg notification_cfg;
112ad8b1aafSjsg 	struct backlight_device *bd;
113c349dbc7Sjsg 	struct amdgpu_dm_backlight_caps backlight_caps;
114fb4d8502Sjsg };
115fb4d8502Sjsg 
1165ca02815Sjsg struct amdgpu_atcs_functions {
1175ca02815Sjsg 	bool get_ext_state;
1185ca02815Sjsg 	bool pcie_perf_req;
1195ca02815Sjsg 	bool pcie_dev_rdy;
1205ca02815Sjsg 	bool pcie_bus_width;
1215ca02815Sjsg 	bool power_shift_control;
1225ca02815Sjsg };
1235ca02815Sjsg 
1245ca02815Sjsg struct amdgpu_atcs {
1255ca02815Sjsg 	acpi_handle handle;
1265ca02815Sjsg 
1275ca02815Sjsg 	struct amdgpu_atcs_functions functions;
1285ca02815Sjsg };
1295ca02815Sjsg 
1305ca02815Sjsg static struct amdgpu_acpi_priv {
1315ca02815Sjsg 	struct amdgpu_atif atif;
1325ca02815Sjsg 	struct amdgpu_atcs atcs;
1335ca02815Sjsg } amdgpu_acpi_priv;
1345ca02815Sjsg 
135fb4d8502Sjsg /* Call the ATIF method
136fb4d8502Sjsg  */
137fb4d8502Sjsg /**
138fb4d8502Sjsg  * amdgpu_atif_call - call an ATIF method
139fb4d8502Sjsg  *
1405ca02815Sjsg  * @atif: atif structure
141fb4d8502Sjsg  * @function: the ATIF function to execute
142fb4d8502Sjsg  * @params: ATIF function params
143fb4d8502Sjsg  *
144fb4d8502Sjsg  * Executes the requested ATIF function (all asics).
145fb4d8502Sjsg  * Returns a pointer to the acpi output buffer.
146fb4d8502Sjsg  */
147fb4d8502Sjsg static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
148fb4d8502Sjsg 					   int function,
149fb4d8502Sjsg 					   struct acpi_buffer *params)
150fb4d8502Sjsg {
151fb4d8502Sjsg 	acpi_status status;
15220002c28Sjsg 	union acpi_object *obj;
153fb4d8502Sjsg 	union acpi_object atif_arg_elements[2];
154fb4d8502Sjsg 	struct acpi_object_list atif_arg;
155fb4d8502Sjsg 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
156fb4d8502Sjsg 
157fb4d8502Sjsg 	atif_arg.count = 2;
158fb4d8502Sjsg 	atif_arg.pointer = &atif_arg_elements[0];
159fb4d8502Sjsg 
160fb4d8502Sjsg 	atif_arg_elements[0].type = ACPI_TYPE_INTEGER;
161fb4d8502Sjsg 	atif_arg_elements[0].integer.value = function;
162fb4d8502Sjsg 
163fb4d8502Sjsg 	if (params) {
164fb4d8502Sjsg 		atif_arg_elements[1].type = ACPI_TYPE_BUFFER;
165fb4d8502Sjsg 		atif_arg_elements[1].buffer.length = params->length;
166fb4d8502Sjsg 		atif_arg_elements[1].buffer.pointer = params->pointer;
167fb4d8502Sjsg 	} else {
168fb4d8502Sjsg 		/* We need a second fake parameter */
169fb4d8502Sjsg 		atif_arg_elements[1].type = ACPI_TYPE_INTEGER;
170fb4d8502Sjsg 		atif_arg_elements[1].integer.value = 0;
171fb4d8502Sjsg 	}
172fb4d8502Sjsg 
173fb4d8502Sjsg 	status = acpi_evaluate_object(atif->handle, NULL, &atif_arg,
174fb4d8502Sjsg 				      &buffer);
17520002c28Sjsg 	obj = (union acpi_object *)buffer.pointer;
176fb4d8502Sjsg 
1772c8a74f9Sjsg 	/* Fail if calling the method fails */
1782c8a74f9Sjsg 	if (ACPI_FAILURE(status)) {
179fb4d8502Sjsg 		DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
180fb4d8502Sjsg 				 acpi_format_exception(status));
18120002c28Sjsg 		kfree(obj);
182fb4d8502Sjsg 		return NULL;
183fb4d8502Sjsg 	}
184fb4d8502Sjsg 
18520002c28Sjsg 	if (obj->type != ACPI_TYPE_BUFFER) {
18620002c28Sjsg 		DRM_DEBUG_DRIVER("bad object returned from ATIF: %d\n",
18720002c28Sjsg 				 obj->type);
18820002c28Sjsg 		kfree(obj);
18920002c28Sjsg 		return NULL;
19020002c28Sjsg 	}
19120002c28Sjsg 
19220002c28Sjsg 	return obj;
193fb4d8502Sjsg }
194fb4d8502Sjsg 
195fb4d8502Sjsg /**
196fb4d8502Sjsg  * amdgpu_atif_parse_notification - parse supported notifications
197fb4d8502Sjsg  *
198fb4d8502Sjsg  * @n: supported notifications struct
199fb4d8502Sjsg  * @mask: supported notifications mask from ATIF
200fb4d8502Sjsg  *
201fb4d8502Sjsg  * Use the supported notifications mask from ATIF function
202fb4d8502Sjsg  * ATIF_FUNCTION_VERIFY_INTERFACE to determine what notifications
203fb4d8502Sjsg  * are supported (all asics).
204fb4d8502Sjsg  */
205fb4d8502Sjsg static void amdgpu_atif_parse_notification(struct amdgpu_atif_notifications *n, u32 mask)
206fb4d8502Sjsg {
207fb4d8502Sjsg 	n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED;
208fb4d8502Sjsg 	n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED;
209fb4d8502Sjsg 	n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED;
210fb4d8502Sjsg 	n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED;
211fb4d8502Sjsg 	n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED;
212c349dbc7Sjsg 	n->gpu_package_power_limit = mask & ATIF_GPU_PACKAGE_POWER_LIMIT_REQUEST_SUPPORTED;
213fb4d8502Sjsg }
214fb4d8502Sjsg 
215fb4d8502Sjsg /**
216fb4d8502Sjsg  * amdgpu_atif_parse_functions - parse supported functions
217fb4d8502Sjsg  *
218fb4d8502Sjsg  * @f: supported functions struct
219fb4d8502Sjsg  * @mask: supported functions mask from ATIF
220fb4d8502Sjsg  *
221fb4d8502Sjsg  * Use the supported functions mask from ATIF function
222fb4d8502Sjsg  * ATIF_FUNCTION_VERIFY_INTERFACE to determine what functions
223fb4d8502Sjsg  * are supported (all asics).
224fb4d8502Sjsg  */
225fb4d8502Sjsg static void amdgpu_atif_parse_functions(struct amdgpu_atif_functions *f, u32 mask)
226fb4d8502Sjsg {
227fb4d8502Sjsg 	f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED;
228fb4d8502Sjsg 	f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED;
229fb4d8502Sjsg 	f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED;
230c349dbc7Sjsg 	f->query_backlight_transfer_characteristics =
231c349dbc7Sjsg 		mask & ATIF_QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS_SUPPORTED;
232c349dbc7Sjsg 	f->ready_to_undock = mask & ATIF_READY_TO_UNDOCK_NOTIFICATION_SUPPORTED;
233c349dbc7Sjsg 	f->external_gpu_information = mask & ATIF_GET_EXTERNAL_GPU_INFORMATION_SUPPORTED;
234fb4d8502Sjsg }
235fb4d8502Sjsg 
236fb4d8502Sjsg /**
237fb4d8502Sjsg  * amdgpu_atif_verify_interface - verify ATIF
238fb4d8502Sjsg  *
239fb4d8502Sjsg  * @atif: amdgpu atif struct
240fb4d8502Sjsg  *
241fb4d8502Sjsg  * Execute the ATIF_FUNCTION_VERIFY_INTERFACE ATIF function
242fb4d8502Sjsg  * to initialize ATIF and determine what features are supported
243fb4d8502Sjsg  * (all asics).
244fb4d8502Sjsg  * returns 0 on success, error on failure.
245fb4d8502Sjsg  */
246fb4d8502Sjsg static int amdgpu_atif_verify_interface(struct amdgpu_atif *atif)
247fb4d8502Sjsg {
248fb4d8502Sjsg 	union acpi_object *info;
249fb4d8502Sjsg 	struct atif_verify_interface output;
250fb4d8502Sjsg 	size_t size;
251fb4d8502Sjsg 	int err = 0;
252fb4d8502Sjsg 
253fb4d8502Sjsg 	info = amdgpu_atif_call(atif, ATIF_FUNCTION_VERIFY_INTERFACE, NULL);
254fb4d8502Sjsg 	if (!info)
255fb4d8502Sjsg 		return -EIO;
256fb4d8502Sjsg 
257fb4d8502Sjsg 	memset(&output, 0, sizeof(output));
258fb4d8502Sjsg 
259fb4d8502Sjsg 	size = *(u16 *) info->buffer.pointer;
260fb4d8502Sjsg 	if (size < 12) {
261fb4d8502Sjsg 		DRM_INFO("ATIF buffer is too small: %zu\n", size);
262fb4d8502Sjsg 		err = -EINVAL;
263fb4d8502Sjsg 		goto out;
264fb4d8502Sjsg 	}
265fb4d8502Sjsg 	size = min(sizeof(output), size);
266fb4d8502Sjsg 
267fb4d8502Sjsg 	memcpy(&output, info->buffer.pointer, size);
268fb4d8502Sjsg 
269fb4d8502Sjsg 	/* TODO: check version? */
270fb4d8502Sjsg 	DRM_DEBUG_DRIVER("ATIF version %u\n", output.version);
271fb4d8502Sjsg 
272fb4d8502Sjsg 	amdgpu_atif_parse_notification(&atif->notifications, output.notification_mask);
273fb4d8502Sjsg 	amdgpu_atif_parse_functions(&atif->functions, output.function_bits);
274fb4d8502Sjsg 
275fb4d8502Sjsg out:
276fb4d8502Sjsg 	kfree(info);
277fb4d8502Sjsg 	return err;
278fb4d8502Sjsg }
279fb4d8502Sjsg 
280fb4d8502Sjsg /**
281fb4d8502Sjsg  * amdgpu_atif_get_notification_params - determine notify configuration
282fb4d8502Sjsg  *
2835ca02815Sjsg  * @atif: acpi handle
284fb4d8502Sjsg  *
285fb4d8502Sjsg  * Execute the ATIF_FUNCTION_GET_SYSTEM_PARAMETERS ATIF function
286fb4d8502Sjsg  * to determine if a notifier is used and if so which one
287fb4d8502Sjsg  * (all asics).  This is either Notify(VGA, 0x81) or Notify(VGA, n)
288fb4d8502Sjsg  * where n is specified in the result if a notifier is used.
289fb4d8502Sjsg  * Returns 0 on success, error on failure.
290fb4d8502Sjsg  */
291fb4d8502Sjsg static int amdgpu_atif_get_notification_params(struct amdgpu_atif *atif)
292fb4d8502Sjsg {
293fb4d8502Sjsg 	union acpi_object *info;
294fb4d8502Sjsg 	struct amdgpu_atif_notification_cfg *n = &atif->notification_cfg;
295fb4d8502Sjsg 	struct atif_system_params params;
296fb4d8502Sjsg 	size_t size;
297fb4d8502Sjsg 	int err = 0;
298fb4d8502Sjsg 
299fb4d8502Sjsg 	info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS,
300fb4d8502Sjsg 				NULL);
301fb4d8502Sjsg 	if (!info) {
302fb4d8502Sjsg 		err = -EIO;
303fb4d8502Sjsg 		goto out;
304fb4d8502Sjsg 	}
305fb4d8502Sjsg 
306fb4d8502Sjsg 	size = *(u16 *) info->buffer.pointer;
307fb4d8502Sjsg 	if (size < 10) {
308fb4d8502Sjsg 		err = -EINVAL;
309fb4d8502Sjsg 		goto out;
310fb4d8502Sjsg 	}
311fb4d8502Sjsg 
312fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
313fb4d8502Sjsg 	size = min(sizeof(params), size);
314fb4d8502Sjsg 	memcpy(&params, info->buffer.pointer, size);
315fb4d8502Sjsg 
316fb4d8502Sjsg 	DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n",
317fb4d8502Sjsg 			params.flags, params.valid_mask);
318fb4d8502Sjsg 	params.flags = params.flags & params.valid_mask;
319fb4d8502Sjsg 
320fb4d8502Sjsg 	if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) {
321fb4d8502Sjsg 		n->enabled = false;
322fb4d8502Sjsg 		n->command_code = 0;
323fb4d8502Sjsg 	} else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) {
324fb4d8502Sjsg 		n->enabled = true;
325fb4d8502Sjsg 		n->command_code = 0x81;
326fb4d8502Sjsg 	} else {
327fb4d8502Sjsg 		if (size < 11) {
328fb4d8502Sjsg 			err = -EINVAL;
329fb4d8502Sjsg 			goto out;
330fb4d8502Sjsg 		}
331fb4d8502Sjsg 		n->enabled = true;
332fb4d8502Sjsg 		n->command_code = params.command_code;
333fb4d8502Sjsg 	}
334fb4d8502Sjsg 
335fb4d8502Sjsg out:
336fb4d8502Sjsg 	DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n",
337fb4d8502Sjsg 			(n->enabled ? "enabled" : "disabled"),
338fb4d8502Sjsg 			n->command_code);
339fb4d8502Sjsg 	kfree(info);
340fb4d8502Sjsg 	return err;
341fb4d8502Sjsg }
342fb4d8502Sjsg 
343fb4d8502Sjsg /**
344c349dbc7Sjsg  * amdgpu_atif_query_backlight_caps - get min and max backlight input signal
345c349dbc7Sjsg  *
3465ca02815Sjsg  * @atif: acpi handle
347c349dbc7Sjsg  *
348c349dbc7Sjsg  * Execute the QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS ATIF function
349c349dbc7Sjsg  * to determine the acceptable range of backlight values
350c349dbc7Sjsg  *
351c349dbc7Sjsg  * Backlight_caps.caps_valid will be set to true if the query is successful
352c349dbc7Sjsg  *
353c349dbc7Sjsg  * The input signals are in range 0-255
354c349dbc7Sjsg  *
355c349dbc7Sjsg  * This function assumes the display with backlight is the first LCD
356c349dbc7Sjsg  *
357c349dbc7Sjsg  * Returns 0 on success, error on failure.
358c349dbc7Sjsg  */
359c349dbc7Sjsg static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif)
360c349dbc7Sjsg {
361c349dbc7Sjsg 	union acpi_object *info;
362c349dbc7Sjsg 	struct atif_qbtc_output characteristics;
363c349dbc7Sjsg 	struct atif_qbtc_arguments arguments;
364c349dbc7Sjsg 	struct acpi_buffer params;
365c349dbc7Sjsg 	size_t size;
366c349dbc7Sjsg 	int err = 0;
367c349dbc7Sjsg 
368c349dbc7Sjsg 	arguments.size = sizeof(arguments);
369c349dbc7Sjsg 	arguments.requested_display = ATIF_QBTC_REQUEST_LCD1;
370c349dbc7Sjsg 
371c349dbc7Sjsg 	params.length = sizeof(arguments);
372c349dbc7Sjsg 	params.pointer = (void *)&arguments;
373c349dbc7Sjsg 
374c349dbc7Sjsg 	info = amdgpu_atif_call(atif,
375c349dbc7Sjsg 		ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS,
376c349dbc7Sjsg 		&params);
377c349dbc7Sjsg 	if (!info) {
378c349dbc7Sjsg 		err = -EIO;
379c349dbc7Sjsg 		goto out;
380c349dbc7Sjsg 	}
381c349dbc7Sjsg 
382c349dbc7Sjsg 	size = *(u16 *) info->buffer.pointer;
383c349dbc7Sjsg 	if (size < 10) {
384c349dbc7Sjsg 		err = -EINVAL;
385c349dbc7Sjsg 		goto out;
386c349dbc7Sjsg 	}
387c349dbc7Sjsg 
388c349dbc7Sjsg 	memset(&characteristics, 0, sizeof(characteristics));
389c349dbc7Sjsg 	size = min(sizeof(characteristics), size);
390c349dbc7Sjsg 	memcpy(&characteristics, info->buffer.pointer, size);
391c349dbc7Sjsg 
392c349dbc7Sjsg 	atif->backlight_caps.caps_valid = true;
393c349dbc7Sjsg 	atif->backlight_caps.min_input_signal =
394c349dbc7Sjsg 			characteristics.min_input_signal;
395c349dbc7Sjsg 	atif->backlight_caps.max_input_signal =
396c349dbc7Sjsg 			characteristics.max_input_signal;
397c349dbc7Sjsg out:
398c349dbc7Sjsg 	kfree(info);
399c349dbc7Sjsg 	return err;
400c349dbc7Sjsg }
401c349dbc7Sjsg 
402c349dbc7Sjsg /**
403fb4d8502Sjsg  * amdgpu_atif_get_sbios_requests - get requested sbios event
404fb4d8502Sjsg  *
4055ca02815Sjsg  * @atif: acpi handle
406fb4d8502Sjsg  * @req: atif sbios request struct
407fb4d8502Sjsg  *
408fb4d8502Sjsg  * Execute the ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS ATIF function
409fb4d8502Sjsg  * to determine what requests the sbios is making to the driver
410fb4d8502Sjsg  * (all asics).
411fb4d8502Sjsg  * Returns 0 on success, error on failure.
412fb4d8502Sjsg  */
413fb4d8502Sjsg static int amdgpu_atif_get_sbios_requests(struct amdgpu_atif *atif,
414fb4d8502Sjsg 					  struct atif_sbios_requests *req)
415fb4d8502Sjsg {
416fb4d8502Sjsg 	union acpi_object *info;
417fb4d8502Sjsg 	size_t size;
418fb4d8502Sjsg 	int count = 0;
419fb4d8502Sjsg 
420fb4d8502Sjsg 	info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS,
421fb4d8502Sjsg 				NULL);
422fb4d8502Sjsg 	if (!info)
423fb4d8502Sjsg 		return -EIO;
424fb4d8502Sjsg 
425fb4d8502Sjsg 	size = *(u16 *)info->buffer.pointer;
426fb4d8502Sjsg 	if (size < 0xd) {
427fb4d8502Sjsg 		count = -EINVAL;
428fb4d8502Sjsg 		goto out;
429fb4d8502Sjsg 	}
430fb4d8502Sjsg 	memset(req, 0, sizeof(*req));
431fb4d8502Sjsg 
432fb4d8502Sjsg 	size = min(sizeof(*req), size);
433fb4d8502Sjsg 	memcpy(req, info->buffer.pointer, size);
434fb4d8502Sjsg 	DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending);
435fb4d8502Sjsg 
436fb4d8502Sjsg 	count = hweight32(req->pending);
437fb4d8502Sjsg 
438fb4d8502Sjsg out:
439fb4d8502Sjsg 	kfree(info);
440fb4d8502Sjsg 	return count;
441fb4d8502Sjsg }
442fb4d8502Sjsg 
443fb4d8502Sjsg /**
444fb4d8502Sjsg  * amdgpu_atif_handler - handle ATIF notify requests
445fb4d8502Sjsg  *
446fb4d8502Sjsg  * @adev: amdgpu_device pointer
447fb4d8502Sjsg  * @event: atif sbios request struct
448fb4d8502Sjsg  *
449fb4d8502Sjsg  * Checks the acpi event and if it matches an atif event,
450fb4d8502Sjsg  * handles it.
451fb4d8502Sjsg  *
452fb4d8502Sjsg  * Returns:
453fb4d8502Sjsg  * NOTIFY_BAD or NOTIFY_DONE, depending on the event.
454fb4d8502Sjsg  */
455fb4d8502Sjsg static int amdgpu_atif_handler(struct amdgpu_device *adev,
456fb4d8502Sjsg 			       struct acpi_bus_event *event)
457fb4d8502Sjsg {
4585ca02815Sjsg 	struct amdgpu_atif *atif = &amdgpu_acpi_priv.atif;
459fb4d8502Sjsg 	int count;
460fb4d8502Sjsg 
461fb4d8502Sjsg 	DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n",
462fb4d8502Sjsg 			event->device_class, event->type);
463fb4d8502Sjsg 
464fb4d8502Sjsg 	if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
465fb4d8502Sjsg 		return NOTIFY_DONE;
466fb4d8502Sjsg 
467fb4d8502Sjsg 	/* Is this actually our event? */
4685ca02815Sjsg 	if (!atif->notification_cfg.enabled ||
469fb4d8502Sjsg 	    event->type != atif->notification_cfg.command_code) {
470fb4d8502Sjsg 		/* These events will generate keypresses otherwise */
471fb4d8502Sjsg 		if (event->type == ACPI_VIDEO_NOTIFY_PROBE)
472fb4d8502Sjsg 			return NOTIFY_BAD;
473fb4d8502Sjsg 		else
474fb4d8502Sjsg 			return NOTIFY_DONE;
475fb4d8502Sjsg 	}
476fb4d8502Sjsg 
477fb4d8502Sjsg 	if (atif->functions.sbios_requests) {
478fb4d8502Sjsg 		struct atif_sbios_requests req;
479fb4d8502Sjsg 
480fb4d8502Sjsg 		/* Check pending SBIOS requests */
481fb4d8502Sjsg 		count = amdgpu_atif_get_sbios_requests(atif, &req);
482fb4d8502Sjsg 
483fb4d8502Sjsg 		if (count <= 0)
484fb4d8502Sjsg 			return NOTIFY_BAD;
485fb4d8502Sjsg 
486fb4d8502Sjsg 		DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count);
487fb4d8502Sjsg 
488ad8b1aafSjsg 		if (req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) {
489ad8b1aafSjsg 			if (atif->bd) {
490fb4d8502Sjsg 				DRM_DEBUG_DRIVER("Changing brightness to %d\n",
491fb4d8502Sjsg 						 req.backlight_level);
492ad8b1aafSjsg 				/*
493ad8b1aafSjsg 				 * XXX backlight_device_set_brightness() is
494ad8b1aafSjsg 				 * hardwired to post BACKLIGHT_UPDATE_SYSFS.
495ad8b1aafSjsg 				 * It probably should accept 'reason' parameter.
496ad8b1aafSjsg 				 */
497ad8b1aafSjsg 				backlight_device_set_brightness(atif->bd, req.backlight_level);
498ad8b1aafSjsg 			}
499fb4d8502Sjsg 		}
500ad8b1aafSjsg 
501fb4d8502Sjsg 		if (req.pending & ATIF_DGPU_DISPLAY_EVENT) {
50296ac00dcSjsg 			if (adev->flags & AMD_IS_PX) {
503ad8b1aafSjsg 				pm_runtime_get_sync(adev_to_drm(adev)->dev);
504fb4d8502Sjsg 				/* Just fire off a uevent and let userspace tell us what to do */
505ad8b1aafSjsg 				drm_helper_hpd_irq_event(adev_to_drm(adev));
506ad8b1aafSjsg 				pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
507ad8b1aafSjsg 				pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
508fb4d8502Sjsg 			}
509fb4d8502Sjsg 		}
510fb4d8502Sjsg 		/* TODO: check other events */
511fb4d8502Sjsg 	}
512fb4d8502Sjsg 
513fb4d8502Sjsg 	/* We've handled the event, stop the notifier chain. The ACPI interface
514fb4d8502Sjsg 	 * overloads ACPI_VIDEO_NOTIFY_PROBE, we don't want to send that to
515fb4d8502Sjsg 	 * userspace if the event was generated only to signal a SBIOS
516fb4d8502Sjsg 	 * request.
517fb4d8502Sjsg 	 */
518fb4d8502Sjsg 	return NOTIFY_BAD;
519fb4d8502Sjsg }
520fb4d8502Sjsg 
521fb4d8502Sjsg /* Call the ATCS method
522fb4d8502Sjsg  */
523fb4d8502Sjsg /**
524fb4d8502Sjsg  * amdgpu_atcs_call - call an ATCS method
525fb4d8502Sjsg  *
5265ca02815Sjsg  * @atcs: atcs structure
527fb4d8502Sjsg  * @function: the ATCS function to execute
528fb4d8502Sjsg  * @params: ATCS function params
529fb4d8502Sjsg  *
530fb4d8502Sjsg  * Executes the requested ATCS function (all asics).
531fb4d8502Sjsg  * Returns a pointer to the acpi output buffer.
532fb4d8502Sjsg  */
5335ca02815Sjsg static union acpi_object *amdgpu_atcs_call(struct amdgpu_atcs *atcs,
5345ca02815Sjsg 					   int function,
535fb4d8502Sjsg 					   struct acpi_buffer *params)
536fb4d8502Sjsg {
537fb4d8502Sjsg 	acpi_status status;
538fb4d8502Sjsg 	union acpi_object atcs_arg_elements[2];
539fb4d8502Sjsg 	struct acpi_object_list atcs_arg;
540fb4d8502Sjsg 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
541fb4d8502Sjsg 
542fb4d8502Sjsg 	atcs_arg.count = 2;
543fb4d8502Sjsg 	atcs_arg.pointer = &atcs_arg_elements[0];
544fb4d8502Sjsg 
545fb4d8502Sjsg 	atcs_arg_elements[0].type = ACPI_TYPE_INTEGER;
546fb4d8502Sjsg 	atcs_arg_elements[0].integer.value = function;
547fb4d8502Sjsg 
548fb4d8502Sjsg 	if (params) {
549fb4d8502Sjsg 		atcs_arg_elements[1].type = ACPI_TYPE_BUFFER;
550fb4d8502Sjsg 		atcs_arg_elements[1].buffer.length = params->length;
551fb4d8502Sjsg 		atcs_arg_elements[1].buffer.pointer = params->pointer;
552fb4d8502Sjsg 	} else {
553fb4d8502Sjsg 		/* We need a second fake parameter */
554fb4d8502Sjsg 		atcs_arg_elements[1].type = ACPI_TYPE_INTEGER;
555fb4d8502Sjsg 		atcs_arg_elements[1].integer.value = 0;
556fb4d8502Sjsg 	}
557fb4d8502Sjsg 
5585ca02815Sjsg 	status = acpi_evaluate_object(atcs->handle, NULL, &atcs_arg, &buffer);
559fb4d8502Sjsg 
560fb4d8502Sjsg 	/* Fail only if calling the method fails and ATIF is supported */
561fb4d8502Sjsg 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
562fb4d8502Sjsg 		DRM_DEBUG_DRIVER("failed to evaluate ATCS got %s\n",
563fb4d8502Sjsg 				 acpi_format_exception(status));
564fb4d8502Sjsg 		kfree(buffer.pointer);
565fb4d8502Sjsg 		return NULL;
566fb4d8502Sjsg 	}
567fb4d8502Sjsg 
568fb4d8502Sjsg 	return buffer.pointer;
569fb4d8502Sjsg }
570fb4d8502Sjsg 
571fb4d8502Sjsg /**
572fb4d8502Sjsg  * amdgpu_atcs_parse_functions - parse supported functions
573fb4d8502Sjsg  *
574fb4d8502Sjsg  * @f: supported functions struct
575fb4d8502Sjsg  * @mask: supported functions mask from ATCS
576fb4d8502Sjsg  *
577fb4d8502Sjsg  * Use the supported functions mask from ATCS function
578fb4d8502Sjsg  * ATCS_FUNCTION_VERIFY_INTERFACE to determine what functions
579fb4d8502Sjsg  * are supported (all asics).
580fb4d8502Sjsg  */
581fb4d8502Sjsg static void amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions *f, u32 mask)
582fb4d8502Sjsg {
583fb4d8502Sjsg 	f->get_ext_state = mask & ATCS_GET_EXTERNAL_STATE_SUPPORTED;
584fb4d8502Sjsg 	f->pcie_perf_req = mask & ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED;
585fb4d8502Sjsg 	f->pcie_dev_rdy = mask & ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED;
586fb4d8502Sjsg 	f->pcie_bus_width = mask & ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED;
5875ca02815Sjsg 	f->power_shift_control = mask & ATCS_SET_POWER_SHIFT_CONTROL_SUPPORTED;
588fb4d8502Sjsg }
589fb4d8502Sjsg 
590fb4d8502Sjsg /**
591fb4d8502Sjsg  * amdgpu_atcs_verify_interface - verify ATCS
592fb4d8502Sjsg  *
593fb4d8502Sjsg  * @atcs: amdgpu atcs struct
594fb4d8502Sjsg  *
595fb4d8502Sjsg  * Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function
596fb4d8502Sjsg  * to initialize ATCS and determine what features are supported
597fb4d8502Sjsg  * (all asics).
598fb4d8502Sjsg  * returns 0 on success, error on failure.
599fb4d8502Sjsg  */
6005ca02815Sjsg static int amdgpu_atcs_verify_interface(struct amdgpu_atcs *atcs)
601fb4d8502Sjsg {
602fb4d8502Sjsg 	union acpi_object *info;
603fb4d8502Sjsg 	struct atcs_verify_interface output;
604fb4d8502Sjsg 	size_t size;
605fb4d8502Sjsg 	int err = 0;
606fb4d8502Sjsg 
6075ca02815Sjsg 	info = amdgpu_atcs_call(atcs, ATCS_FUNCTION_VERIFY_INTERFACE, NULL);
608fb4d8502Sjsg 	if (!info)
609fb4d8502Sjsg 		return -EIO;
610fb4d8502Sjsg 
611fb4d8502Sjsg 	memset(&output, 0, sizeof(output));
612fb4d8502Sjsg 
613fb4d8502Sjsg 	size = *(u16 *) info->buffer.pointer;
614fb4d8502Sjsg 	if (size < 8) {
615fb4d8502Sjsg 		DRM_INFO("ATCS buffer is too small: %zu\n", size);
616fb4d8502Sjsg 		err = -EINVAL;
617fb4d8502Sjsg 		goto out;
618fb4d8502Sjsg 	}
619fb4d8502Sjsg 	size = min(sizeof(output), size);
620fb4d8502Sjsg 
621fb4d8502Sjsg 	memcpy(&output, info->buffer.pointer, size);
622fb4d8502Sjsg 
623fb4d8502Sjsg 	/* TODO: check version? */
624fb4d8502Sjsg 	DRM_DEBUG_DRIVER("ATCS version %u\n", output.version);
625fb4d8502Sjsg 
626fb4d8502Sjsg 	amdgpu_atcs_parse_functions(&atcs->functions, output.function_bits);
627fb4d8502Sjsg 
628fb4d8502Sjsg out:
629fb4d8502Sjsg 	kfree(info);
630fb4d8502Sjsg 	return err;
631fb4d8502Sjsg }
632fb4d8502Sjsg 
633fb4d8502Sjsg /**
634fb4d8502Sjsg  * amdgpu_acpi_is_pcie_performance_request_supported
635fb4d8502Sjsg  *
636fb4d8502Sjsg  * @adev: amdgpu_device pointer
637fb4d8502Sjsg  *
638fb4d8502Sjsg  * Check if the ATCS pcie_perf_req and pcie_dev_rdy methods
639fb4d8502Sjsg  * are supported (all asics).
640fb4d8502Sjsg  * returns true if supported, false if not.
641fb4d8502Sjsg  */
642fb4d8502Sjsg bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *adev)
643fb4d8502Sjsg {
6445ca02815Sjsg 	struct amdgpu_atcs *atcs = &amdgpu_acpi_priv.atcs;
645fb4d8502Sjsg 
646fb4d8502Sjsg 	if (atcs->functions.pcie_perf_req && atcs->functions.pcie_dev_rdy)
647fb4d8502Sjsg 		return true;
648fb4d8502Sjsg 
649fb4d8502Sjsg 	return false;
650fb4d8502Sjsg }
651fb4d8502Sjsg 
652fb4d8502Sjsg /**
6535ca02815Sjsg  * amdgpu_acpi_is_power_shift_control_supported
6545ca02815Sjsg  *
6555ca02815Sjsg  * Check if the ATCS power shift control method
6565ca02815Sjsg  * is supported.
6575ca02815Sjsg  * returns true if supported, false if not.
6585ca02815Sjsg  */
6595ca02815Sjsg bool amdgpu_acpi_is_power_shift_control_supported(void)
6605ca02815Sjsg {
6615ca02815Sjsg 	return amdgpu_acpi_priv.atcs.functions.power_shift_control;
6625ca02815Sjsg }
6635ca02815Sjsg 
6645ca02815Sjsg /**
665fb4d8502Sjsg  * amdgpu_acpi_pcie_notify_device_ready
666fb4d8502Sjsg  *
667fb4d8502Sjsg  * @adev: amdgpu_device pointer
668fb4d8502Sjsg  *
669fb4d8502Sjsg  * Executes the PCIE_DEVICE_READY_NOTIFICATION method
670fb4d8502Sjsg  * (all asics).
671fb4d8502Sjsg  * returns 0 on success, error on failure.
672fb4d8502Sjsg  */
673fb4d8502Sjsg int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev)
674fb4d8502Sjsg {
675fb4d8502Sjsg 	union acpi_object *info;
6765ca02815Sjsg 	struct amdgpu_atcs *atcs = &amdgpu_acpi_priv.atcs;
677fb4d8502Sjsg 
678fb4d8502Sjsg 	if (!atcs->functions.pcie_dev_rdy)
679fb4d8502Sjsg 		return -EINVAL;
680fb4d8502Sjsg 
6815ca02815Sjsg 	info = amdgpu_atcs_call(atcs, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION, NULL);
682fb4d8502Sjsg 	if (!info)
683fb4d8502Sjsg 		return -EIO;
684fb4d8502Sjsg 
685fb4d8502Sjsg 	kfree(info);
686fb4d8502Sjsg 
687fb4d8502Sjsg 	return 0;
688fb4d8502Sjsg }
689fb4d8502Sjsg 
690fb4d8502Sjsg /**
691fb4d8502Sjsg  * amdgpu_acpi_pcie_performance_request
692fb4d8502Sjsg  *
693fb4d8502Sjsg  * @adev: amdgpu_device pointer
694fb4d8502Sjsg  * @perf_req: requested perf level (pcie gen speed)
695fb4d8502Sjsg  * @advertise: set advertise caps flag if set
696fb4d8502Sjsg  *
697fb4d8502Sjsg  * Executes the PCIE_PERFORMANCE_REQUEST method to
698fb4d8502Sjsg  * change the pcie gen speed (all asics).
699fb4d8502Sjsg  * returns 0 on success, error on failure.
700fb4d8502Sjsg  */
701fb4d8502Sjsg int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev,
702fb4d8502Sjsg 					 u8 perf_req, bool advertise)
703fb4d8502Sjsg {
704fb4d8502Sjsg 	union acpi_object *info;
7055ca02815Sjsg 	struct amdgpu_atcs *atcs = &amdgpu_acpi_priv.atcs;
706fb4d8502Sjsg 	struct atcs_pref_req_input atcs_input;
707fb4d8502Sjsg 	struct atcs_pref_req_output atcs_output;
708fb4d8502Sjsg 	struct acpi_buffer params;
709fb4d8502Sjsg 	size_t size;
710fb4d8502Sjsg 	u32 retry = 3;
711fb4d8502Sjsg 
712fb4d8502Sjsg 	if (amdgpu_acpi_pcie_notify_device_ready(adev))
713fb4d8502Sjsg 		return -EINVAL;
714fb4d8502Sjsg 
715fb4d8502Sjsg 	if (!atcs->functions.pcie_perf_req)
716fb4d8502Sjsg 		return -EINVAL;
717fb4d8502Sjsg 
718fb4d8502Sjsg 	atcs_input.size = sizeof(struct atcs_pref_req_input);
719fb4d8502Sjsg 	/* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */
720f005ef32Sjsg 	atcs_input.client_id = pci_dev_id(adev->pdev);
721fb4d8502Sjsg 	atcs_input.valid_flags_mask = ATCS_VALID_FLAGS_MASK;
722fb4d8502Sjsg 	atcs_input.flags = ATCS_WAIT_FOR_COMPLETION;
723fb4d8502Sjsg 	if (advertise)
724fb4d8502Sjsg 		atcs_input.flags |= ATCS_ADVERTISE_CAPS;
725fb4d8502Sjsg 	atcs_input.req_type = ATCS_PCIE_LINK_SPEED;
726fb4d8502Sjsg 	atcs_input.perf_req = perf_req;
727fb4d8502Sjsg 
728fb4d8502Sjsg 	params.length = sizeof(struct atcs_pref_req_input);
729fb4d8502Sjsg 	params.pointer = &atcs_input;
730fb4d8502Sjsg 
731fb4d8502Sjsg 	while (retry--) {
7325ca02815Sjsg 		info = amdgpu_atcs_call(atcs, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, &params);
733fb4d8502Sjsg 		if (!info)
734fb4d8502Sjsg 			return -EIO;
735fb4d8502Sjsg 
736fb4d8502Sjsg 		memset(&atcs_output, 0, sizeof(atcs_output));
737fb4d8502Sjsg 
738fb4d8502Sjsg 		size = *(u16 *) info->buffer.pointer;
739fb4d8502Sjsg 		if (size < 3) {
740fb4d8502Sjsg 			DRM_INFO("ATCS buffer is too small: %zu\n", size);
741fb4d8502Sjsg 			kfree(info);
742fb4d8502Sjsg 			return -EINVAL;
743fb4d8502Sjsg 		}
744fb4d8502Sjsg 		size = min(sizeof(atcs_output), size);
745fb4d8502Sjsg 
746fb4d8502Sjsg 		memcpy(&atcs_output, info->buffer.pointer, size);
747fb4d8502Sjsg 
748fb4d8502Sjsg 		kfree(info);
749fb4d8502Sjsg 
750fb4d8502Sjsg 		switch (atcs_output.ret_val) {
751fb4d8502Sjsg 		case ATCS_REQUEST_REFUSED:
752fb4d8502Sjsg 		default:
753fb4d8502Sjsg 			return -EINVAL;
754fb4d8502Sjsg 		case ATCS_REQUEST_COMPLETE:
755fb4d8502Sjsg 			return 0;
756fb4d8502Sjsg 		case ATCS_REQUEST_IN_PROGRESS:
757fb4d8502Sjsg 			udelay(10);
758fb4d8502Sjsg 			break;
759fb4d8502Sjsg 		}
760fb4d8502Sjsg 	}
761fb4d8502Sjsg 
762fb4d8502Sjsg 	return 0;
763fb4d8502Sjsg }
764fb4d8502Sjsg 
765fb4d8502Sjsg /**
7665ca02815Sjsg  * amdgpu_acpi_power_shift_control
7675ca02815Sjsg  *
7685ca02815Sjsg  * @adev: amdgpu_device pointer
7695ca02815Sjsg  * @dev_state: device acpi state
7705ca02815Sjsg  * @drv_state: driver state
7715ca02815Sjsg  *
7725ca02815Sjsg  * Executes the POWER_SHIFT_CONTROL method to
7735ca02815Sjsg  * communicate current dGPU device state and
7745ca02815Sjsg  * driver state to APU/SBIOS.
7755ca02815Sjsg  * returns 0 on success, error on failure.
7765ca02815Sjsg  */
7775ca02815Sjsg int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
7785ca02815Sjsg 				    u8 dev_state, bool drv_state)
7795ca02815Sjsg {
7805ca02815Sjsg 	union acpi_object *info;
7815ca02815Sjsg 	struct amdgpu_atcs *atcs = &amdgpu_acpi_priv.atcs;
7825ca02815Sjsg 	struct atcs_pwr_shift_input atcs_input;
7835ca02815Sjsg 	struct acpi_buffer params;
7845ca02815Sjsg 
7855ca02815Sjsg 	if (!amdgpu_acpi_is_power_shift_control_supported())
7865ca02815Sjsg 		return -EINVAL;
7875ca02815Sjsg 
7885ca02815Sjsg 	atcs_input.size = sizeof(struct atcs_pwr_shift_input);
7895ca02815Sjsg 	/* dGPU id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */
790f005ef32Sjsg 	atcs_input.dgpu_id = pci_dev_id(adev->pdev);
7915ca02815Sjsg 	atcs_input.dev_acpi_state = dev_state;
7925ca02815Sjsg 	atcs_input.drv_state = drv_state;
7935ca02815Sjsg 
7945ca02815Sjsg 	params.length = sizeof(struct atcs_pwr_shift_input);
7955ca02815Sjsg 	params.pointer = &atcs_input;
7965ca02815Sjsg 
7975ca02815Sjsg 	info = amdgpu_atcs_call(atcs, ATCS_FUNCTION_POWER_SHIFT_CONTROL, &params);
7985ca02815Sjsg 	if (!info) {
7995ca02815Sjsg 		DRM_ERROR("ATCS PSC update failed\n");
8005ca02815Sjsg 		return -EIO;
8015ca02815Sjsg 	}
8025ca02815Sjsg 
803*8ac6d3a7Sjsg 	kfree(info);
8045ca02815Sjsg 	return 0;
8055ca02815Sjsg }
8065ca02815Sjsg 
8075ca02815Sjsg /**
8085ca02815Sjsg  * amdgpu_acpi_smart_shift_update - update dGPU device state to SBIOS
8095ca02815Sjsg  *
8105ca02815Sjsg  * @dev: drm_device pointer
8115ca02815Sjsg  * @ss_state: current smart shift event
8125ca02815Sjsg  *
8135ca02815Sjsg  * returns 0 on success,
8145ca02815Sjsg  * otherwise return error number.
8155ca02815Sjsg  */
8165ca02815Sjsg int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_state)
8175ca02815Sjsg {
8185ca02815Sjsg 	struct amdgpu_device *adev = drm_to_adev(dev);
8195ca02815Sjsg 	int r;
8205ca02815Sjsg 
8215ca02815Sjsg 	if (!amdgpu_device_supports_smart_shift(dev))
8225ca02815Sjsg 		return 0;
8235ca02815Sjsg 
8245ca02815Sjsg 	switch (ss_state) {
8255ca02815Sjsg 	/* SBIOS trigger “stop”, “enable” and “start” at D0, Driver Operational.
8265ca02815Sjsg 	 * SBIOS trigger “stop” at D3, Driver Not Operational.
8275ca02815Sjsg 	 * SBIOS trigger “stop” and “disable” at D0, Driver NOT operational.
8285ca02815Sjsg 	 */
8295ca02815Sjsg 	case AMDGPU_SS_DRV_LOAD:
8305ca02815Sjsg 		r = amdgpu_acpi_power_shift_control(adev,
8315ca02815Sjsg 						    AMDGPU_ATCS_PSC_DEV_STATE_D0,
8325ca02815Sjsg 						    AMDGPU_ATCS_PSC_DRV_STATE_OPR);
8335ca02815Sjsg 		break;
8345ca02815Sjsg 	case AMDGPU_SS_DEV_D0:
8355ca02815Sjsg 		r = amdgpu_acpi_power_shift_control(adev,
8365ca02815Sjsg 						    AMDGPU_ATCS_PSC_DEV_STATE_D0,
8375ca02815Sjsg 						    AMDGPU_ATCS_PSC_DRV_STATE_OPR);
8385ca02815Sjsg 		break;
8395ca02815Sjsg 	case AMDGPU_SS_DEV_D3:
8405ca02815Sjsg 		r = amdgpu_acpi_power_shift_control(adev,
8415ca02815Sjsg 						    AMDGPU_ATCS_PSC_DEV_STATE_D3_HOT,
8425ca02815Sjsg 						    AMDGPU_ATCS_PSC_DRV_STATE_NOT_OPR);
8435ca02815Sjsg 		break;
8445ca02815Sjsg 	case AMDGPU_SS_DRV_UNLOAD:
8455ca02815Sjsg 		r = amdgpu_acpi_power_shift_control(adev,
8465ca02815Sjsg 						    AMDGPU_ATCS_PSC_DEV_STATE_D0,
8475ca02815Sjsg 						    AMDGPU_ATCS_PSC_DRV_STATE_NOT_OPR);
8485ca02815Sjsg 		break;
8495ca02815Sjsg 	default:
8505ca02815Sjsg 		return -EINVAL;
8515ca02815Sjsg 	}
8525ca02815Sjsg 
8535ca02815Sjsg 	return r;
8545ca02815Sjsg }
8555ca02815Sjsg 
856f005ef32Sjsg #ifdef CONFIG_ACPI_NUMA
857f005ef32Sjsg static inline uint64_t amdgpu_acpi_get_numa_size(int nid)
858f005ef32Sjsg {
859f005ef32Sjsg 	/* This is directly using si_meminfo_node implementation as the
860f005ef32Sjsg 	 * function is not exported.
861f005ef32Sjsg 	 */
862f005ef32Sjsg 	int zone_type;
863f005ef32Sjsg 	uint64_t managed_pages = 0;
864f005ef32Sjsg 
865f005ef32Sjsg 	pg_data_t *pgdat = NODE_DATA(nid);
866f005ef32Sjsg 
867f005ef32Sjsg 	for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++)
868f005ef32Sjsg 		managed_pages +=
869f005ef32Sjsg 			zone_managed_pages(&pgdat->node_zones[zone_type]);
870f005ef32Sjsg 	return managed_pages * PAGE_SIZE;
871f005ef32Sjsg }
872f005ef32Sjsg 
873f005ef32Sjsg static struct amdgpu_numa_info *amdgpu_acpi_get_numa_info(uint32_t pxm)
874f005ef32Sjsg {
875f005ef32Sjsg 	struct amdgpu_numa_info *numa_info;
876f005ef32Sjsg 	int nid;
877f005ef32Sjsg 
878f005ef32Sjsg 	numa_info = xa_load(&numa_info_xa, pxm);
879f005ef32Sjsg 
880f005ef32Sjsg 	if (!numa_info) {
881f005ef32Sjsg 		struct sysinfo info;
882f005ef32Sjsg 
883f005ef32Sjsg 		numa_info = kzalloc(sizeof(*numa_info), GFP_KERNEL);
884f005ef32Sjsg 		if (!numa_info)
885f005ef32Sjsg 			return NULL;
886f005ef32Sjsg 
887f005ef32Sjsg 		nid = pxm_to_node(pxm);
888f005ef32Sjsg 		numa_info->pxm = pxm;
889f005ef32Sjsg 		numa_info->nid = nid;
890f005ef32Sjsg 
891f005ef32Sjsg 		if (numa_info->nid == NUMA_NO_NODE) {
892f005ef32Sjsg 			si_meminfo(&info);
893f005ef32Sjsg 			numa_info->size = info.totalram * info.mem_unit;
894f005ef32Sjsg 		} else {
895f005ef32Sjsg 			numa_info->size = amdgpu_acpi_get_numa_size(nid);
896f005ef32Sjsg 		}
897f005ef32Sjsg 		xa_store(&numa_info_xa, numa_info->pxm, numa_info, GFP_KERNEL);
898f005ef32Sjsg 	}
899f005ef32Sjsg 
900f005ef32Sjsg 	return numa_info;
901f005ef32Sjsg }
902f005ef32Sjsg #endif
903f005ef32Sjsg 
904f005ef32Sjsg /**
905f005ef32Sjsg  * amdgpu_acpi_get_node_id - obtain the NUMA node id for corresponding amdgpu
906f005ef32Sjsg  * acpi device handle
907f005ef32Sjsg  *
908f005ef32Sjsg  * @handle: acpi handle
909f005ef32Sjsg  * @numa_info: amdgpu_numa_info structure holding numa information
910f005ef32Sjsg  *
911f005ef32Sjsg  * Queries the ACPI interface to fetch the corresponding NUMA Node ID for a
912f005ef32Sjsg  * given amdgpu acpi device.
913f005ef32Sjsg  *
914f005ef32Sjsg  * Returns ACPI STATUS OK with Node ID on success or the corresponding failure reason
915f005ef32Sjsg  */
916f005ef32Sjsg static acpi_status amdgpu_acpi_get_node_id(acpi_handle handle,
917f005ef32Sjsg 				    struct amdgpu_numa_info **numa_info)
918f005ef32Sjsg {
919f005ef32Sjsg #ifdef CONFIG_ACPI_NUMA
920f005ef32Sjsg 	u64 pxm;
921f005ef32Sjsg 	acpi_status status;
922f005ef32Sjsg 
923f005ef32Sjsg 	if (!numa_info)
924f005ef32Sjsg 		return_ACPI_STATUS(AE_ERROR);
925f005ef32Sjsg 
926f005ef32Sjsg 	status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
927f005ef32Sjsg 
928f005ef32Sjsg 	if (ACPI_FAILURE(status))
929f005ef32Sjsg 		return status;
930f005ef32Sjsg 
931f005ef32Sjsg 	*numa_info = amdgpu_acpi_get_numa_info(pxm);
932f005ef32Sjsg 
933f005ef32Sjsg 	if (!*numa_info)
934f005ef32Sjsg 		return_ACPI_STATUS(AE_ERROR);
935f005ef32Sjsg 
936f005ef32Sjsg 	return_ACPI_STATUS(AE_OK);
937f005ef32Sjsg #else
938f005ef32Sjsg 	return_ACPI_STATUS(AE_NOT_EXIST);
939f005ef32Sjsg #endif
940f005ef32Sjsg }
941f005ef32Sjsg 
942f005ef32Sjsg static struct amdgpu_acpi_dev_info *amdgpu_acpi_get_dev(u16 bdf)
943f005ef32Sjsg {
944f005ef32Sjsg 	struct amdgpu_acpi_dev_info *acpi_dev;
945f005ef32Sjsg 
946f005ef32Sjsg 	if (list_empty(&amdgpu_acpi_dev_list))
947f005ef32Sjsg 		return NULL;
948f005ef32Sjsg 
949f005ef32Sjsg 	list_for_each_entry(acpi_dev, &amdgpu_acpi_dev_list, list)
950f005ef32Sjsg 		if (acpi_dev->bdf == bdf)
951f005ef32Sjsg 			return acpi_dev;
952f005ef32Sjsg 
953f005ef32Sjsg 	return NULL;
954f005ef32Sjsg }
955f005ef32Sjsg 
956f005ef32Sjsg static int amdgpu_acpi_dev_init(struct amdgpu_acpi_dev_info **dev_info,
957f005ef32Sjsg 				struct amdgpu_acpi_xcc_info *xcc_info, u16 bdf)
958f005ef32Sjsg {
959f005ef32Sjsg 	struct amdgpu_acpi_dev_info *tmp;
960f005ef32Sjsg 	union acpi_object *obj;
961f005ef32Sjsg 	int ret = -ENOENT;
962f005ef32Sjsg 
963f005ef32Sjsg 	*dev_info = NULL;
964f005ef32Sjsg 	tmp = kzalloc(sizeof(struct amdgpu_acpi_dev_info), GFP_KERNEL);
965f005ef32Sjsg 	if (!tmp)
966f005ef32Sjsg 		return -ENOMEM;
967f005ef32Sjsg 
968f005ef32Sjsg 	INIT_LIST_HEAD(&tmp->xcc_list);
969f005ef32Sjsg 	INIT_LIST_HEAD(&tmp->list);
970f005ef32Sjsg 	tmp->bdf = bdf;
971f005ef32Sjsg 
972f005ef32Sjsg 	STUB();
973f005ef32Sjsg 	return -ENOSYS;
974f005ef32Sjsg #ifdef notyet
975f005ef32Sjsg 
976f005ef32Sjsg 	obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
977f005ef32Sjsg 				      AMD_XCC_DSM_GET_SUPP_MODE, NULL,
978f005ef32Sjsg 				      ACPI_TYPE_INTEGER);
979f005ef32Sjsg 
980f005ef32Sjsg 	if (!obj) {
981f005ef32Sjsg 		acpi_handle_debug(xcc_info->handle,
982f005ef32Sjsg 				  "_DSM function %d evaluation failed",
983f005ef32Sjsg 				  AMD_XCC_DSM_GET_SUPP_MODE);
984f005ef32Sjsg 		ret = -ENOENT;
985f005ef32Sjsg 		goto out;
986f005ef32Sjsg 	}
987f005ef32Sjsg 
988f005ef32Sjsg 	tmp->supp_xcp_mode = obj->integer.value & 0xFFFF;
989f005ef32Sjsg 	ACPI_FREE(obj);
990f005ef32Sjsg 
991f005ef32Sjsg 	obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
992f005ef32Sjsg 				      AMD_XCC_DSM_GET_XCP_MODE, NULL,
993f005ef32Sjsg 				      ACPI_TYPE_INTEGER);
994f005ef32Sjsg 
995f005ef32Sjsg 	if (!obj) {
996f005ef32Sjsg 		acpi_handle_debug(xcc_info->handle,
997f005ef32Sjsg 				  "_DSM function %d evaluation failed",
998f005ef32Sjsg 				  AMD_XCC_DSM_GET_XCP_MODE);
999f005ef32Sjsg 		ret = -ENOENT;
1000f005ef32Sjsg 		goto out;
1001f005ef32Sjsg 	}
1002f005ef32Sjsg 
1003f005ef32Sjsg 	tmp->xcp_mode = obj->integer.value & 0xFFFF;
1004f005ef32Sjsg 	tmp->mem_mode = (obj->integer.value >> 32) & 0xFFFF;
1005f005ef32Sjsg 	ACPI_FREE(obj);
1006f005ef32Sjsg 
1007f005ef32Sjsg 	/* Evaluate DSMs and fill XCC information */
1008f005ef32Sjsg 	obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
1009f005ef32Sjsg 				      AMD_XCC_DSM_GET_TMR_INFO, NULL,
1010f005ef32Sjsg 				      ACPI_TYPE_PACKAGE);
1011f005ef32Sjsg 
1012f005ef32Sjsg 	if (!obj || obj->package.count < 2) {
1013f005ef32Sjsg 		acpi_handle_debug(xcc_info->handle,
1014f005ef32Sjsg 				  "_DSM function %d evaluation failed",
1015f005ef32Sjsg 				  AMD_XCC_DSM_GET_TMR_INFO);
1016f005ef32Sjsg 		ret = -ENOENT;
1017f005ef32Sjsg 		goto out;
1018f005ef32Sjsg 	}
1019f005ef32Sjsg 
1020f005ef32Sjsg 	tmp->tmr_base = obj->package.elements[0].integer.value;
1021f005ef32Sjsg 	tmp->tmr_size = obj->package.elements[1].integer.value;
1022f005ef32Sjsg 	ACPI_FREE(obj);
1023f005ef32Sjsg 
1024f005ef32Sjsg 	DRM_DEBUG_DRIVER(
1025f005ef32Sjsg 		"New dev(%x): Supported xcp mode: %x curr xcp_mode : %x mem mode : %x, tmr base: %llx tmr size: %llx  ",
1026f005ef32Sjsg 		tmp->bdf, tmp->supp_xcp_mode, tmp->xcp_mode, tmp->mem_mode,
1027f005ef32Sjsg 		tmp->tmr_base, tmp->tmr_size);
1028f005ef32Sjsg 	list_add_tail(&tmp->list, &amdgpu_acpi_dev_list);
1029f005ef32Sjsg 	*dev_info = tmp;
1030f005ef32Sjsg 
1031f005ef32Sjsg 	return 0;
1032f005ef32Sjsg 
1033f005ef32Sjsg out:
1034f005ef32Sjsg 	if (obj)
1035f005ef32Sjsg 		ACPI_FREE(obj);
1036f005ef32Sjsg 	kfree(tmp);
1037f005ef32Sjsg 
1038f005ef32Sjsg 	return ret;
1039f005ef32Sjsg #endif
1040f005ef32Sjsg }
1041f005ef32Sjsg 
1042f005ef32Sjsg static int amdgpu_acpi_get_xcc_info(struct amdgpu_acpi_xcc_info *xcc_info,
1043f005ef32Sjsg 				    u16 *bdf)
1044f005ef32Sjsg {
1045f005ef32Sjsg 	STUB();
1046f005ef32Sjsg 	return -ENOSYS;
1047f005ef32Sjsg #ifdef notyet
1048f005ef32Sjsg 	union acpi_object *obj;
1049f005ef32Sjsg 	acpi_status status;
1050f005ef32Sjsg 	int ret = -ENOENT;
1051f005ef32Sjsg 
1052f005ef32Sjsg 	obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
1053f005ef32Sjsg 				      AMD_XCC_DSM_GET_NUM_FUNCS, NULL,
1054f005ef32Sjsg 				      ACPI_TYPE_INTEGER);
1055f005ef32Sjsg 
1056f005ef32Sjsg 	if (!obj || obj->integer.value != AMD_XCC_DSM_NUM_FUNCS)
1057f005ef32Sjsg 		goto out;
1058f005ef32Sjsg 	ACPI_FREE(obj);
1059f005ef32Sjsg 
1060f005ef32Sjsg 	/* Evaluate DSMs and fill XCC information */
1061f005ef32Sjsg 	obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
1062f005ef32Sjsg 				      AMD_XCC_DSM_GET_VF_XCC_MAPPING, NULL,
1063f005ef32Sjsg 				      ACPI_TYPE_INTEGER);
1064f005ef32Sjsg 
1065f005ef32Sjsg 	if (!obj) {
1066f005ef32Sjsg 		acpi_handle_debug(xcc_info->handle,
1067f005ef32Sjsg 				  "_DSM function %d evaluation failed",
1068f005ef32Sjsg 				  AMD_XCC_DSM_GET_VF_XCC_MAPPING);
1069f005ef32Sjsg 		ret = -EINVAL;
1070f005ef32Sjsg 		goto out;
1071f005ef32Sjsg 	}
1072f005ef32Sjsg 
1073f005ef32Sjsg 	/* PF xcc id [39:32] */
1074f005ef32Sjsg 	xcc_info->phy_id = (obj->integer.value >> 32) & 0xFF;
1075f005ef32Sjsg 	/* xcp node of this xcc [47:40] */
1076f005ef32Sjsg 	xcc_info->xcp_node = (obj->integer.value >> 40) & 0xFF;
1077f005ef32Sjsg 	/* PF bus/dev/fn of this xcc [63:48] */
1078f005ef32Sjsg 	*bdf = (obj->integer.value >> 48) & 0xFFFF;
1079f005ef32Sjsg 	ACPI_FREE(obj);
1080f005ef32Sjsg 	obj = NULL;
1081f005ef32Sjsg 
1082f005ef32Sjsg 	status =
1083f005ef32Sjsg 		amdgpu_acpi_get_node_id(xcc_info->handle, &xcc_info->numa_info);
1084f005ef32Sjsg 
1085f005ef32Sjsg 	/* TODO: check if this check is required */
1086f005ef32Sjsg 	if (ACPI_SUCCESS(status))
1087f005ef32Sjsg 		ret = 0;
1088f005ef32Sjsg out:
1089f005ef32Sjsg 	if (obj)
1090f005ef32Sjsg 		ACPI_FREE(obj);
1091f005ef32Sjsg 
1092f005ef32Sjsg 	return ret;
1093f005ef32Sjsg #endif
1094f005ef32Sjsg }
1095f005ef32Sjsg 
1096f005ef32Sjsg static int amdgpu_acpi_enumerate_xcc(void)
1097f005ef32Sjsg {
1098f005ef32Sjsg 	struct amdgpu_acpi_dev_info *dev_info = NULL;
1099f005ef32Sjsg 	struct amdgpu_acpi_xcc_info *xcc_info;
1100f005ef32Sjsg 	struct acpi_device *acpi_dev;
1101f005ef32Sjsg 	char hid[ACPI_ID_LEN];
1102f005ef32Sjsg 	int ret, id;
1103f005ef32Sjsg 	u16 bdf;
1104f005ef32Sjsg 
1105f005ef32Sjsg 	INIT_LIST_HEAD(&amdgpu_acpi_dev_list);
1106f005ef32Sjsg 	xa_init(&numa_info_xa);
1107f005ef32Sjsg 
1108a8551f48Sjsg #ifdef notyet
1109f005ef32Sjsg 	for (id = 0; id < AMD_XCC_MAX_HID; id++) {
1110f005ef32Sjsg 		snprintf(hid, sizeof(hid), "%s%d", "AMD", AMD_XCC_HID_START + id);
1111f005ef32Sjsg 		acpi_dev = acpi_dev_get_first_match_dev(hid, NULL, -1);
1112f005ef32Sjsg 		/* These ACPI objects are expected to be in sequential order. If
1113f005ef32Sjsg 		 * one is not found, no need to check the rest.
1114f005ef32Sjsg 		 */
1115f005ef32Sjsg 		if (!acpi_dev) {
1116f005ef32Sjsg 			DRM_DEBUG_DRIVER("No matching acpi device found for %s",
1117f005ef32Sjsg 					 hid);
1118f005ef32Sjsg 			break;
1119f005ef32Sjsg 		}
1120f005ef32Sjsg 
1121f005ef32Sjsg 		xcc_info = kzalloc(sizeof(struct amdgpu_acpi_xcc_info),
1122f005ef32Sjsg 				   GFP_KERNEL);
1123f005ef32Sjsg 		if (!xcc_info) {
1124f005ef32Sjsg 			DRM_ERROR("Failed to allocate memory for xcc info\n");
1125f005ef32Sjsg 			return -ENOMEM;
1126f005ef32Sjsg 		}
1127f005ef32Sjsg 
1128f005ef32Sjsg 		INIT_LIST_HEAD(&xcc_info->list);
1129f005ef32Sjsg 		xcc_info->handle = acpi_device_handle(acpi_dev);
1130f005ef32Sjsg 		acpi_dev_put(acpi_dev);
1131f005ef32Sjsg 
1132f005ef32Sjsg 		ret = amdgpu_acpi_get_xcc_info(xcc_info, &bdf);
1133f005ef32Sjsg 		if (ret) {
1134f005ef32Sjsg 			kfree(xcc_info);
1135f005ef32Sjsg 			continue;
1136f005ef32Sjsg 		}
1137f005ef32Sjsg 
1138f005ef32Sjsg 		dev_info = amdgpu_acpi_get_dev(bdf);
1139f005ef32Sjsg 
1140f005ef32Sjsg 		if (!dev_info)
1141f005ef32Sjsg 			ret = amdgpu_acpi_dev_init(&dev_info, xcc_info, bdf);
1142f005ef32Sjsg 
1143f005ef32Sjsg 		if (ret == -ENOMEM)
1144f005ef32Sjsg 			return ret;
1145f005ef32Sjsg 
1146f005ef32Sjsg 		if (!dev_info) {
1147f005ef32Sjsg 			kfree(xcc_info);
1148f005ef32Sjsg 			continue;
1149f005ef32Sjsg 		}
1150f005ef32Sjsg 
1151f005ef32Sjsg 		list_add_tail(&xcc_info->list, &dev_info->xcc_list);
1152f005ef32Sjsg 	}
1153a8551f48Sjsg #endif
1154f005ef32Sjsg 
1155f005ef32Sjsg 	return 0;
1156f005ef32Sjsg }
1157f005ef32Sjsg 
1158f005ef32Sjsg int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, u64 *tmr_offset,
1159f005ef32Sjsg 			     u64 *tmr_size)
1160f005ef32Sjsg {
1161f005ef32Sjsg 	struct amdgpu_acpi_dev_info *dev_info;
1162f005ef32Sjsg 	u16 bdf;
1163f005ef32Sjsg 
1164f005ef32Sjsg 	if (!tmr_offset || !tmr_size)
1165f005ef32Sjsg 		return -EINVAL;
1166f005ef32Sjsg 
1167f005ef32Sjsg 	bdf = pci_dev_id(adev->pdev);
1168f005ef32Sjsg 	dev_info = amdgpu_acpi_get_dev(bdf);
1169f005ef32Sjsg 	if (!dev_info)
1170f005ef32Sjsg 		return -ENOENT;
1171f005ef32Sjsg 
1172f005ef32Sjsg 	*tmr_offset = dev_info->tmr_base;
1173f005ef32Sjsg 	*tmr_size = dev_info->tmr_size;
1174f005ef32Sjsg 
1175f005ef32Sjsg 	return 0;
1176f005ef32Sjsg }
1177f005ef32Sjsg 
1178f005ef32Sjsg int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, int xcc_id,
1179f005ef32Sjsg 			     struct amdgpu_numa_info *numa_info)
1180f005ef32Sjsg {
1181f005ef32Sjsg 	struct amdgpu_acpi_dev_info *dev_info;
1182f005ef32Sjsg 	struct amdgpu_acpi_xcc_info *xcc_info;
1183f005ef32Sjsg 	u16 bdf;
1184f005ef32Sjsg 
1185f005ef32Sjsg 	if (!numa_info)
1186f005ef32Sjsg 		return -EINVAL;
1187f005ef32Sjsg 
1188f005ef32Sjsg 	bdf = pci_dev_id(adev->pdev);
1189f005ef32Sjsg 	dev_info = amdgpu_acpi_get_dev(bdf);
1190f005ef32Sjsg 	if (!dev_info)
1191f005ef32Sjsg 		return -ENOENT;
1192f005ef32Sjsg 
1193f005ef32Sjsg 	list_for_each_entry(xcc_info, &dev_info->xcc_list, list) {
1194f005ef32Sjsg 		if (xcc_info->phy_id == xcc_id) {
1195f005ef32Sjsg 			memcpy(numa_info, xcc_info->numa_info,
1196f005ef32Sjsg 			       sizeof(*numa_info));
1197f005ef32Sjsg 			return 0;
1198f005ef32Sjsg 		}
1199f005ef32Sjsg 	}
1200f005ef32Sjsg 
1201f005ef32Sjsg 	return -ENOENT;
1202f005ef32Sjsg }
1203f005ef32Sjsg 
12045ca02815Sjsg /**
1205fb4d8502Sjsg  * amdgpu_acpi_event - handle notify events
1206fb4d8502Sjsg  *
1207fb4d8502Sjsg  * @nb: notifier block
1208fb4d8502Sjsg  * @val: val
1209fb4d8502Sjsg  * @data: acpi event
1210fb4d8502Sjsg  *
1211fb4d8502Sjsg  * Calls relevant amdgpu functions in response to various
1212fb4d8502Sjsg  * acpi events.
1213fb4d8502Sjsg  * Returns NOTIFY code
1214fb4d8502Sjsg  */
1215fb4d8502Sjsg static int amdgpu_acpi_event(struct notifier_block *nb,
1216fb4d8502Sjsg 			     unsigned long val,
1217fb4d8502Sjsg 			     void *data)
1218fb4d8502Sjsg {
1219fb4d8502Sjsg 	struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, acpi_nb);
1220fb4d8502Sjsg 	struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
1221fb4d8502Sjsg 
1222fb4d8502Sjsg 	if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
1223fb4d8502Sjsg 		if (power_supply_is_system_supplied() > 0)
1224fb4d8502Sjsg 			DRM_DEBUG_DRIVER("pm: AC\n");
1225fb4d8502Sjsg 		else
1226fb4d8502Sjsg 			DRM_DEBUG_DRIVER("pm: DC\n");
1227fb4d8502Sjsg 
1228fb4d8502Sjsg 		amdgpu_pm_acpi_event_handler(adev);
1229fb4d8502Sjsg 	}
1230fb4d8502Sjsg 
1231fb4d8502Sjsg 	/* Check for pending SBIOS requests */
1232fb4d8502Sjsg 	return amdgpu_atif_handler(adev, entry);
1233fb4d8502Sjsg }
1234fb4d8502Sjsg 
1235fb4d8502Sjsg /* Call all ACPI methods here */
1236fb4d8502Sjsg /**
1237fb4d8502Sjsg  * amdgpu_acpi_init - init driver acpi support
1238fb4d8502Sjsg  *
1239fb4d8502Sjsg  * @adev: amdgpu_device pointer
1240fb4d8502Sjsg  *
1241fb4d8502Sjsg  * Verifies the AMD ACPI interfaces and registers with the acpi
1242fb4d8502Sjsg  * notifier chain (all asics).
1243fb4d8502Sjsg  * Returns 0 on success, error on failure.
1244fb4d8502Sjsg  */
1245fb4d8502Sjsg int amdgpu_acpi_init(struct amdgpu_device *adev)
1246fb4d8502Sjsg {
12475ca02815Sjsg 	struct amdgpu_atif *atif = &amdgpu_acpi_priv.atif;
1248fb4d8502Sjsg 
1249fb4d8502Sjsg 	if (atif->notifications.brightness_change) {
1250f005ef32Sjsg 		if (adev->dc_enabled) {
1251ad8b1aafSjsg #if defined(CONFIG_DRM_AMD_DC)
1252ad8b1aafSjsg 			struct amdgpu_display_manager *dm = &adev->dm;
12531bb76ff1Sjsg 
12545ca02815Sjsg 			if (dm->backlight_dev[0])
12555ca02815Sjsg 				atif->bd = dm->backlight_dev[0];
1256ad8b1aafSjsg #endif
1257ad8b1aafSjsg 		} else {
1258fb4d8502Sjsg 			struct drm_encoder *tmp;
1259fb4d8502Sjsg 
1260fb4d8502Sjsg 			/* Find the encoder controlling the brightness */
1261ad8b1aafSjsg 			list_for_each_entry(tmp, &adev_to_drm(adev)->mode_config.encoder_list,
1262fb4d8502Sjsg 					    head) {
1263fb4d8502Sjsg 				struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp);
1264fb4d8502Sjsg 
1265fb4d8502Sjsg 				if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
1266fb4d8502Sjsg 				    enc->enc_priv) {
1267fb4d8502Sjsg 					struct amdgpu_encoder_atom_dig *dig = enc->enc_priv;
12681bb76ff1Sjsg 
1269fb4d8502Sjsg 					if (dig->bl_dev) {
1270ad8b1aafSjsg 						atif->bd = dig->bl_dev;
1271fb4d8502Sjsg 						break;
1272fb4d8502Sjsg 					}
1273fb4d8502Sjsg 				}
1274fb4d8502Sjsg 			}
1275fb4d8502Sjsg 		}
1276ad8b1aafSjsg 	}
12775ca02815Sjsg 	adev->acpi_nb.notifier_call = amdgpu_acpi_event;
12785ca02815Sjsg 	register_acpi_notifier(&adev->acpi_nb);
12795ca02815Sjsg 
12805ca02815Sjsg 	return 0;
12815ca02815Sjsg }
12825ca02815Sjsg 
12835ca02815Sjsg void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps)
12845ca02815Sjsg {
12855ca02815Sjsg 	struct amdgpu_atif *atif = &amdgpu_acpi_priv.atif;
12865ca02815Sjsg 
12875ca02815Sjsg 	caps->caps_valid = atif->backlight_caps.caps_valid;
12885ca02815Sjsg 	caps->min_input_signal = atif->backlight_caps.min_input_signal;
12895ca02815Sjsg 	caps->max_input_signal = atif->backlight_caps.max_input_signal;
12905ca02815Sjsg }
12915ca02815Sjsg 
12925ca02815Sjsg /**
12935ca02815Sjsg  * amdgpu_acpi_fini - tear down driver acpi support
12945ca02815Sjsg  *
12955ca02815Sjsg  * @adev: amdgpu_device pointer
12965ca02815Sjsg  *
12975ca02815Sjsg  * Unregisters with the acpi notifier chain (all asics).
12985ca02815Sjsg  */
12995ca02815Sjsg void amdgpu_acpi_fini(struct amdgpu_device *adev)
13005ca02815Sjsg {
13015ca02815Sjsg 	unregister_acpi_notifier(&adev->acpi_nb);
13025ca02815Sjsg }
13035ca02815Sjsg 
13045ca02815Sjsg /**
13055ca02815Sjsg  * amdgpu_atif_pci_probe_handle - look up the ATIF handle
13065ca02815Sjsg  *
13075ca02815Sjsg  * @pdev: pci device
13085ca02815Sjsg  *
13095ca02815Sjsg  * Look up the ATIF handles (all asics).
13105ca02815Sjsg  * Returns true if the handle is found, false if not.
13115ca02815Sjsg  */
13125ca02815Sjsg static bool amdgpu_atif_pci_probe_handle(struct pci_dev *pdev)
13135ca02815Sjsg {
13145ca02815Sjsg 	char acpi_method_name[255] = { 0 };
13155ca02815Sjsg 	struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
13165ca02815Sjsg 	acpi_handle dhandle, atif_handle;
13175ca02815Sjsg 	acpi_status status;
13185ca02815Sjsg 	int ret;
13195ca02815Sjsg 
13205ca02815Sjsg 	dhandle = ACPI_HANDLE(&pdev->dev);
13215ca02815Sjsg 	if (!dhandle)
13225ca02815Sjsg 		return false;
13235ca02815Sjsg 
13245ca02815Sjsg 	status = acpi_get_handle(dhandle, "ATIF", &atif_handle);
13251bb76ff1Sjsg 	if (ACPI_FAILURE(status))
13265ca02815Sjsg 		return false;
13271bb76ff1Sjsg 
13285ca02815Sjsg 	amdgpu_acpi_priv.atif.handle = atif_handle;
13295ca02815Sjsg 	acpi_get_name(amdgpu_acpi_priv.atif.handle, ACPI_FULL_PATHNAME, &buffer);
13305ca02815Sjsg 	DRM_DEBUG_DRIVER("Found ATIF handle %s\n", acpi_method_name);
13315ca02815Sjsg 	ret = amdgpu_atif_verify_interface(&amdgpu_acpi_priv.atif);
13325ca02815Sjsg 	if (ret) {
13335ca02815Sjsg 		amdgpu_acpi_priv.atif.handle = 0;
13345ca02815Sjsg 		return false;
13355ca02815Sjsg 	}
13365ca02815Sjsg 	return true;
13375ca02815Sjsg }
13385ca02815Sjsg 
13395ca02815Sjsg /**
13405ca02815Sjsg  * amdgpu_atcs_pci_probe_handle - look up the ATCS handle
13415ca02815Sjsg  *
13425ca02815Sjsg  * @pdev: pci device
13435ca02815Sjsg  *
13445ca02815Sjsg  * Look up the ATCS handles (all asics).
13455ca02815Sjsg  * Returns true if the handle is found, false if not.
13465ca02815Sjsg  */
13475ca02815Sjsg static bool amdgpu_atcs_pci_probe_handle(struct pci_dev *pdev)
13485ca02815Sjsg {
13495ca02815Sjsg 	char acpi_method_name[255] = { 0 };
13505ca02815Sjsg 	struct acpi_buffer buffer = { sizeof(acpi_method_name), acpi_method_name };
13515ca02815Sjsg 	acpi_handle dhandle, atcs_handle;
13525ca02815Sjsg 	acpi_status status;
13535ca02815Sjsg 	int ret;
13545ca02815Sjsg 
13555ca02815Sjsg 	dhandle = ACPI_HANDLE(&pdev->dev);
13565ca02815Sjsg 	if (!dhandle)
13575ca02815Sjsg 		return false;
13585ca02815Sjsg 
13595ca02815Sjsg 	status = acpi_get_handle(dhandle, "ATCS", &atcs_handle);
13601bb76ff1Sjsg 	if (ACPI_FAILURE(status))
13615ca02815Sjsg 		return false;
13621bb76ff1Sjsg 
13635ca02815Sjsg 	amdgpu_acpi_priv.atcs.handle = atcs_handle;
13645ca02815Sjsg 	acpi_get_name(amdgpu_acpi_priv.atcs.handle, ACPI_FULL_PATHNAME, &buffer);
13655ca02815Sjsg 	DRM_DEBUG_DRIVER("Found ATCS handle %s\n", acpi_method_name);
13665ca02815Sjsg 	ret = amdgpu_atcs_verify_interface(&amdgpu_acpi_priv.atcs);
13675ca02815Sjsg 	if (ret) {
13685ca02815Sjsg 		amdgpu_acpi_priv.atcs.handle = 0;
13695ca02815Sjsg 		return false;
13705ca02815Sjsg 	}
13715ca02815Sjsg 	return true;
13725ca02815Sjsg }
13735ca02815Sjsg 
13745ca02815Sjsg extern struct cfdriver amdgpu_cd;
13755ca02815Sjsg 
13766f802cabSjsg 
13776f802cabSjsg /**
13786f802cabSjsg  * amdgpu_acpi_should_gpu_reset
13796f802cabSjsg  *
13806f802cabSjsg  * @adev: amdgpu_device_pointer
13816f802cabSjsg  *
13826f802cabSjsg  * returns true if should reset GPU, false if not
13836f802cabSjsg  */
13846f802cabSjsg bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev)
13856f802cabSjsg {
138690faafb5Sjsg 	if ((adev->flags & AMD_IS_APU) &&
138790faafb5Sjsg 	    adev->gfx.imu.funcs) /* Not need to do mode2 reset for IMU enabled APUs */
138890faafb5Sjsg 		return false;
138990faafb5Sjsg 
139090faafb5Sjsg 	if ((adev->flags & AMD_IS_APU) &&
139190faafb5Sjsg 	    amdgpu_acpi_is_s3_active(adev))
13926f802cabSjsg 		return false;
13936f802cabSjsg 
13946f802cabSjsg 	if (amdgpu_sriov_vf(adev))
13956f802cabSjsg 		return false;
13966f802cabSjsg 
13971dc2c084Sjsg #ifdef __OpenBSD__
13981dc2c084Sjsg 	/* XXX VEGA10 S3 fails if reset is done */
13991dc2c084Sjsg 	if (pm_suspend_target_state == PM_SUSPEND_MEM)
14001dc2c084Sjsg 		return false;
14011dc2c084Sjsg #endif
14021dc2c084Sjsg 
14036f802cabSjsg #if IS_ENABLED(CONFIG_SUSPEND)
14046f802cabSjsg 	return pm_suspend_target_state != PM_SUSPEND_TO_IDLE;
14056f802cabSjsg #else
14066f802cabSjsg 	return true;
14076f802cabSjsg #endif
14086f802cabSjsg }
14096f802cabSjsg 
14105ca02815Sjsg /*
14115ca02815Sjsg  * amdgpu_acpi_detect - detect ACPI ATIF/ATCS methods
14125ca02815Sjsg  *
14135ca02815Sjsg  * Check if we have the ATIF/ATCS methods and populate
14145ca02815Sjsg  * the structures in the driver.
14155ca02815Sjsg  */
14165ca02815Sjsg void amdgpu_acpi_detect(void)
14175ca02815Sjsg {
14185ca02815Sjsg 	struct amdgpu_atif *atif = &amdgpu_acpi_priv.atif;
14195ca02815Sjsg 	struct amdgpu_atcs *atcs = &amdgpu_acpi_priv.atcs;
14205ca02815Sjsg 	struct pci_dev *pdev = NULL;
14215ca02815Sjsg 	int ret;
14225ca02815Sjsg 
14235ca02815Sjsg #ifdef notyet
14245ca02815Sjsg 	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
14255ca02815Sjsg 		if (!atif->handle)
14265ca02815Sjsg 			amdgpu_atif_pci_probe_handle(pdev);
14275ca02815Sjsg 		if (!atcs->handle)
14285ca02815Sjsg 			amdgpu_atcs_pci_probe_handle(pdev);
14295ca02815Sjsg 	}
14305ca02815Sjsg 
14315ca02815Sjsg 	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
14325ca02815Sjsg 		if (!atif->handle)
14335ca02815Sjsg 			amdgpu_atif_pci_probe_handle(pdev);
14345ca02815Sjsg 		if (!atcs->handle)
14355ca02815Sjsg 			amdgpu_atcs_pci_probe_handle(pdev);
14365ca02815Sjsg 	}
14375ca02815Sjsg #else
14385ca02815Sjsg 	{
14395ca02815Sjsg 		struct amdgpu_device *adev = (void *)amdgpu_cd.cd_devs[0];
14405ca02815Sjsg 		pdev = adev->pdev;
14415ca02815Sjsg 		if (!atif->handle)
14425ca02815Sjsg 			amdgpu_atif_pci_probe_handle(pdev);
14435ca02815Sjsg 		if (!atcs->handle)
14445ca02815Sjsg 			amdgpu_atcs_pci_probe_handle(pdev);
14455ca02815Sjsg 	}
14465ca02815Sjsg #endif
1447fb4d8502Sjsg 
1448fb4d8502Sjsg 	if (atif->functions.sbios_requests && !atif->functions.system_params) {
1449fb4d8502Sjsg 		/* XXX check this workraround, if sbios request function is
1450fb4d8502Sjsg 		 * present we have to see how it's configured in the system
1451fb4d8502Sjsg 		 * params
1452fb4d8502Sjsg 		 */
1453fb4d8502Sjsg 		atif->functions.system_params = true;
1454fb4d8502Sjsg 	}
1455fb4d8502Sjsg 
1456fb4d8502Sjsg 	if (atif->functions.system_params) {
1457fb4d8502Sjsg 		ret = amdgpu_atif_get_notification_params(atif);
1458fb4d8502Sjsg 		if (ret) {
1459fb4d8502Sjsg 			DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n",
1460fb4d8502Sjsg 					ret);
1461fb4d8502Sjsg 			/* Disable notification */
1462fb4d8502Sjsg 			atif->notification_cfg.enabled = false;
1463fb4d8502Sjsg 		}
1464fb4d8502Sjsg 	}
1465fb4d8502Sjsg 
1466c349dbc7Sjsg 	if (atif->functions.query_backlight_transfer_characteristics) {
1467c349dbc7Sjsg 		ret = amdgpu_atif_query_backlight_caps(atif);
1468c349dbc7Sjsg 		if (ret) {
1469c349dbc7Sjsg 			DRM_DEBUG_DRIVER("Call to QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS failed: %d\n",
1470c349dbc7Sjsg 					ret);
1471c349dbc7Sjsg 			atif->backlight_caps.caps_valid = false;
1472c349dbc7Sjsg 		}
1473c349dbc7Sjsg 	} else {
1474c349dbc7Sjsg 		atif->backlight_caps.caps_valid = false;
1475c349dbc7Sjsg 	}
1476f005ef32Sjsg 
1477f005ef32Sjsg 	amdgpu_acpi_enumerate_xcc();
1478f005ef32Sjsg }
1479f005ef32Sjsg 
1480f005ef32Sjsg void amdgpu_acpi_release(void)
1481f005ef32Sjsg {
1482f005ef32Sjsg 	struct amdgpu_acpi_dev_info *dev_info, *dev_tmp;
1483f005ef32Sjsg 	struct amdgpu_acpi_xcc_info *xcc_info, *xcc_tmp;
1484f005ef32Sjsg 	struct amdgpu_numa_info *numa_info;
1485f005ef32Sjsg 	unsigned long index;
1486f005ef32Sjsg 
1487f005ef32Sjsg 	xa_for_each(&numa_info_xa, index, numa_info) {
1488f005ef32Sjsg 		kfree(numa_info);
1489f005ef32Sjsg 		xa_erase(&numa_info_xa, index);
1490f005ef32Sjsg 	}
1491f005ef32Sjsg 
1492f005ef32Sjsg 	if (list_empty(&amdgpu_acpi_dev_list))
1493f005ef32Sjsg 		return;
1494f005ef32Sjsg 
1495f005ef32Sjsg 	list_for_each_entry_safe(dev_info, dev_tmp, &amdgpu_acpi_dev_list,
1496f005ef32Sjsg 				 list) {
1497f005ef32Sjsg 		list_for_each_entry_safe(xcc_info, xcc_tmp, &dev_info->xcc_list,
1498f005ef32Sjsg 					 list) {
1499f005ef32Sjsg 			list_del(&xcc_info->list);
1500f005ef32Sjsg 			kfree(xcc_info);
1501f005ef32Sjsg 		}
1502f005ef32Sjsg 
1503f005ef32Sjsg 		list_del(&dev_info->list);
1504f005ef32Sjsg 		kfree(dev_info);
1505f005ef32Sjsg 	}
1506c349dbc7Sjsg }
1507c349dbc7Sjsg 
150848739ed2Sjsg #if IS_ENABLED(CONFIG_SUSPEND)
1509fb4d8502Sjsg /**
151068c9ef6eSjsg  * amdgpu_acpi_is_s3_active
151168c9ef6eSjsg  *
151268c9ef6eSjsg  * @adev: amdgpu_device_pointer
151368c9ef6eSjsg  *
151468c9ef6eSjsg  * returns true if supported, false if not.
151568c9ef6eSjsg  */
151668c9ef6eSjsg bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev)
151768c9ef6eSjsg {
151868c9ef6eSjsg 	return !(adev->flags & AMD_IS_APU) ||
151968c9ef6eSjsg 		(pm_suspend_target_state == PM_SUSPEND_MEM);
152068c9ef6eSjsg }
152168c9ef6eSjsg 
152268c9ef6eSjsg /**
15235ca02815Sjsg  * amdgpu_acpi_is_s0ix_active
1524fb4d8502Sjsg  *
15255ca02815Sjsg  * @adev: amdgpu_device_pointer
1526fb4d8502Sjsg  *
15275ca02815Sjsg  * returns true if supported, false if not.
1528fb4d8502Sjsg  */
15295ca02815Sjsg bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
1530fb4d8502Sjsg {
153148739ed2Sjsg 	if (!(adev->flags & AMD_IS_APU) ||
153248739ed2Sjsg 	    (pm_suspend_target_state != PM_SUSPEND_TO_IDLE))
153348739ed2Sjsg 		return false;
153448739ed2Sjsg 
1535d87ad1f5Sjsg 	if (adev->asic_type < CHIP_RAVEN)
1536d87ad1f5Sjsg 		return false;
1537d87ad1f5Sjsg 
15387dd51cb7Skettenis #ifdef __linux__
15391bb76ff1Sjsg 	/*
15401bb76ff1Sjsg 	 * If ACPI_FADT_LOW_POWER_S0 is not set in the FADT, it is generally
15411bb76ff1Sjsg 	 * risky to do any special firmware-related preparations for entering
15421bb76ff1Sjsg 	 * S0ix even though the system is suspending to idle, so return false
15431bb76ff1Sjsg 	 * in that case.
15441bb76ff1Sjsg 	 */
154548739ed2Sjsg 	if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) {
1546f005ef32Sjsg 		dev_err_once(adev->dev,
154748739ed2Sjsg 			      "Power consumption will be higher as BIOS has not been configured for suspend-to-idle.\n"
154848739ed2Sjsg 			      "To use suspend-to-idle change the sleep mode in BIOS setup.\n");
15495ca02815Sjsg 		return false;
1550fb4d8502Sjsg 	}
15517dd51cb7Skettenis #endif
155248739ed2Sjsg 
155348739ed2Sjsg #if !IS_ENABLED(CONFIG_AMD_PMC)
1554f005ef32Sjsg 	dev_err_once(adev->dev,
155548739ed2Sjsg 		      "Power consumption will be higher as the kernel has not been compiled with CONFIG_AMD_PMC.\n");
155648739ed2Sjsg 	return false;
155748739ed2Sjsg #else
155848739ed2Sjsg 	return true;
155948739ed2Sjsg #endif /* CONFIG_AMD_PMC */
156048739ed2Sjsg }
156148739ed2Sjsg 
15628571a5a7Skettenis /**
15638571a5a7Skettenis  * amdgpu_choose_low_power_state
15648571a5a7Skettenis  *
15658571a5a7Skettenis  * @adev: amdgpu_device_pointer
15668571a5a7Skettenis  *
15678571a5a7Skettenis  * Choose the target low power state for the GPU
15688571a5a7Skettenis  */
15698571a5a7Skettenis void amdgpu_choose_low_power_state(struct amdgpu_device *adev)
15708571a5a7Skettenis {
15718571a5a7Skettenis 	if (amdgpu_acpi_is_s0ix_active(adev))
15728571a5a7Skettenis 		adev->in_s0ix = true;
15738571a5a7Skettenis 	else if (amdgpu_acpi_is_s3_active(adev))
15748571a5a7Skettenis 		adev->in_s3 = true;
15758571a5a7Skettenis }
15768571a5a7Skettenis 
157748739ed2Sjsg #endif /* CONFIG_SUSPEND */
1578