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