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(¶ms, 0, sizeof(params));
273*4882a593Smuzhiyun size = min(sizeof(params), size);
274*4882a593Smuzhiyun memcpy(¶ms, 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 ¶ms);
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, ¶ms);
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