xref: /linux/drivers/gpu/drm/radeon/radeon_acpi.c (revision fda4b25c55a59ba12378e4b9e4553f6ea57d802d)
1efd4e418SAlex Deucher /*
2efd4e418SAlex Deucher  * Copyright 2012 Advanced Micro Devices, Inc.
3efd4e418SAlex Deucher  *
4efd4e418SAlex Deucher  * Permission is hereby granted, free of charge, to any person obtaining a
5efd4e418SAlex Deucher  * copy of this software and associated documentation files (the "Software"),
6efd4e418SAlex Deucher  * to deal in the Software without restriction, including without limitation
7efd4e418SAlex Deucher  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8efd4e418SAlex Deucher  * and/or sell copies of the Software, and to permit persons to whom the
9efd4e418SAlex Deucher  * Software is furnished to do so, subject to the following conditions:
10efd4e418SAlex Deucher  *
11efd4e418SAlex Deucher  * The above copyright notice and this permission notice shall be included in
12efd4e418SAlex Deucher  * all copies or substantial portions of the Software.
13efd4e418SAlex Deucher  *
14efd4e418SAlex Deucher  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15efd4e418SAlex Deucher  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16efd4e418SAlex Deucher  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17efd4e418SAlex Deucher  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18efd4e418SAlex Deucher  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19efd4e418SAlex Deucher  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20efd4e418SAlex Deucher  * OTHER DEALINGS IN THE SOFTWARE.
21efd4e418SAlex Deucher  *
22efd4e418SAlex Deucher  */
23efd4e418SAlex Deucher 
24d7a2952fSAlberto Milone #include <linux/pci.h>
25d7a2952fSAlberto Milone #include <linux/acpi.h>
26d7a2952fSAlberto Milone #include <linux/slab.h>
27d7a2952fSAlberto Milone #include <acpi/acpi_drivers.h>
28d7a2952fSAlberto Milone #include <acpi/acpi_bus.h>
29*fda4b25cSLuca Tettamanti #include <acpi/video.h>
30d7a2952fSAlberto Milone 
31d7a2952fSAlberto Milone #include "drmP.h"
32d7a2952fSAlberto Milone #include "drm.h"
33d7a2952fSAlberto Milone #include "drm_sarea.h"
34d7a2952fSAlberto Milone #include "drm_crtc_helper.h"
35d7a2952fSAlberto Milone #include "radeon.h"
369e05b2f4SAlex Deucher #include "radeon_acpi.h"
37*fda4b25cSLuca Tettamanti #include "atom.h"
38d7a2952fSAlberto Milone 
39d7a2952fSAlberto Milone #include <linux/vga_switcheroo.h>
40d7a2952fSAlberto Milone 
41fd64ca8aSLuca Tettamanti struct atif_verify_interface {
42fd64ca8aSLuca Tettamanti 	u16 size;		/* structure size in bytes (includes size field) */
43fd64ca8aSLuca Tettamanti 	u16 version;		/* version */
44fd64ca8aSLuca Tettamanti 	u32 notification_mask;	/* supported notifications mask */
45fd64ca8aSLuca Tettamanti 	u32 function_bits;	/* supported functions bit vector */
46fd64ca8aSLuca Tettamanti } __packed;
47fd64ca8aSLuca Tettamanti 
48ce3cf821SLuca Tettamanti struct atif_system_params {
49*fda4b25cSLuca Tettamanti 	u16 size;		/* structure size in bytes (includes size field) */
50*fda4b25cSLuca Tettamanti 	u32 valid_mask;		/* valid flags mask */
51*fda4b25cSLuca Tettamanti 	u32 flags;		/* flags */
52*fda4b25cSLuca Tettamanti 	u8 command_code;	/* notify command code */
53*fda4b25cSLuca Tettamanti } __packed;
54*fda4b25cSLuca Tettamanti 
55*fda4b25cSLuca Tettamanti struct atif_sbios_requests {
56*fda4b25cSLuca Tettamanti 	u16 size;		/* structure size in bytes (includes size field) */
57*fda4b25cSLuca Tettamanti 	u32 pending;		/* pending sbios requests */
58*fda4b25cSLuca Tettamanti 	u8 panel_exp_mode;	/* panel expansion mode */
59*fda4b25cSLuca Tettamanti 	u8 thermal_gfx;		/* thermal state: target gfx controller */
60*fda4b25cSLuca Tettamanti 	u8 thermal_state;	/* thermal state: state id (0: exit state, non-0: state) */
61*fda4b25cSLuca Tettamanti 	u8 forced_power_gfx;	/* forced power state: target gfx controller */
62*fda4b25cSLuca Tettamanti 	u8 forced_power_state;	/* forced power state: state id */
63*fda4b25cSLuca Tettamanti 	u8 system_power_src;	/* system power source */
64*fda4b25cSLuca Tettamanti 	u8 backlight_level;	/* panel backlight level (0-255) */
65ce3cf821SLuca Tettamanti } __packed;
66ce3cf821SLuca Tettamanti 
67ce3cf821SLuca Tettamanti #define ATIF_NOTIFY_MASK	0x3
68ce3cf821SLuca Tettamanti #define ATIF_NOTIFY_NONE	0
69ce3cf821SLuca Tettamanti #define ATIF_NOTIFY_81		1
70ce3cf821SLuca Tettamanti #define ATIF_NOTIFY_N		2
71ce3cf821SLuca Tettamanti 
72d7a2952fSAlberto Milone /* Call the ATIF method
73d7a2952fSAlberto Milone  */
7486504672SLuca Tettamanti static union acpi_object *radeon_atif_call(acpi_handle handle, int function,
7586504672SLuca Tettamanti 		struct acpi_buffer *params)
76d7a2952fSAlberto Milone {
77d7a2952fSAlberto Milone 	acpi_status status;
78d7a2952fSAlberto Milone 	union acpi_object atif_arg_elements[2];
79d7a2952fSAlberto Milone 	struct acpi_object_list atif_arg;
80d7a2952fSAlberto Milone 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
81d7a2952fSAlberto Milone 
82d7a2952fSAlberto Milone 	atif_arg.count = 2;
83d7a2952fSAlberto Milone 	atif_arg.pointer = &atif_arg_elements[0];
84d7a2952fSAlberto Milone 
85d7a2952fSAlberto Milone 	atif_arg_elements[0].type = ACPI_TYPE_INTEGER;
8686504672SLuca Tettamanti 	atif_arg_elements[0].integer.value = function;
8786504672SLuca Tettamanti 
8886504672SLuca Tettamanti 	if (params) {
8986504672SLuca Tettamanti 		atif_arg_elements[1].type = ACPI_TYPE_BUFFER;
9086504672SLuca Tettamanti 		atif_arg_elements[1].buffer.length = params->length;
9186504672SLuca Tettamanti 		atif_arg_elements[1].buffer.pointer = params->pointer;
9286504672SLuca Tettamanti 	} else {
9386504672SLuca Tettamanti 		/* We need a second fake parameter */
94d7a2952fSAlberto Milone 		atif_arg_elements[1].type = ACPI_TYPE_INTEGER;
95d7a2952fSAlberto Milone 		atif_arg_elements[1].integer.value = 0;
9686504672SLuca Tettamanti 	}
97d7a2952fSAlberto Milone 
98d7a2952fSAlberto Milone 	status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer);
99d7a2952fSAlberto Milone 
100d7a2952fSAlberto Milone 	/* Fail only if calling the method fails and ATIF is supported */
101d7a2952fSAlberto Milone 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
102bc96f942SJean Delvare 		DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
103bc96f942SJean Delvare 				 acpi_format_exception(status));
104d7a2952fSAlberto Milone 		kfree(buffer.pointer);
10586504672SLuca Tettamanti 		return NULL;
106d7a2952fSAlberto Milone 	}
107d7a2952fSAlberto Milone 
10886504672SLuca Tettamanti 	return buffer.pointer;
109d7a2952fSAlberto Milone }
110d7a2952fSAlberto Milone 
111fd64ca8aSLuca Tettamanti static void radeon_atif_parse_notification(struct radeon_atif_notifications *n, u32 mask)
112fd64ca8aSLuca Tettamanti {
113fd64ca8aSLuca Tettamanti 	n->display_switch = mask & ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED;
114fd64ca8aSLuca Tettamanti 	n->expansion_mode_change = mask & ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED;
115fd64ca8aSLuca Tettamanti 	n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED;
116fd64ca8aSLuca Tettamanti 	n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED;
117fd64ca8aSLuca Tettamanti 	n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED;
118fd64ca8aSLuca Tettamanti 	n->display_conf_change = mask & ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED;
119fd64ca8aSLuca Tettamanti 	n->px_gfx_switch = mask & ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED;
120fd64ca8aSLuca Tettamanti 	n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED;
121fd64ca8aSLuca Tettamanti 	n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED;
122fd64ca8aSLuca Tettamanti }
123fd64ca8aSLuca Tettamanti 
124fd64ca8aSLuca Tettamanti static void radeon_atif_parse_functions(struct radeon_atif_functions *f, u32 mask)
125fd64ca8aSLuca Tettamanti {
126fd64ca8aSLuca Tettamanti 	f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED;
127fd64ca8aSLuca Tettamanti 	f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED;
128fd64ca8aSLuca Tettamanti 	f->select_active_disp = mask & ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED;
129fd64ca8aSLuca Tettamanti 	f->lid_state = mask & ATIF_GET_LID_STATE_SUPPORTED;
130fd64ca8aSLuca Tettamanti 	f->get_tv_standard = mask & ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED;
131fd64ca8aSLuca Tettamanti 	f->set_tv_standard = mask & ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED;
132fd64ca8aSLuca Tettamanti 	f->get_panel_expansion_mode = mask & ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED;
133fd64ca8aSLuca Tettamanti 	f->set_panel_expansion_mode = mask & ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED;
134fd64ca8aSLuca Tettamanti 	f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED;
135fd64ca8aSLuca Tettamanti 	f->graphics_device_types = mask & ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED;
136fd64ca8aSLuca Tettamanti }
137fd64ca8aSLuca Tettamanti 
138fd64ca8aSLuca Tettamanti static int radeon_atif_verify_interface(acpi_handle handle,
139fd64ca8aSLuca Tettamanti 		struct radeon_atif *atif)
140fd64ca8aSLuca Tettamanti {
141fd64ca8aSLuca Tettamanti 	union acpi_object *info;
142fd64ca8aSLuca Tettamanti 	struct atif_verify_interface output;
143fd64ca8aSLuca Tettamanti 	size_t size;
144fd64ca8aSLuca Tettamanti 	int err = 0;
145fd64ca8aSLuca Tettamanti 
146fd64ca8aSLuca Tettamanti 	info = radeon_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL);
147fd64ca8aSLuca Tettamanti 	if (!info)
148fd64ca8aSLuca Tettamanti 		return -EIO;
149fd64ca8aSLuca Tettamanti 
150fd64ca8aSLuca Tettamanti 	memset(&output, 0, sizeof(output));
151fd64ca8aSLuca Tettamanti 
152fd64ca8aSLuca Tettamanti 	size = *(u16 *) info->buffer.pointer;
153fd64ca8aSLuca Tettamanti 	if (size < 12) {
154fd64ca8aSLuca Tettamanti 		DRM_INFO("ATIF buffer is too small: %lu\n", size);
155fd64ca8aSLuca Tettamanti 		err = -EINVAL;
156fd64ca8aSLuca Tettamanti 		goto out;
157fd64ca8aSLuca Tettamanti 	}
158fd64ca8aSLuca Tettamanti 	size = min(sizeof(output), size);
159fd64ca8aSLuca Tettamanti 
160fd64ca8aSLuca Tettamanti 	memcpy(&output, info->buffer.pointer, size);
161fd64ca8aSLuca Tettamanti 
162fd64ca8aSLuca Tettamanti 	/* TODO: check version? */
163fd64ca8aSLuca Tettamanti 	DRM_DEBUG_DRIVER("ATIF version %u\n", output.version);
164fd64ca8aSLuca Tettamanti 
165fd64ca8aSLuca Tettamanti 	radeon_atif_parse_notification(&atif->notifications, output.notification_mask);
166fd64ca8aSLuca Tettamanti 	radeon_atif_parse_functions(&atif->functions, output.function_bits);
167fd64ca8aSLuca Tettamanti 
168fd64ca8aSLuca Tettamanti out:
169fd64ca8aSLuca Tettamanti 	kfree(info);
170fd64ca8aSLuca Tettamanti 	return err;
171fd64ca8aSLuca Tettamanti }
172fd64ca8aSLuca Tettamanti 
173ce3cf821SLuca Tettamanti static int radeon_atif_get_notification_params(acpi_handle handle,
174ce3cf821SLuca Tettamanti 		struct radeon_atif_notification_cfg *n)
175ce3cf821SLuca Tettamanti {
176ce3cf821SLuca Tettamanti 	union acpi_object *info;
177ce3cf821SLuca Tettamanti 	struct atif_system_params params;
178ce3cf821SLuca Tettamanti 	size_t size;
179ce3cf821SLuca Tettamanti 	int err = 0;
180ce3cf821SLuca Tettamanti 
181ce3cf821SLuca Tettamanti 	info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL);
182ce3cf821SLuca Tettamanti 	if (!info) {
183ce3cf821SLuca Tettamanti 		err = -EIO;
184ce3cf821SLuca Tettamanti 		goto out;
185ce3cf821SLuca Tettamanti 	}
186ce3cf821SLuca Tettamanti 
187ce3cf821SLuca Tettamanti 	size = *(u16 *) info->buffer.pointer;
188ce3cf821SLuca Tettamanti 	if (size < 10) {
189ce3cf821SLuca Tettamanti 		err = -EINVAL;
190ce3cf821SLuca Tettamanti 		goto out;
191ce3cf821SLuca Tettamanti 	}
192ce3cf821SLuca Tettamanti 
193ce3cf821SLuca Tettamanti 	memset(&params, 0, sizeof(params));
194ce3cf821SLuca Tettamanti 	size = min(sizeof(params), size);
195ce3cf821SLuca Tettamanti 	memcpy(&params, info->buffer.pointer, size);
196ce3cf821SLuca Tettamanti 
197*fda4b25cSLuca Tettamanti 	DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n",
198*fda4b25cSLuca Tettamanti 			params.flags, params.valid_mask);
199ce3cf821SLuca Tettamanti 	params.flags = params.flags & params.valid_mask;
200ce3cf821SLuca Tettamanti 
201ce3cf821SLuca Tettamanti 	if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) {
202ce3cf821SLuca Tettamanti 		n->enabled = false;
203ce3cf821SLuca Tettamanti 		n->command_code = 0;
204ce3cf821SLuca Tettamanti 	} else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) {
205ce3cf821SLuca Tettamanti 		n->enabled = true;
206ce3cf821SLuca Tettamanti 		n->command_code = 0x81;
207ce3cf821SLuca Tettamanti 	} else {
208ce3cf821SLuca Tettamanti 		if (size < 11) {
209ce3cf821SLuca Tettamanti 			err = -EINVAL;
210ce3cf821SLuca Tettamanti 			goto out;
211ce3cf821SLuca Tettamanti 		}
212ce3cf821SLuca Tettamanti 		n->enabled = true;
213ce3cf821SLuca Tettamanti 		n->command_code = params.command_code;
214ce3cf821SLuca Tettamanti 	}
215ce3cf821SLuca Tettamanti 
216ce3cf821SLuca Tettamanti out:
217*fda4b25cSLuca Tettamanti 	DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n",
218*fda4b25cSLuca Tettamanti 			(n->enabled ? "enabled" : "disabled"),
219*fda4b25cSLuca Tettamanti 			n->command_code);
220ce3cf821SLuca Tettamanti 	kfree(info);
221ce3cf821SLuca Tettamanti 	return err;
222ce3cf821SLuca Tettamanti }
223ce3cf821SLuca Tettamanti 
224*fda4b25cSLuca Tettamanti static int radeon_atif_get_sbios_requests(acpi_handle handle,
225*fda4b25cSLuca Tettamanti 		struct atif_sbios_requests *req)
226*fda4b25cSLuca Tettamanti {
227*fda4b25cSLuca Tettamanti 	union acpi_object *info;
228*fda4b25cSLuca Tettamanti 	size_t size;
229*fda4b25cSLuca Tettamanti 	int count = 0;
230*fda4b25cSLuca Tettamanti 
231*fda4b25cSLuca Tettamanti 	info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, NULL);
232*fda4b25cSLuca Tettamanti 	if (!info)
233*fda4b25cSLuca Tettamanti 		return -EIO;
234*fda4b25cSLuca Tettamanti 
235*fda4b25cSLuca Tettamanti 	size = *(u16 *)info->buffer.pointer;
236*fda4b25cSLuca Tettamanti 	if (size < 0xd) {
237*fda4b25cSLuca Tettamanti 		count = -EINVAL;
238*fda4b25cSLuca Tettamanti 		goto out;
239*fda4b25cSLuca Tettamanti 	}
240*fda4b25cSLuca Tettamanti 	memset(req, 0, sizeof(*req));
241*fda4b25cSLuca Tettamanti 
242*fda4b25cSLuca Tettamanti 	size = min(sizeof(*req), size);
243*fda4b25cSLuca Tettamanti 	memcpy(req, info->buffer.pointer, size);
244*fda4b25cSLuca Tettamanti 	DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending);
245*fda4b25cSLuca Tettamanti 
246*fda4b25cSLuca Tettamanti 	count = hweight32(req->pending);
247*fda4b25cSLuca Tettamanti 
248*fda4b25cSLuca Tettamanti out:
249*fda4b25cSLuca Tettamanti 	kfree(info);
250*fda4b25cSLuca Tettamanti 	return count;
251*fda4b25cSLuca Tettamanti }
252*fda4b25cSLuca Tettamanti 
253*fda4b25cSLuca Tettamanti int radeon_atif_handler(struct radeon_device *rdev,
254*fda4b25cSLuca Tettamanti 		struct acpi_bus_event *event)
255*fda4b25cSLuca Tettamanti {
256*fda4b25cSLuca Tettamanti 	struct radeon_atif *atif = &rdev->atif;
257*fda4b25cSLuca Tettamanti 	struct atif_sbios_requests req;
258*fda4b25cSLuca Tettamanti 	acpi_handle handle;
259*fda4b25cSLuca Tettamanti 	int count;
260*fda4b25cSLuca Tettamanti 
261*fda4b25cSLuca Tettamanti 	DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n",
262*fda4b25cSLuca Tettamanti 			event->device_class, event->type);
263*fda4b25cSLuca Tettamanti 
264*fda4b25cSLuca Tettamanti 	if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
265*fda4b25cSLuca Tettamanti 		return NOTIFY_DONE;
266*fda4b25cSLuca Tettamanti 
267*fda4b25cSLuca Tettamanti 	if (!atif->notification_cfg.enabled ||
268*fda4b25cSLuca Tettamanti 			event->type != atif->notification_cfg.command_code)
269*fda4b25cSLuca Tettamanti 		/* Not our event */
270*fda4b25cSLuca Tettamanti 		return NOTIFY_DONE;
271*fda4b25cSLuca Tettamanti 
272*fda4b25cSLuca Tettamanti 	/* Check pending SBIOS requests */
273*fda4b25cSLuca Tettamanti 	handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev);
274*fda4b25cSLuca Tettamanti 	count = radeon_atif_get_sbios_requests(handle, &req);
275*fda4b25cSLuca Tettamanti 
276*fda4b25cSLuca Tettamanti 	if (count <= 0)
277*fda4b25cSLuca Tettamanti 		return NOTIFY_DONE;
278*fda4b25cSLuca Tettamanti 
279*fda4b25cSLuca Tettamanti 	DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count);
280*fda4b25cSLuca Tettamanti 
281*fda4b25cSLuca Tettamanti 	if (req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) {
282*fda4b25cSLuca Tettamanti 		struct radeon_encoder *enc = atif->backlight_ctl;
283*fda4b25cSLuca Tettamanti 
284*fda4b25cSLuca Tettamanti 		if (enc) {
285*fda4b25cSLuca Tettamanti 			struct radeon_encoder_atom_dig *dig = enc->enc_priv;
286*fda4b25cSLuca Tettamanti 			dig->backlight_level = req.backlight_level;
287*fda4b25cSLuca Tettamanti 
288*fda4b25cSLuca Tettamanti 			DRM_DEBUG_DRIVER("Changing brightness to %d\n",
289*fda4b25cSLuca Tettamanti 					req.backlight_level);
290*fda4b25cSLuca Tettamanti 
291*fda4b25cSLuca Tettamanti 			atombios_set_panel_brightness(enc);
292*fda4b25cSLuca Tettamanti 
293*fda4b25cSLuca Tettamanti 			backlight_force_update(dig->bl_dev,
294*fda4b25cSLuca Tettamanti 					BACKLIGHT_UPDATE_HOTKEY);
295*fda4b25cSLuca Tettamanti 		}
296*fda4b25cSLuca Tettamanti 	}
297*fda4b25cSLuca Tettamanti 	/* TODO: check other events */
298*fda4b25cSLuca Tettamanti 
299*fda4b25cSLuca Tettamanti 	return NOTIFY_OK;
300*fda4b25cSLuca Tettamanti }
301*fda4b25cSLuca Tettamanti 
302d7a2952fSAlberto Milone /* Call all ACPI methods here */
303d7a2952fSAlberto Milone int radeon_acpi_init(struct radeon_device *rdev)
304d7a2952fSAlberto Milone {
305d7a2952fSAlberto Milone 	acpi_handle handle;
306ce3cf821SLuca Tettamanti 	struct radeon_atif *atif = &rdev->atif;
307fd64ca8aSLuca Tettamanti 	int ret;
308d7a2952fSAlberto Milone 
309d7a2952fSAlberto Milone 	/* Get the device handle */
310d7a2952fSAlberto Milone 	handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev);
311d7a2952fSAlberto Milone 
31248cc9b2cSJean Delvare 	/* No need to proceed if we're sure that ATIF is not supported */
31348cc9b2cSJean Delvare 	if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle)
31448cc9b2cSJean Delvare 		return 0;
31548cc9b2cSJean Delvare 
316d7a2952fSAlberto Milone 	/* Call the ATIF method */
317ce3cf821SLuca Tettamanti 	ret = radeon_atif_verify_interface(handle, atif);
318ce3cf821SLuca Tettamanti 	if (ret) {
319fd64ca8aSLuca Tettamanti 		DRM_DEBUG_DRIVER("Call to verify_interface failed: %d\n", ret);
320ce3cf821SLuca Tettamanti 		goto out;
321ce3cf821SLuca Tettamanti 	}
322d7a2952fSAlberto Milone 
323*fda4b25cSLuca Tettamanti 	if (atif->notifications.brightness_change) {
324*fda4b25cSLuca Tettamanti 		struct drm_encoder *tmp;
325*fda4b25cSLuca Tettamanti 		struct radeon_encoder *target = NULL;
326*fda4b25cSLuca Tettamanti 
327*fda4b25cSLuca Tettamanti 		/* Find the encoder controlling the brightness */
328*fda4b25cSLuca Tettamanti 		list_for_each_entry(tmp, &rdev->ddev->mode_config.encoder_list,
329*fda4b25cSLuca Tettamanti 				head) {
330*fda4b25cSLuca Tettamanti 			struct radeon_encoder *enc = to_radeon_encoder(tmp);
331*fda4b25cSLuca Tettamanti 			struct radeon_encoder_atom_dig *dig = enc->enc_priv;
332*fda4b25cSLuca Tettamanti 
333*fda4b25cSLuca Tettamanti 			if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
334*fda4b25cSLuca Tettamanti 					dig->bl_dev != NULL) {
335*fda4b25cSLuca Tettamanti 				target = enc;
336*fda4b25cSLuca Tettamanti 				break;
337*fda4b25cSLuca Tettamanti 			}
338*fda4b25cSLuca Tettamanti 		}
339*fda4b25cSLuca Tettamanti 
340*fda4b25cSLuca Tettamanti 		atif->backlight_ctl = target;
341*fda4b25cSLuca Tettamanti 		if (!target) {
342*fda4b25cSLuca Tettamanti 			/* Brightness change notification is enabled, but we
343*fda4b25cSLuca Tettamanti 			 * didn't find a backlight controller, this should
344*fda4b25cSLuca Tettamanti 			 * never happen.
345*fda4b25cSLuca Tettamanti 			 */
346*fda4b25cSLuca Tettamanti 			DRM_ERROR("Cannot find a backlight controller\n");
347*fda4b25cSLuca Tettamanti 		}
348*fda4b25cSLuca Tettamanti 	}
349*fda4b25cSLuca Tettamanti 
350ce3cf821SLuca Tettamanti 	if (atif->functions.sbios_requests && !atif->functions.system_params) {
351ce3cf821SLuca Tettamanti 		/* XXX check this workraround, if sbios request function is
352ce3cf821SLuca Tettamanti 		 * present we have to see how it's configured in the system
353ce3cf821SLuca Tettamanti 		 * params
354ce3cf821SLuca Tettamanti 		 */
355ce3cf821SLuca Tettamanti 		atif->functions.system_params = true;
356ce3cf821SLuca Tettamanti 	}
357ce3cf821SLuca Tettamanti 
358ce3cf821SLuca Tettamanti 	if (atif->functions.system_params) {
359ce3cf821SLuca Tettamanti 		ret = radeon_atif_get_notification_params(handle,
360ce3cf821SLuca Tettamanti 				&atif->notification_cfg);
361ce3cf821SLuca Tettamanti 		if (ret) {
362ce3cf821SLuca Tettamanti 			DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n",
363ce3cf821SLuca Tettamanti 					ret);
364ce3cf821SLuca Tettamanti 			/* Disable notification */
365ce3cf821SLuca Tettamanti 			atif->notification_cfg.enabled = false;
366ce3cf821SLuca Tettamanti 		}
367ce3cf821SLuca Tettamanti 	}
368ce3cf821SLuca Tettamanti 
369ce3cf821SLuca Tettamanti out:
37086504672SLuca Tettamanti 	return ret;
371d7a2952fSAlberto Milone }
372d7a2952fSAlberto Milone 
373