xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2012 Advanced Micro Devices, Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun  * all copies or substantial portions of the Software.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17*4882a593Smuzhiyun  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*4882a593Smuzhiyun  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*4882a593Smuzhiyun  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*4882a593Smuzhiyun  * OTHER DEALINGS IN THE SOFTWARE.
21*4882a593Smuzhiyun  *
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include <linux/pci.h>
25*4882a593Smuzhiyun #include <linux/acpi.h>
26*4882a593Smuzhiyun #include <linux/slab.h>
27*4882a593Smuzhiyun #include <linux/power_supply.h>
28*4882a593Smuzhiyun #include <linux/pm_runtime.h>
29*4882a593Smuzhiyun #include <acpi/video.h>
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include <drm/drm_crtc_helper.h>
32*4882a593Smuzhiyun #include "amdgpu.h"
33*4882a593Smuzhiyun #include "amdgpu_pm.h"
34*4882a593Smuzhiyun #include "amdgpu_display.h"
35*4882a593Smuzhiyun #include "amd_acpi.h"
36*4882a593Smuzhiyun #include "atom.h"
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun struct amdgpu_atif_notification_cfg {
39*4882a593Smuzhiyun 	bool enabled;
40*4882a593Smuzhiyun 	int command_code;
41*4882a593Smuzhiyun };
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun struct amdgpu_atif_notifications {
44*4882a593Smuzhiyun 	bool thermal_state;
45*4882a593Smuzhiyun 	bool forced_power_state;
46*4882a593Smuzhiyun 	bool system_power_state;
47*4882a593Smuzhiyun 	bool brightness_change;
48*4882a593Smuzhiyun 	bool dgpu_display_event;
49*4882a593Smuzhiyun 	bool gpu_package_power_limit;
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun struct amdgpu_atif_functions {
53*4882a593Smuzhiyun 	bool system_params;
54*4882a593Smuzhiyun 	bool sbios_requests;
55*4882a593Smuzhiyun 	bool temperature_change;
56*4882a593Smuzhiyun 	bool query_backlight_transfer_characteristics;
57*4882a593Smuzhiyun 	bool ready_to_undock;
58*4882a593Smuzhiyun 	bool external_gpu_information;
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun struct amdgpu_atif {
62*4882a593Smuzhiyun 	acpi_handle handle;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	struct amdgpu_atif_notifications notifications;
65*4882a593Smuzhiyun 	struct amdgpu_atif_functions functions;
66*4882a593Smuzhiyun 	struct amdgpu_atif_notification_cfg notification_cfg;
67*4882a593Smuzhiyun #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
68*4882a593Smuzhiyun 	struct backlight_device *bd;
69*4882a593Smuzhiyun #endif
70*4882a593Smuzhiyun 	struct amdgpu_dm_backlight_caps backlight_caps;
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun /* Call the ATIF method
74*4882a593Smuzhiyun  */
75*4882a593Smuzhiyun /**
76*4882a593Smuzhiyun  * amdgpu_atif_call - call an ATIF method
77*4882a593Smuzhiyun  *
78*4882a593Smuzhiyun  * @handle: acpi handle
79*4882a593Smuzhiyun  * @function: the ATIF function to execute
80*4882a593Smuzhiyun  * @params: ATIF function params
81*4882a593Smuzhiyun  *
82*4882a593Smuzhiyun  * Executes the requested ATIF function (all asics).
83*4882a593Smuzhiyun  * Returns a pointer to the acpi output buffer.
84*4882a593Smuzhiyun  */
amdgpu_atif_call(struct amdgpu_atif * atif,int function,struct acpi_buffer * params)85*4882a593Smuzhiyun static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
86*4882a593Smuzhiyun 					   int function,
87*4882a593Smuzhiyun 					   struct acpi_buffer *params)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	acpi_status status;
90*4882a593Smuzhiyun 	union acpi_object atif_arg_elements[2];
91*4882a593Smuzhiyun 	struct acpi_object_list atif_arg;
92*4882a593Smuzhiyun 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	atif_arg.count = 2;
95*4882a593Smuzhiyun 	atif_arg.pointer = &atif_arg_elements[0];
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	atif_arg_elements[0].type = ACPI_TYPE_INTEGER;
98*4882a593Smuzhiyun 	atif_arg_elements[0].integer.value = function;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	if (params) {
101*4882a593Smuzhiyun 		atif_arg_elements[1].type = ACPI_TYPE_BUFFER;
102*4882a593Smuzhiyun 		atif_arg_elements[1].buffer.length = params->length;
103*4882a593Smuzhiyun 		atif_arg_elements[1].buffer.pointer = params->pointer;
104*4882a593Smuzhiyun 	} else {
105*4882a593Smuzhiyun 		/* We need a second fake parameter */
106*4882a593Smuzhiyun 		atif_arg_elements[1].type = ACPI_TYPE_INTEGER;
107*4882a593Smuzhiyun 		atif_arg_elements[1].integer.value = 0;
108*4882a593Smuzhiyun 	}
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	status = acpi_evaluate_object(atif->handle, NULL, &atif_arg,
111*4882a593Smuzhiyun 				      &buffer);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	/* Fail only if calling the method fails and ATIF is supported */
114*4882a593Smuzhiyun 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
115*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
116*4882a593Smuzhiyun 				 acpi_format_exception(status));
117*4882a593Smuzhiyun 		kfree(buffer.pointer);
118*4882a593Smuzhiyun 		return NULL;
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	return buffer.pointer;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun /**
125*4882a593Smuzhiyun  * amdgpu_atif_parse_notification - parse supported notifications
126*4882a593Smuzhiyun  *
127*4882a593Smuzhiyun  * @n: supported notifications struct
128*4882a593Smuzhiyun  * @mask: supported notifications mask from ATIF
129*4882a593Smuzhiyun  *
130*4882a593Smuzhiyun  * Use the supported notifications mask from ATIF function
131*4882a593Smuzhiyun  * ATIF_FUNCTION_VERIFY_INTERFACE to determine what notifications
132*4882a593Smuzhiyun  * are supported (all asics).
133*4882a593Smuzhiyun  */
amdgpu_atif_parse_notification(struct amdgpu_atif_notifications * n,u32 mask)134*4882a593Smuzhiyun static void amdgpu_atif_parse_notification(struct amdgpu_atif_notifications *n, u32 mask)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun 	n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED;
137*4882a593Smuzhiyun 	n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED;
138*4882a593Smuzhiyun 	n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED;
139*4882a593Smuzhiyun 	n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED;
140*4882a593Smuzhiyun 	n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED;
141*4882a593Smuzhiyun 	n->gpu_package_power_limit = mask & ATIF_GPU_PACKAGE_POWER_LIMIT_REQUEST_SUPPORTED;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun /**
145*4882a593Smuzhiyun  * amdgpu_atif_parse_functions - parse supported functions
146*4882a593Smuzhiyun  *
147*4882a593Smuzhiyun  * @f: supported functions struct
148*4882a593Smuzhiyun  * @mask: supported functions mask from ATIF
149*4882a593Smuzhiyun  *
150*4882a593Smuzhiyun  * Use the supported functions mask from ATIF function
151*4882a593Smuzhiyun  * ATIF_FUNCTION_VERIFY_INTERFACE to determine what functions
152*4882a593Smuzhiyun  * are supported (all asics).
153*4882a593Smuzhiyun  */
amdgpu_atif_parse_functions(struct amdgpu_atif_functions * f,u32 mask)154*4882a593Smuzhiyun static void amdgpu_atif_parse_functions(struct amdgpu_atif_functions *f, u32 mask)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun 	f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED;
157*4882a593Smuzhiyun 	f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED;
158*4882a593Smuzhiyun 	f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED;
159*4882a593Smuzhiyun 	f->query_backlight_transfer_characteristics =
160*4882a593Smuzhiyun 		mask & ATIF_QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS_SUPPORTED;
161*4882a593Smuzhiyun 	f->ready_to_undock = mask & ATIF_READY_TO_UNDOCK_NOTIFICATION_SUPPORTED;
162*4882a593Smuzhiyun 	f->external_gpu_information = mask & ATIF_GET_EXTERNAL_GPU_INFORMATION_SUPPORTED;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun /**
166*4882a593Smuzhiyun  * amdgpu_atif_verify_interface - verify ATIF
167*4882a593Smuzhiyun  *
168*4882a593Smuzhiyun  * @handle: acpi handle
169*4882a593Smuzhiyun  * @atif: amdgpu atif struct
170*4882a593Smuzhiyun  *
171*4882a593Smuzhiyun  * Execute the ATIF_FUNCTION_VERIFY_INTERFACE ATIF function
172*4882a593Smuzhiyun  * to initialize ATIF and determine what features are supported
173*4882a593Smuzhiyun  * (all asics).
174*4882a593Smuzhiyun  * returns 0 on success, error on failure.
175*4882a593Smuzhiyun  */
amdgpu_atif_verify_interface(struct amdgpu_atif * atif)176*4882a593Smuzhiyun static int amdgpu_atif_verify_interface(struct amdgpu_atif *atif)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	union acpi_object *info;
179*4882a593Smuzhiyun 	struct atif_verify_interface output;
180*4882a593Smuzhiyun 	size_t size;
181*4882a593Smuzhiyun 	int err = 0;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	info = amdgpu_atif_call(atif, ATIF_FUNCTION_VERIFY_INTERFACE, NULL);
184*4882a593Smuzhiyun 	if (!info)
185*4882a593Smuzhiyun 		return -EIO;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	memset(&output, 0, sizeof(output));
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	size = *(u16 *) info->buffer.pointer;
190*4882a593Smuzhiyun 	if (size < 12) {
191*4882a593Smuzhiyun 		DRM_INFO("ATIF buffer is too small: %zu\n", size);
192*4882a593Smuzhiyun 		err = -EINVAL;
193*4882a593Smuzhiyun 		goto out;
194*4882a593Smuzhiyun 	}
195*4882a593Smuzhiyun 	size = min(sizeof(output), size);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	memcpy(&output, info->buffer.pointer, size);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	/* TODO: check version? */
200*4882a593Smuzhiyun 	DRM_DEBUG_DRIVER("ATIF version %u\n", output.version);
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	amdgpu_atif_parse_notification(&atif->notifications, output.notification_mask);
203*4882a593Smuzhiyun 	amdgpu_atif_parse_functions(&atif->functions, output.function_bits);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun out:
206*4882a593Smuzhiyun 	kfree(info);
207*4882a593Smuzhiyun 	return err;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
amdgpu_atif_probe_handle(acpi_handle dhandle)210*4882a593Smuzhiyun static acpi_handle amdgpu_atif_probe_handle(acpi_handle dhandle)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	acpi_handle handle = NULL;
213*4882a593Smuzhiyun 	char acpi_method_name[255] = { 0 };
214*4882a593Smuzhiyun 	struct acpi_buffer buffer = { sizeof(acpi_method_name), acpi_method_name };
215*4882a593Smuzhiyun 	acpi_status status;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	/* For PX/HG systems, ATIF and ATPX are in the iGPU's namespace, on dGPU only
218*4882a593Smuzhiyun 	 * systems, ATIF is in the dGPU's namespace.
219*4882a593Smuzhiyun 	 */
220*4882a593Smuzhiyun 	status = acpi_get_handle(dhandle, "ATIF", &handle);
221*4882a593Smuzhiyun 	if (ACPI_SUCCESS(status))
222*4882a593Smuzhiyun 		goto out;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	if (amdgpu_has_atpx()) {
225*4882a593Smuzhiyun 		status = acpi_get_handle(amdgpu_atpx_get_dhandle(), "ATIF",
226*4882a593Smuzhiyun 					 &handle);
227*4882a593Smuzhiyun 		if (ACPI_SUCCESS(status))
228*4882a593Smuzhiyun 			goto out;
229*4882a593Smuzhiyun 	}
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	DRM_DEBUG_DRIVER("No ATIF handle found\n");
232*4882a593Smuzhiyun 	return NULL;
233*4882a593Smuzhiyun out:
234*4882a593Smuzhiyun 	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
235*4882a593Smuzhiyun 	DRM_DEBUG_DRIVER("Found ATIF handle %s\n", acpi_method_name);
236*4882a593Smuzhiyun 	return handle;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun /**
240*4882a593Smuzhiyun  * amdgpu_atif_get_notification_params - determine notify configuration
241*4882a593Smuzhiyun  *
242*4882a593Smuzhiyun  * @handle: acpi handle
243*4882a593Smuzhiyun  * @n: atif notification configuration struct
244*4882a593Smuzhiyun  *
245*4882a593Smuzhiyun  * Execute the ATIF_FUNCTION_GET_SYSTEM_PARAMETERS ATIF function
246*4882a593Smuzhiyun  * to determine if a notifier is used and if so which one
247*4882a593Smuzhiyun  * (all asics).  This is either Notify(VGA, 0x81) or Notify(VGA, n)
248*4882a593Smuzhiyun  * where n is specified in the result if a notifier is used.
249*4882a593Smuzhiyun  * Returns 0 on success, error on failure.
250*4882a593Smuzhiyun  */
amdgpu_atif_get_notification_params(struct amdgpu_atif * atif)251*4882a593Smuzhiyun static int amdgpu_atif_get_notification_params(struct amdgpu_atif *atif)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	union acpi_object *info;
254*4882a593Smuzhiyun 	struct amdgpu_atif_notification_cfg *n = &atif->notification_cfg;
255*4882a593Smuzhiyun 	struct atif_system_params params;
256*4882a593Smuzhiyun 	size_t size;
257*4882a593Smuzhiyun 	int err = 0;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS,
260*4882a593Smuzhiyun 				NULL);
261*4882a593Smuzhiyun 	if (!info) {
262*4882a593Smuzhiyun 		err = -EIO;
263*4882a593Smuzhiyun 		goto out;
264*4882a593Smuzhiyun 	}
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	size = *(u16 *) info->buffer.pointer;
267*4882a593Smuzhiyun 	if (size < 10) {
268*4882a593Smuzhiyun 		err = -EINVAL;
269*4882a593Smuzhiyun 		goto out;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	memset(&params, 0, sizeof(params));
273*4882a593Smuzhiyun 	size = min(sizeof(params), size);
274*4882a593Smuzhiyun 	memcpy(&params, info->buffer.pointer, size);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n",
277*4882a593Smuzhiyun 			params.flags, params.valid_mask);
278*4882a593Smuzhiyun 	params.flags = params.flags & params.valid_mask;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) {
281*4882a593Smuzhiyun 		n->enabled = false;
282*4882a593Smuzhiyun 		n->command_code = 0;
283*4882a593Smuzhiyun 	} else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) {
284*4882a593Smuzhiyun 		n->enabled = true;
285*4882a593Smuzhiyun 		n->command_code = 0x81;
286*4882a593Smuzhiyun 	} else {
287*4882a593Smuzhiyun 		if (size < 11) {
288*4882a593Smuzhiyun 			err = -EINVAL;
289*4882a593Smuzhiyun 			goto out;
290*4882a593Smuzhiyun 		}
291*4882a593Smuzhiyun 		n->enabled = true;
292*4882a593Smuzhiyun 		n->command_code = params.command_code;
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun out:
296*4882a593Smuzhiyun 	DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n",
297*4882a593Smuzhiyun 			(n->enabled ? "enabled" : "disabled"),
298*4882a593Smuzhiyun 			n->command_code);
299*4882a593Smuzhiyun 	kfree(info);
300*4882a593Smuzhiyun 	return err;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun /**
304*4882a593Smuzhiyun  * amdgpu_atif_query_backlight_caps - get min and max backlight input signal
305*4882a593Smuzhiyun  *
306*4882a593Smuzhiyun  * @handle: acpi handle
307*4882a593Smuzhiyun  *
308*4882a593Smuzhiyun  * Execute the QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS ATIF function
309*4882a593Smuzhiyun  * to determine the acceptable range of backlight values
310*4882a593Smuzhiyun  *
311*4882a593Smuzhiyun  * Backlight_caps.caps_valid will be set to true if the query is successful
312*4882a593Smuzhiyun  *
313*4882a593Smuzhiyun  * The input signals are in range 0-255
314*4882a593Smuzhiyun  *
315*4882a593Smuzhiyun  * This function assumes the display with backlight is the first LCD
316*4882a593Smuzhiyun  *
317*4882a593Smuzhiyun  * Returns 0 on success, error on failure.
318*4882a593Smuzhiyun  */
amdgpu_atif_query_backlight_caps(struct amdgpu_atif * atif)319*4882a593Smuzhiyun static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	union acpi_object *info;
322*4882a593Smuzhiyun 	struct atif_qbtc_output characteristics;
323*4882a593Smuzhiyun 	struct atif_qbtc_arguments arguments;
324*4882a593Smuzhiyun 	struct acpi_buffer params;
325*4882a593Smuzhiyun 	size_t size;
326*4882a593Smuzhiyun 	int err = 0;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	arguments.size = sizeof(arguments);
329*4882a593Smuzhiyun 	arguments.requested_display = ATIF_QBTC_REQUEST_LCD1;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	params.length = sizeof(arguments);
332*4882a593Smuzhiyun 	params.pointer = (void *)&arguments;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	info = amdgpu_atif_call(atif,
335*4882a593Smuzhiyun 		ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS,
336*4882a593Smuzhiyun 		&params);
337*4882a593Smuzhiyun 	if (!info) {
338*4882a593Smuzhiyun 		err = -EIO;
339*4882a593Smuzhiyun 		goto out;
340*4882a593Smuzhiyun 	}
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	size = *(u16 *) info->buffer.pointer;
343*4882a593Smuzhiyun 	if (size < 10) {
344*4882a593Smuzhiyun 		err = -EINVAL;
345*4882a593Smuzhiyun 		goto out;
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	memset(&characteristics, 0, sizeof(characteristics));
349*4882a593Smuzhiyun 	size = min(sizeof(characteristics), size);
350*4882a593Smuzhiyun 	memcpy(&characteristics, info->buffer.pointer, size);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	atif->backlight_caps.caps_valid = true;
353*4882a593Smuzhiyun 	atif->backlight_caps.min_input_signal =
354*4882a593Smuzhiyun 			characteristics.min_input_signal;
355*4882a593Smuzhiyun 	atif->backlight_caps.max_input_signal =
356*4882a593Smuzhiyun 			characteristics.max_input_signal;
357*4882a593Smuzhiyun out:
358*4882a593Smuzhiyun 	kfree(info);
359*4882a593Smuzhiyun 	return err;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun /**
363*4882a593Smuzhiyun  * amdgpu_atif_get_sbios_requests - get requested sbios event
364*4882a593Smuzhiyun  *
365*4882a593Smuzhiyun  * @handle: acpi handle
366*4882a593Smuzhiyun  * @req: atif sbios request struct
367*4882a593Smuzhiyun  *
368*4882a593Smuzhiyun  * Execute the ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS ATIF function
369*4882a593Smuzhiyun  * to determine what requests the sbios is making to the driver
370*4882a593Smuzhiyun  * (all asics).
371*4882a593Smuzhiyun  * Returns 0 on success, error on failure.
372*4882a593Smuzhiyun  */
amdgpu_atif_get_sbios_requests(struct amdgpu_atif * atif,struct atif_sbios_requests * req)373*4882a593Smuzhiyun static int amdgpu_atif_get_sbios_requests(struct amdgpu_atif *atif,
374*4882a593Smuzhiyun 					  struct atif_sbios_requests *req)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun 	union acpi_object *info;
377*4882a593Smuzhiyun 	size_t size;
378*4882a593Smuzhiyun 	int count = 0;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS,
381*4882a593Smuzhiyun 				NULL);
382*4882a593Smuzhiyun 	if (!info)
383*4882a593Smuzhiyun 		return -EIO;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	size = *(u16 *)info->buffer.pointer;
386*4882a593Smuzhiyun 	if (size < 0xd) {
387*4882a593Smuzhiyun 		count = -EINVAL;
388*4882a593Smuzhiyun 		goto out;
389*4882a593Smuzhiyun 	}
390*4882a593Smuzhiyun 	memset(req, 0, sizeof(*req));
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	size = min(sizeof(*req), size);
393*4882a593Smuzhiyun 	memcpy(req, info->buffer.pointer, size);
394*4882a593Smuzhiyun 	DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	count = hweight32(req->pending);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun out:
399*4882a593Smuzhiyun 	kfree(info);
400*4882a593Smuzhiyun 	return count;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun /**
404*4882a593Smuzhiyun  * amdgpu_atif_handler - handle ATIF notify requests
405*4882a593Smuzhiyun  *
406*4882a593Smuzhiyun  * @adev: amdgpu_device pointer
407*4882a593Smuzhiyun  * @event: atif sbios request struct
408*4882a593Smuzhiyun  *
409*4882a593Smuzhiyun  * Checks the acpi event and if it matches an atif event,
410*4882a593Smuzhiyun  * handles it.
411*4882a593Smuzhiyun  *
412*4882a593Smuzhiyun  * Returns:
413*4882a593Smuzhiyun  * NOTIFY_BAD or NOTIFY_DONE, depending on the event.
414*4882a593Smuzhiyun  */
amdgpu_atif_handler(struct amdgpu_device * adev,struct acpi_bus_event * event)415*4882a593Smuzhiyun static int amdgpu_atif_handler(struct amdgpu_device *adev,
416*4882a593Smuzhiyun 			       struct acpi_bus_event *event)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	struct amdgpu_atif *atif = adev->atif;
419*4882a593Smuzhiyun 	int count;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n",
422*4882a593Smuzhiyun 			event->device_class, event->type);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
425*4882a593Smuzhiyun 		return NOTIFY_DONE;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	/* Is this actually our event? */
428*4882a593Smuzhiyun 	if (!atif ||
429*4882a593Smuzhiyun 	    !atif->notification_cfg.enabled ||
430*4882a593Smuzhiyun 	    event->type != atif->notification_cfg.command_code) {
431*4882a593Smuzhiyun 		/* These events will generate keypresses otherwise */
432*4882a593Smuzhiyun 		if (event->type == ACPI_VIDEO_NOTIFY_PROBE)
433*4882a593Smuzhiyun 			return NOTIFY_BAD;
434*4882a593Smuzhiyun 		else
435*4882a593Smuzhiyun 			return NOTIFY_DONE;
436*4882a593Smuzhiyun 	}
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	if (atif->functions.sbios_requests) {
439*4882a593Smuzhiyun 		struct atif_sbios_requests req;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 		/* Check pending SBIOS requests */
442*4882a593Smuzhiyun 		count = amdgpu_atif_get_sbios_requests(atif, &req);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 		if (count <= 0)
445*4882a593Smuzhiyun 			return NOTIFY_BAD;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 		if (req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) {
450*4882a593Smuzhiyun #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
451*4882a593Smuzhiyun 			if (atif->bd) {
452*4882a593Smuzhiyun 				DRM_DEBUG_DRIVER("Changing brightness to %d\n",
453*4882a593Smuzhiyun 						 req.backlight_level);
454*4882a593Smuzhiyun 				/*
455*4882a593Smuzhiyun 				 * XXX backlight_device_set_brightness() is
456*4882a593Smuzhiyun 				 * hardwired to post BACKLIGHT_UPDATE_SYSFS.
457*4882a593Smuzhiyun 				 * It probably should accept 'reason' parameter.
458*4882a593Smuzhiyun 				 */
459*4882a593Smuzhiyun 				backlight_device_set_brightness(atif->bd, req.backlight_level);
460*4882a593Smuzhiyun 			}
461*4882a593Smuzhiyun #endif
462*4882a593Smuzhiyun 		}
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 		if (req.pending & ATIF_DGPU_DISPLAY_EVENT) {
465*4882a593Smuzhiyun 			if (adev->flags & AMD_IS_PX) {
466*4882a593Smuzhiyun 				pm_runtime_get_sync(adev_to_drm(adev)->dev);
467*4882a593Smuzhiyun 				/* Just fire off a uevent and let userspace tell us what to do */
468*4882a593Smuzhiyun 				drm_helper_hpd_irq_event(adev_to_drm(adev));
469*4882a593Smuzhiyun 				pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
470*4882a593Smuzhiyun 				pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
471*4882a593Smuzhiyun 			}
472*4882a593Smuzhiyun 		}
473*4882a593Smuzhiyun 		/* TODO: check other events */
474*4882a593Smuzhiyun 	}
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	/* We've handled the event, stop the notifier chain. The ACPI interface
477*4882a593Smuzhiyun 	 * overloads ACPI_VIDEO_NOTIFY_PROBE, we don't want to send that to
478*4882a593Smuzhiyun 	 * userspace if the event was generated only to signal a SBIOS
479*4882a593Smuzhiyun 	 * request.
480*4882a593Smuzhiyun 	 */
481*4882a593Smuzhiyun 	return NOTIFY_BAD;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun /* Call the ATCS method
485*4882a593Smuzhiyun  */
486*4882a593Smuzhiyun /**
487*4882a593Smuzhiyun  * amdgpu_atcs_call - call an ATCS method
488*4882a593Smuzhiyun  *
489*4882a593Smuzhiyun  * @handle: acpi handle
490*4882a593Smuzhiyun  * @function: the ATCS function to execute
491*4882a593Smuzhiyun  * @params: ATCS function params
492*4882a593Smuzhiyun  *
493*4882a593Smuzhiyun  * Executes the requested ATCS function (all asics).
494*4882a593Smuzhiyun  * Returns a pointer to the acpi output buffer.
495*4882a593Smuzhiyun  */
amdgpu_atcs_call(acpi_handle handle,int function,struct acpi_buffer * params)496*4882a593Smuzhiyun static union acpi_object *amdgpu_atcs_call(acpi_handle handle, int function,
497*4882a593Smuzhiyun 					   struct acpi_buffer *params)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun 	acpi_status status;
500*4882a593Smuzhiyun 	union acpi_object atcs_arg_elements[2];
501*4882a593Smuzhiyun 	struct acpi_object_list atcs_arg;
502*4882a593Smuzhiyun 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	atcs_arg.count = 2;
505*4882a593Smuzhiyun 	atcs_arg.pointer = &atcs_arg_elements[0];
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	atcs_arg_elements[0].type = ACPI_TYPE_INTEGER;
508*4882a593Smuzhiyun 	atcs_arg_elements[0].integer.value = function;
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	if (params) {
511*4882a593Smuzhiyun 		atcs_arg_elements[1].type = ACPI_TYPE_BUFFER;
512*4882a593Smuzhiyun 		atcs_arg_elements[1].buffer.length = params->length;
513*4882a593Smuzhiyun 		atcs_arg_elements[1].buffer.pointer = params->pointer;
514*4882a593Smuzhiyun 	} else {
515*4882a593Smuzhiyun 		/* We need a second fake parameter */
516*4882a593Smuzhiyun 		atcs_arg_elements[1].type = ACPI_TYPE_INTEGER;
517*4882a593Smuzhiyun 		atcs_arg_elements[1].integer.value = 0;
518*4882a593Smuzhiyun 	}
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	status = acpi_evaluate_object(handle, "ATCS", &atcs_arg, &buffer);
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	/* Fail only if calling the method fails and ATIF is supported */
523*4882a593Smuzhiyun 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
524*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("failed to evaluate ATCS got %s\n",
525*4882a593Smuzhiyun 				 acpi_format_exception(status));
526*4882a593Smuzhiyun 		kfree(buffer.pointer);
527*4882a593Smuzhiyun 		return NULL;
528*4882a593Smuzhiyun 	}
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	return buffer.pointer;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun /**
534*4882a593Smuzhiyun  * amdgpu_atcs_parse_functions - parse supported functions
535*4882a593Smuzhiyun  *
536*4882a593Smuzhiyun  * @f: supported functions struct
537*4882a593Smuzhiyun  * @mask: supported functions mask from ATCS
538*4882a593Smuzhiyun  *
539*4882a593Smuzhiyun  * Use the supported functions mask from ATCS function
540*4882a593Smuzhiyun  * ATCS_FUNCTION_VERIFY_INTERFACE to determine what functions
541*4882a593Smuzhiyun  * are supported (all asics).
542*4882a593Smuzhiyun  */
amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions * f,u32 mask)543*4882a593Smuzhiyun static void amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions *f, u32 mask)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun 	f->get_ext_state = mask & ATCS_GET_EXTERNAL_STATE_SUPPORTED;
546*4882a593Smuzhiyun 	f->pcie_perf_req = mask & ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED;
547*4882a593Smuzhiyun 	f->pcie_dev_rdy = mask & ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED;
548*4882a593Smuzhiyun 	f->pcie_bus_width = mask & ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun /**
552*4882a593Smuzhiyun  * amdgpu_atcs_verify_interface - verify ATCS
553*4882a593Smuzhiyun  *
554*4882a593Smuzhiyun  * @handle: acpi handle
555*4882a593Smuzhiyun  * @atcs: amdgpu atcs struct
556*4882a593Smuzhiyun  *
557*4882a593Smuzhiyun  * Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function
558*4882a593Smuzhiyun  * to initialize ATCS and determine what features are supported
559*4882a593Smuzhiyun  * (all asics).
560*4882a593Smuzhiyun  * returns 0 on success, error on failure.
561*4882a593Smuzhiyun  */
amdgpu_atcs_verify_interface(acpi_handle handle,struct amdgpu_atcs * atcs)562*4882a593Smuzhiyun static int amdgpu_atcs_verify_interface(acpi_handle handle,
563*4882a593Smuzhiyun 					struct amdgpu_atcs *atcs)
564*4882a593Smuzhiyun {
565*4882a593Smuzhiyun 	union acpi_object *info;
566*4882a593Smuzhiyun 	struct atcs_verify_interface output;
567*4882a593Smuzhiyun 	size_t size;
568*4882a593Smuzhiyun 	int err = 0;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	info = amdgpu_atcs_call(handle, ATCS_FUNCTION_VERIFY_INTERFACE, NULL);
571*4882a593Smuzhiyun 	if (!info)
572*4882a593Smuzhiyun 		return -EIO;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	memset(&output, 0, sizeof(output));
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	size = *(u16 *) info->buffer.pointer;
577*4882a593Smuzhiyun 	if (size < 8) {
578*4882a593Smuzhiyun 		DRM_INFO("ATCS buffer is too small: %zu\n", size);
579*4882a593Smuzhiyun 		err = -EINVAL;
580*4882a593Smuzhiyun 		goto out;
581*4882a593Smuzhiyun 	}
582*4882a593Smuzhiyun 	size = min(sizeof(output), size);
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	memcpy(&output, info->buffer.pointer, size);
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 	/* TODO: check version? */
587*4882a593Smuzhiyun 	DRM_DEBUG_DRIVER("ATCS version %u\n", output.version);
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	amdgpu_atcs_parse_functions(&atcs->functions, output.function_bits);
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun out:
592*4882a593Smuzhiyun 	kfree(info);
593*4882a593Smuzhiyun 	return err;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun /**
597*4882a593Smuzhiyun  * amdgpu_acpi_is_pcie_performance_request_supported
598*4882a593Smuzhiyun  *
599*4882a593Smuzhiyun  * @adev: amdgpu_device pointer
600*4882a593Smuzhiyun  *
601*4882a593Smuzhiyun  * Check if the ATCS pcie_perf_req and pcie_dev_rdy methods
602*4882a593Smuzhiyun  * are supported (all asics).
603*4882a593Smuzhiyun  * returns true if supported, false if not.
604*4882a593Smuzhiyun  */
amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device * adev)605*4882a593Smuzhiyun bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *adev)
606*4882a593Smuzhiyun {
607*4882a593Smuzhiyun 	struct amdgpu_atcs *atcs = &adev->atcs;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	if (atcs->functions.pcie_perf_req && atcs->functions.pcie_dev_rdy)
610*4882a593Smuzhiyun 		return true;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	return false;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun /**
616*4882a593Smuzhiyun  * amdgpu_acpi_pcie_notify_device_ready
617*4882a593Smuzhiyun  *
618*4882a593Smuzhiyun  * @adev: amdgpu_device pointer
619*4882a593Smuzhiyun  *
620*4882a593Smuzhiyun  * Executes the PCIE_DEVICE_READY_NOTIFICATION method
621*4882a593Smuzhiyun  * (all asics).
622*4882a593Smuzhiyun  * returns 0 on success, error on failure.
623*4882a593Smuzhiyun  */
amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device * adev)624*4882a593Smuzhiyun int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev)
625*4882a593Smuzhiyun {
626*4882a593Smuzhiyun 	acpi_handle handle;
627*4882a593Smuzhiyun 	union acpi_object *info;
628*4882a593Smuzhiyun 	struct amdgpu_atcs *atcs = &adev->atcs;
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	/* Get the device handle */
631*4882a593Smuzhiyun 	handle = ACPI_HANDLE(&adev->pdev->dev);
632*4882a593Smuzhiyun 	if (!handle)
633*4882a593Smuzhiyun 		return -EINVAL;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	if (!atcs->functions.pcie_dev_rdy)
636*4882a593Smuzhiyun 		return -EINVAL;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	info = amdgpu_atcs_call(handle, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION, NULL);
639*4882a593Smuzhiyun 	if (!info)
640*4882a593Smuzhiyun 		return -EIO;
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	kfree(info);
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	return 0;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun /**
648*4882a593Smuzhiyun  * amdgpu_acpi_pcie_performance_request
649*4882a593Smuzhiyun  *
650*4882a593Smuzhiyun  * @adev: amdgpu_device pointer
651*4882a593Smuzhiyun  * @perf_req: requested perf level (pcie gen speed)
652*4882a593Smuzhiyun  * @advertise: set advertise caps flag if set
653*4882a593Smuzhiyun  *
654*4882a593Smuzhiyun  * Executes the PCIE_PERFORMANCE_REQUEST method to
655*4882a593Smuzhiyun  * change the pcie gen speed (all asics).
656*4882a593Smuzhiyun  * returns 0 on success, error on failure.
657*4882a593Smuzhiyun  */
amdgpu_acpi_pcie_performance_request(struct amdgpu_device * adev,u8 perf_req,bool advertise)658*4882a593Smuzhiyun int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev,
659*4882a593Smuzhiyun 					 u8 perf_req, bool advertise)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun 	acpi_handle handle;
662*4882a593Smuzhiyun 	union acpi_object *info;
663*4882a593Smuzhiyun 	struct amdgpu_atcs *atcs = &adev->atcs;
664*4882a593Smuzhiyun 	struct atcs_pref_req_input atcs_input;
665*4882a593Smuzhiyun 	struct atcs_pref_req_output atcs_output;
666*4882a593Smuzhiyun 	struct acpi_buffer params;
667*4882a593Smuzhiyun 	size_t size;
668*4882a593Smuzhiyun 	u32 retry = 3;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	if (amdgpu_acpi_pcie_notify_device_ready(adev))
671*4882a593Smuzhiyun 		return -EINVAL;
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	/* Get the device handle */
674*4882a593Smuzhiyun 	handle = ACPI_HANDLE(&adev->pdev->dev);
675*4882a593Smuzhiyun 	if (!handle)
676*4882a593Smuzhiyun 		return -EINVAL;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	if (!atcs->functions.pcie_perf_req)
679*4882a593Smuzhiyun 		return -EINVAL;
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun 	atcs_input.size = sizeof(struct atcs_pref_req_input);
682*4882a593Smuzhiyun 	/* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */
683*4882a593Smuzhiyun 	atcs_input.client_id = adev->pdev->devfn | (adev->pdev->bus->number << 8);
684*4882a593Smuzhiyun 	atcs_input.valid_flags_mask = ATCS_VALID_FLAGS_MASK;
685*4882a593Smuzhiyun 	atcs_input.flags = ATCS_WAIT_FOR_COMPLETION;
686*4882a593Smuzhiyun 	if (advertise)
687*4882a593Smuzhiyun 		atcs_input.flags |= ATCS_ADVERTISE_CAPS;
688*4882a593Smuzhiyun 	atcs_input.req_type = ATCS_PCIE_LINK_SPEED;
689*4882a593Smuzhiyun 	atcs_input.perf_req = perf_req;
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	params.length = sizeof(struct atcs_pref_req_input);
692*4882a593Smuzhiyun 	params.pointer = &atcs_input;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	while (retry--) {
695*4882a593Smuzhiyun 		info = amdgpu_atcs_call(handle, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, &params);
696*4882a593Smuzhiyun 		if (!info)
697*4882a593Smuzhiyun 			return -EIO;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 		memset(&atcs_output, 0, sizeof(atcs_output));
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 		size = *(u16 *) info->buffer.pointer;
702*4882a593Smuzhiyun 		if (size < 3) {
703*4882a593Smuzhiyun 			DRM_INFO("ATCS buffer is too small: %zu\n", size);
704*4882a593Smuzhiyun 			kfree(info);
705*4882a593Smuzhiyun 			return -EINVAL;
706*4882a593Smuzhiyun 		}
707*4882a593Smuzhiyun 		size = min(sizeof(atcs_output), size);
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 		memcpy(&atcs_output, info->buffer.pointer, size);
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 		kfree(info);
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 		switch (atcs_output.ret_val) {
714*4882a593Smuzhiyun 		case ATCS_REQUEST_REFUSED:
715*4882a593Smuzhiyun 		default:
716*4882a593Smuzhiyun 			return -EINVAL;
717*4882a593Smuzhiyun 		case ATCS_REQUEST_COMPLETE:
718*4882a593Smuzhiyun 			return 0;
719*4882a593Smuzhiyun 		case ATCS_REQUEST_IN_PROGRESS:
720*4882a593Smuzhiyun 			udelay(10);
721*4882a593Smuzhiyun 			break;
722*4882a593Smuzhiyun 		}
723*4882a593Smuzhiyun 	}
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	return 0;
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun /**
729*4882a593Smuzhiyun  * amdgpu_acpi_event - handle notify events
730*4882a593Smuzhiyun  *
731*4882a593Smuzhiyun  * @nb: notifier block
732*4882a593Smuzhiyun  * @val: val
733*4882a593Smuzhiyun  * @data: acpi event
734*4882a593Smuzhiyun  *
735*4882a593Smuzhiyun  * Calls relevant amdgpu functions in response to various
736*4882a593Smuzhiyun  * acpi events.
737*4882a593Smuzhiyun  * Returns NOTIFY code
738*4882a593Smuzhiyun  */
amdgpu_acpi_event(struct notifier_block * nb,unsigned long val,void * data)739*4882a593Smuzhiyun static int amdgpu_acpi_event(struct notifier_block *nb,
740*4882a593Smuzhiyun 			     unsigned long val,
741*4882a593Smuzhiyun 			     void *data)
742*4882a593Smuzhiyun {
743*4882a593Smuzhiyun 	struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, acpi_nb);
744*4882a593Smuzhiyun 	struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun 	if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
747*4882a593Smuzhiyun 		if (power_supply_is_system_supplied() > 0)
748*4882a593Smuzhiyun 			DRM_DEBUG_DRIVER("pm: AC\n");
749*4882a593Smuzhiyun 		else
750*4882a593Smuzhiyun 			DRM_DEBUG_DRIVER("pm: DC\n");
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 		amdgpu_pm_acpi_event_handler(adev);
753*4882a593Smuzhiyun 	}
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun 	/* Check for pending SBIOS requests */
756*4882a593Smuzhiyun 	return amdgpu_atif_handler(adev, entry);
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun /* Call all ACPI methods here */
760*4882a593Smuzhiyun /**
761*4882a593Smuzhiyun  * amdgpu_acpi_init - init driver acpi support
762*4882a593Smuzhiyun  *
763*4882a593Smuzhiyun  * @adev: amdgpu_device pointer
764*4882a593Smuzhiyun  *
765*4882a593Smuzhiyun  * Verifies the AMD ACPI interfaces and registers with the acpi
766*4882a593Smuzhiyun  * notifier chain (all asics).
767*4882a593Smuzhiyun  * Returns 0 on success, error on failure.
768*4882a593Smuzhiyun  */
amdgpu_acpi_init(struct amdgpu_device * adev)769*4882a593Smuzhiyun int amdgpu_acpi_init(struct amdgpu_device *adev)
770*4882a593Smuzhiyun {
771*4882a593Smuzhiyun 	acpi_handle handle, atif_handle;
772*4882a593Smuzhiyun 	struct amdgpu_atif *atif;
773*4882a593Smuzhiyun 	struct amdgpu_atcs *atcs = &adev->atcs;
774*4882a593Smuzhiyun 	int ret;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	/* Get the device handle */
777*4882a593Smuzhiyun 	handle = ACPI_HANDLE(&adev->pdev->dev);
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	if (!adev->bios || !handle)
780*4882a593Smuzhiyun 		return 0;
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 	/* Call the ATCS method */
783*4882a593Smuzhiyun 	ret = amdgpu_atcs_verify_interface(handle, atcs);
784*4882a593Smuzhiyun 	if (ret) {
785*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret);
786*4882a593Smuzhiyun 	}
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	/* Probe for ATIF, and initialize it if found */
789*4882a593Smuzhiyun 	atif_handle = amdgpu_atif_probe_handle(handle);
790*4882a593Smuzhiyun 	if (!atif_handle)
791*4882a593Smuzhiyun 		goto out;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	atif = kzalloc(sizeof(*atif), GFP_KERNEL);
794*4882a593Smuzhiyun 	if (!atif) {
795*4882a593Smuzhiyun 		DRM_WARN("Not enough memory to initialize ATIF\n");
796*4882a593Smuzhiyun 		goto out;
797*4882a593Smuzhiyun 	}
798*4882a593Smuzhiyun 	atif->handle = atif_handle;
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	/* Call the ATIF method */
801*4882a593Smuzhiyun 	ret = amdgpu_atif_verify_interface(atif);
802*4882a593Smuzhiyun 	if (ret) {
803*4882a593Smuzhiyun 		DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret);
804*4882a593Smuzhiyun 		kfree(atif);
805*4882a593Smuzhiyun 		goto out;
806*4882a593Smuzhiyun 	}
807*4882a593Smuzhiyun 	adev->atif = atif;
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
810*4882a593Smuzhiyun 	if (atif->notifications.brightness_change) {
811*4882a593Smuzhiyun 		if (amdgpu_device_has_dc_support(adev)) {
812*4882a593Smuzhiyun #if defined(CONFIG_DRM_AMD_DC)
813*4882a593Smuzhiyun 			struct amdgpu_display_manager *dm = &adev->dm;
814*4882a593Smuzhiyun 			atif->bd = dm->backlight_dev;
815*4882a593Smuzhiyun #endif
816*4882a593Smuzhiyun 		} else {
817*4882a593Smuzhiyun 			struct drm_encoder *tmp;
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 			/* Find the encoder controlling the brightness */
820*4882a593Smuzhiyun 			list_for_each_entry(tmp, &adev_to_drm(adev)->mode_config.encoder_list,
821*4882a593Smuzhiyun 					    head) {
822*4882a593Smuzhiyun 				struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp);
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun 				if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
825*4882a593Smuzhiyun 				    enc->enc_priv) {
826*4882a593Smuzhiyun 					struct amdgpu_encoder_atom_dig *dig = enc->enc_priv;
827*4882a593Smuzhiyun 					if (dig->bl_dev) {
828*4882a593Smuzhiyun 						atif->bd = dig->bl_dev;
829*4882a593Smuzhiyun 						break;
830*4882a593Smuzhiyun 					}
831*4882a593Smuzhiyun 				}
832*4882a593Smuzhiyun 			}
833*4882a593Smuzhiyun 		}
834*4882a593Smuzhiyun 	}
835*4882a593Smuzhiyun #endif
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	if (atif->functions.sbios_requests && !atif->functions.system_params) {
838*4882a593Smuzhiyun 		/* XXX check this workraround, if sbios request function is
839*4882a593Smuzhiyun 		 * present we have to see how it's configured in the system
840*4882a593Smuzhiyun 		 * params
841*4882a593Smuzhiyun 		 */
842*4882a593Smuzhiyun 		atif->functions.system_params = true;
843*4882a593Smuzhiyun 	}
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 	if (atif->functions.system_params) {
846*4882a593Smuzhiyun 		ret = amdgpu_atif_get_notification_params(atif);
847*4882a593Smuzhiyun 		if (ret) {
848*4882a593Smuzhiyun 			DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n",
849*4882a593Smuzhiyun 					ret);
850*4882a593Smuzhiyun 			/* Disable notification */
851*4882a593Smuzhiyun 			atif->notification_cfg.enabled = false;
852*4882a593Smuzhiyun 		}
853*4882a593Smuzhiyun 	}
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	if (atif->functions.query_backlight_transfer_characteristics) {
856*4882a593Smuzhiyun 		ret = amdgpu_atif_query_backlight_caps(atif);
857*4882a593Smuzhiyun 		if (ret) {
858*4882a593Smuzhiyun 			DRM_DEBUG_DRIVER("Call to QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS failed: %d\n",
859*4882a593Smuzhiyun 					ret);
860*4882a593Smuzhiyun 			atif->backlight_caps.caps_valid = false;
861*4882a593Smuzhiyun 		}
862*4882a593Smuzhiyun 	} else {
863*4882a593Smuzhiyun 		atif->backlight_caps.caps_valid = false;
864*4882a593Smuzhiyun 	}
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun out:
867*4882a593Smuzhiyun 	adev->acpi_nb.notifier_call = amdgpu_acpi_event;
868*4882a593Smuzhiyun 	register_acpi_notifier(&adev->acpi_nb);
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 	return ret;
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun 
amdgpu_acpi_get_backlight_caps(struct amdgpu_device * adev,struct amdgpu_dm_backlight_caps * caps)873*4882a593Smuzhiyun void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev,
874*4882a593Smuzhiyun 		struct amdgpu_dm_backlight_caps *caps)
875*4882a593Smuzhiyun {
876*4882a593Smuzhiyun 	if (!adev->atif) {
877*4882a593Smuzhiyun 		caps->caps_valid = false;
878*4882a593Smuzhiyun 		return;
879*4882a593Smuzhiyun 	}
880*4882a593Smuzhiyun 	caps->caps_valid = adev->atif->backlight_caps.caps_valid;
881*4882a593Smuzhiyun 	caps->min_input_signal = adev->atif->backlight_caps.min_input_signal;
882*4882a593Smuzhiyun 	caps->max_input_signal = adev->atif->backlight_caps.max_input_signal;
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun /**
886*4882a593Smuzhiyun  * amdgpu_acpi_fini - tear down driver acpi support
887*4882a593Smuzhiyun  *
888*4882a593Smuzhiyun  * @adev: amdgpu_device pointer
889*4882a593Smuzhiyun  *
890*4882a593Smuzhiyun  * Unregisters with the acpi notifier chain (all asics).
891*4882a593Smuzhiyun  */
amdgpu_acpi_fini(struct amdgpu_device * adev)892*4882a593Smuzhiyun void amdgpu_acpi_fini(struct amdgpu_device *adev)
893*4882a593Smuzhiyun {
894*4882a593Smuzhiyun 	unregister_acpi_notifier(&adev->acpi_nb);
895*4882a593Smuzhiyun 	kfree(adev->atif);
896*4882a593Smuzhiyun }
897