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