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