1 /*
2  * Copyright (c) 2010 Red Hat Inc.
3  * Author : Dave Airlie <airlied@redhat.com>
4  *
5  * Licensed under GPLv2
6  *
7  * ATPX support for both Intel/ATI
8  */
9 #include <linux/vga_switcheroo.h>
10 #include <linux/slab.h>
11 #include <linux/acpi.h>
12 #include <linux/pci.h>
13 #include <linux/delay.h>
14 
15 #include "amd_acpi.h"
16 
17 #define AMDGPU_PX_QUIRK_FORCE_ATPX  (1 << 0)
18 
19 struct amdgpu_px_quirk {
20 	u32 chip_vendor;
21 	u32 chip_device;
22 	u32 subsys_vendor;
23 	u32 subsys_device;
24 	u32 px_quirk_flags;
25 };
26 
27 struct amdgpu_atpx_functions {
28 	bool px_params;
29 	bool power_cntl;
30 	bool disp_mux_cntl;
31 	bool i2c_mux_cntl;
32 	bool switch_start;
33 	bool switch_end;
34 	bool disp_connectors_mapping;
35 	bool disp_detection_ports;
36 };
37 
38 struct amdgpu_atpx {
39 	acpi_handle handle;
40 	struct amdgpu_atpx_functions functions;
41 	bool is_hybrid;
42 	bool dgpu_req_power_for_displays;
43 };
44 
45 static struct amdgpu_atpx_priv {
46 	bool atpx_detected;
47 	bool bridge_pm_usable;
48 	unsigned int quirks;
49 	/* handle for device - and atpx */
50 	acpi_handle dhandle;
51 	acpi_handle other_handle;
52 	struct amdgpu_atpx atpx;
53 } amdgpu_atpx_priv;
54 
55 struct atpx_verify_interface {
56 	u16 size;		/* structure size in bytes (includes size field) */
57 	u16 version;		/* version */
58 	u32 function_bits;	/* supported functions bit vector */
59 } __packed;
60 
61 struct atpx_px_params {
62 	u16 size;		/* structure size in bytes (includes size field) */
63 	u32 valid_flags;	/* which flags are valid */
64 	u32 flags;		/* flags */
65 } __packed;
66 
67 struct atpx_power_control {
68 	u16 size;
69 	u8 dgpu_state;
70 } __packed;
71 
72 struct atpx_mux {
73 	u16 size;
74 	u16 mux;
75 } __packed;
76 
77 bool amdgpu_has_atpx(void) {
78 	return amdgpu_atpx_priv.atpx_detected;
79 }
80 
81 bool amdgpu_has_atpx_dgpu_power_cntl(void) {
82 	return amdgpu_atpx_priv.atpx.functions.power_cntl;
83 }
84 
85 bool amdgpu_is_atpx_hybrid(void) {
86 	return amdgpu_atpx_priv.atpx.is_hybrid;
87 }
88 
89 bool amdgpu_atpx_dgpu_req_power_for_displays(void) {
90 	return amdgpu_atpx_priv.atpx.dgpu_req_power_for_displays;
91 }
92 
93 #if defined(CONFIG_ACPI)
94 void *amdgpu_atpx_get_dhandle(void) {
95 	return amdgpu_atpx_priv.dhandle;
96 }
97 #endif
98 
99 /**
100  * amdgpu_atpx_call - call an ATPX method
101  *
102  * @handle: acpi handle
103  * @function: the ATPX function to execute
104  * @params: ATPX function params
105  *
106  * Executes the requested ATPX function (all asics).
107  * Returns a pointer to the acpi output buffer.
108  */
109 static union acpi_object *amdgpu_atpx_call(acpi_handle handle, int function,
110 					   struct acpi_buffer *params)
111 {
112 	acpi_status status;
113 	union acpi_object atpx_arg_elements[2];
114 	struct acpi_object_list atpx_arg;
115 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
116 
117 	atpx_arg.count = 2;
118 	atpx_arg.pointer = &atpx_arg_elements[0];
119 
120 	atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
121 	atpx_arg_elements[0].integer.value = function;
122 
123 	if (params) {
124 		atpx_arg_elements[1].type = ACPI_TYPE_BUFFER;
125 		atpx_arg_elements[1].buffer.length = params->length;
126 		atpx_arg_elements[1].buffer.pointer = params->pointer;
127 	} else {
128 		/* We need a second fake parameter */
129 		atpx_arg_elements[1].type = ACPI_TYPE_INTEGER;
130 		atpx_arg_elements[1].integer.value = 0;
131 	}
132 
133 	status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
134 
135 	/* Fail only if calling the method fails and ATPX is supported */
136 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
137 		printk("failed to evaluate ATPX got %s\n",
138 		       acpi_format_exception(status));
139 		kfree(buffer.pointer);
140 		return NULL;
141 	}
142 
143 	return buffer.pointer;
144 }
145 
146 /**
147  * amdgpu_atpx_parse_functions - parse supported functions
148  *
149  * @f: supported functions struct
150  * @mask: supported functions mask from ATPX
151  *
152  * Use the supported functions mask from ATPX function
153  * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions
154  * are supported (all asics).
155  */
156 static void amdgpu_atpx_parse_functions(struct amdgpu_atpx_functions *f, u32 mask)
157 {
158 	f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED;
159 	f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED;
160 	f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED;
161 	f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED;
162 	f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED;
163 	f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED;
164 	f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED;
165 	f->disp_detection_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED;
166 }
167 
168 /**
169  * amdgpu_atpx_validate_functions - validate ATPX functions
170  *
171  * @atpx: amdgpu atpx struct
172  *
173  * Validate that required functions are enabled (all asics).
174  * returns 0 on success, error on failure.
175  */
176 static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
177 {
178 	u32 valid_bits = 0;
179 
180 	if (atpx->functions.px_params) {
181 		union acpi_object *info;
182 		struct atpx_px_params output;
183 		size_t size;
184 
185 		info = amdgpu_atpx_call(atpx->handle, ATPX_FUNCTION_GET_PX_PARAMETERS, NULL);
186 		if (!info)
187 			return -EIO;
188 
189 		memset(&output, 0, sizeof(output));
190 
191 		size = *(u16 *) info->buffer.pointer;
192 		if (size < 10) {
193 			printk("ATPX buffer is too small: %zu\n", size);
194 			kfree(info);
195 			return -EINVAL;
196 		}
197 		size = min(sizeof(output), size);
198 
199 		memcpy(&output, info->buffer.pointer, size);
200 
201 		valid_bits = output.flags & output.valid_flags;
202 
203 		kfree(info);
204 	}
205 
206 	/* if separate mux flag is set, mux controls are required */
207 	if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
208 		atpx->functions.i2c_mux_cntl = true;
209 		atpx->functions.disp_mux_cntl = true;
210 	}
211 	/* if any outputs are muxed, mux controls are required */
212 	if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
213 			  ATPX_TV_SIGNAL_MUXED |
214 			  ATPX_DFP_SIGNAL_MUXED))
215 		atpx->functions.disp_mux_cntl = true;
216 
217 
218 	/* some bioses set these bits rather than flagging power_cntl as supported */
219 	if (valid_bits & (ATPX_DYNAMIC_PX_SUPPORTED |
220 			  ATPX_DYNAMIC_DGPU_POWER_OFF_SUPPORTED))
221 		atpx->functions.power_cntl = true;
222 
223 	atpx->is_hybrid = false;
224 	if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
225 		if (amdgpu_atpx_priv.quirks & AMDGPU_PX_QUIRK_FORCE_ATPX) {
226 			printk("ATPX Hybrid Graphics, forcing to ATPX\n");
227 			atpx->functions.power_cntl = true;
228 			atpx->is_hybrid = false;
229 		} else {
230 			printk("ATPX Hybrid Graphics\n");
231 			/*
232 			 * Disable legacy PM methods only when pcie port PM is usable,
233 			 * otherwise the device might fail to power off or power on.
234 			 */
235 			atpx->functions.power_cntl = !amdgpu_atpx_priv.bridge_pm_usable;
236 			atpx->is_hybrid = true;
237 		}
238 	}
239 
240 	atpx->dgpu_req_power_for_displays = false;
241 	if (valid_bits & ATPX_DGPU_REQ_POWER_FOR_DISPLAYS)
242 		atpx->dgpu_req_power_for_displays = true;
243 
244 	return 0;
245 }
246 
247 /**
248  * amdgpu_atpx_verify_interface - verify ATPX
249  *
250  * @atpx: amdgpu atpx struct
251  *
252  * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
253  * to initialize ATPX and determine what features are supported
254  * (all asics).
255  * returns 0 on success, error on failure.
256  */
257 static int amdgpu_atpx_verify_interface(struct amdgpu_atpx *atpx)
258 {
259 	union acpi_object *info;
260 	struct atpx_verify_interface output;
261 	size_t size;
262 	int err = 0;
263 
264 	info = amdgpu_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL);
265 	if (!info)
266 		return -EIO;
267 
268 	memset(&output, 0, sizeof(output));
269 
270 	size = *(u16 *) info->buffer.pointer;
271 	if (size < 8) {
272 		printk("ATPX buffer is too small: %zu\n", size);
273 		err = -EINVAL;
274 		goto out;
275 	}
276 	size = min(sizeof(output), size);
277 
278 	memcpy(&output, info->buffer.pointer, size);
279 
280 	/* TODO: check version? */
281 	printk("ATPX version %u, functions 0x%08x\n",
282 	       output.version, output.function_bits);
283 
284 	amdgpu_atpx_parse_functions(&atpx->functions, output.function_bits);
285 
286 out:
287 	kfree(info);
288 	return err;
289 }
290 
291 /**
292  * amdgpu_atpx_set_discrete_state - power up/down discrete GPU
293  *
294  * @atpx: atpx info struct
295  * @state: discrete GPU state (0 = power down, 1 = power up)
296  *
297  * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to
298  * power down/up the discrete GPU (all asics).
299  * Returns 0 on success, error on failure.
300  */
301 static int amdgpu_atpx_set_discrete_state(struct amdgpu_atpx *atpx, u8 state)
302 {
303 	struct acpi_buffer params;
304 	union acpi_object *info;
305 	struct atpx_power_control input;
306 
307 	if (atpx->functions.power_cntl) {
308 		input.size = 3;
309 		input.dgpu_state = state;
310 		params.length = input.size;
311 		params.pointer = &input;
312 		info = amdgpu_atpx_call(atpx->handle,
313 					ATPX_FUNCTION_POWER_CONTROL,
314 					&params);
315 		if (!info)
316 			return -EIO;
317 		kfree(info);
318 
319 		/* 200ms delay is required after off */
320 		if (state == 0)
321 			msleep(200);
322 	}
323 	return 0;
324 }
325 
326 /**
327  * amdgpu_atpx_switch_disp_mux - switch display mux
328  *
329  * @atpx: atpx info struct
330  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
331  *
332  * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to
333  * switch the display mux between the discrete GPU and integrated GPU
334  * (all asics).
335  * Returns 0 on success, error on failure.
336  */
337 static int amdgpu_atpx_switch_disp_mux(struct amdgpu_atpx *atpx, u16 mux_id)
338 {
339 	struct acpi_buffer params;
340 	union acpi_object *info;
341 	struct atpx_mux input;
342 
343 	if (atpx->functions.disp_mux_cntl) {
344 		input.size = 4;
345 		input.mux = mux_id;
346 		params.length = input.size;
347 		params.pointer = &input;
348 		info = amdgpu_atpx_call(atpx->handle,
349 					ATPX_FUNCTION_DISPLAY_MUX_CONTROL,
350 					&params);
351 		if (!info)
352 			return -EIO;
353 		kfree(info);
354 	}
355 	return 0;
356 }
357 
358 /**
359  * amdgpu_atpx_switch_i2c_mux - switch i2c/hpd mux
360  *
361  * @atpx: atpx info struct
362  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
363  *
364  * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to
365  * switch the i2c/hpd mux between the discrete GPU and integrated GPU
366  * (all asics).
367  * Returns 0 on success, error on failure.
368  */
369 static int amdgpu_atpx_switch_i2c_mux(struct amdgpu_atpx *atpx, u16 mux_id)
370 {
371 	struct acpi_buffer params;
372 	union acpi_object *info;
373 	struct atpx_mux input;
374 
375 	if (atpx->functions.i2c_mux_cntl) {
376 		input.size = 4;
377 		input.mux = mux_id;
378 		params.length = input.size;
379 		params.pointer = &input;
380 		info = amdgpu_atpx_call(atpx->handle,
381 					ATPX_FUNCTION_I2C_MUX_CONTROL,
382 					&params);
383 		if (!info)
384 			return -EIO;
385 		kfree(info);
386 	}
387 	return 0;
388 }
389 
390 /**
391  * amdgpu_atpx_switch_start - notify the sbios of a GPU switch
392  *
393  * @atpx: atpx info struct
394  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
395  *
396  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX
397  * function to notify the sbios that a switch between the discrete GPU and
398  * integrated GPU has begun (all asics).
399  * Returns 0 on success, error on failure.
400  */
401 static int amdgpu_atpx_switch_start(struct amdgpu_atpx *atpx, u16 mux_id)
402 {
403 	struct acpi_buffer params;
404 	union acpi_object *info;
405 	struct atpx_mux input;
406 
407 	if (atpx->functions.switch_start) {
408 		input.size = 4;
409 		input.mux = mux_id;
410 		params.length = input.size;
411 		params.pointer = &input;
412 		info = amdgpu_atpx_call(atpx->handle,
413 					ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION,
414 					&params);
415 		if (!info)
416 			return -EIO;
417 		kfree(info);
418 	}
419 	return 0;
420 }
421 
422 /**
423  * amdgpu_atpx_switch_end - notify the sbios of a GPU switch
424  *
425  * @atpx: atpx info struct
426  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
427  *
428  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX
429  * function to notify the sbios that a switch between the discrete GPU and
430  * integrated GPU has ended (all asics).
431  * Returns 0 on success, error on failure.
432  */
433 static int amdgpu_atpx_switch_end(struct amdgpu_atpx *atpx, u16 mux_id)
434 {
435 	struct acpi_buffer params;
436 	union acpi_object *info;
437 	struct atpx_mux input;
438 
439 	if (atpx->functions.switch_end) {
440 		input.size = 4;
441 		input.mux = mux_id;
442 		params.length = input.size;
443 		params.pointer = &input;
444 		info = amdgpu_atpx_call(atpx->handle,
445 					ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION,
446 					&params);
447 		if (!info)
448 			return -EIO;
449 		kfree(info);
450 	}
451 	return 0;
452 }
453 
454 /**
455  * amdgpu_atpx_switchto - switch to the requested GPU
456  *
457  * @id: GPU to switch to
458  *
459  * Execute the necessary ATPX functions to switch between the discrete GPU and
460  * integrated GPU (all asics).
461  * Returns 0 on success, error on failure.
462  */
463 static int amdgpu_atpx_switchto(enum vga_switcheroo_client_id id)
464 {
465 	u16 gpu_id;
466 
467 	if (id == VGA_SWITCHEROO_IGD)
468 		gpu_id = ATPX_INTEGRATED_GPU;
469 	else
470 		gpu_id = ATPX_DISCRETE_GPU;
471 
472 	amdgpu_atpx_switch_start(&amdgpu_atpx_priv.atpx, gpu_id);
473 	amdgpu_atpx_switch_disp_mux(&amdgpu_atpx_priv.atpx, gpu_id);
474 	amdgpu_atpx_switch_i2c_mux(&amdgpu_atpx_priv.atpx, gpu_id);
475 	amdgpu_atpx_switch_end(&amdgpu_atpx_priv.atpx, gpu_id);
476 
477 	return 0;
478 }
479 
480 /**
481  * amdgpu_atpx_power_state - power down/up the requested GPU
482  *
483  * @id: GPU to power down/up
484  * @state: requested power state (0 = off, 1 = on)
485  *
486  * Execute the necessary ATPX function to power down/up the discrete GPU
487  * (all asics).
488  * Returns 0 on success, error on failure.
489  */
490 static int amdgpu_atpx_power_state(enum vga_switcheroo_client_id id,
491 				   enum vga_switcheroo_state state)
492 {
493 	/* on w500 ACPI can't change intel gpu state */
494 	if (id == VGA_SWITCHEROO_IGD)
495 		return 0;
496 
497 	amdgpu_atpx_set_discrete_state(&amdgpu_atpx_priv.atpx, state);
498 	return 0;
499 }
500 
501 /**
502  * amdgpu_atpx_pci_probe_handle - look up the ATPX handle
503  *
504  * @pdev: pci device
505  *
506  * Look up the ATPX handles (all asics).
507  * Returns true if the handles are found, false if not.
508  */
509 static bool amdgpu_atpx_pci_probe_handle(struct pci_dev *pdev)
510 {
511 	acpi_handle dhandle, atpx_handle;
512 	acpi_status status;
513 
514 	dhandle = ACPI_HANDLE(&pdev->dev);
515 	if (!dhandle)
516 		return false;
517 
518 	status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
519 	if (ACPI_FAILURE(status)) {
520 		amdgpu_atpx_priv.other_handle = dhandle;
521 		return false;
522 	}
523 	amdgpu_atpx_priv.dhandle = dhandle;
524 	amdgpu_atpx_priv.atpx.handle = atpx_handle;
525 	return true;
526 }
527 
528 /**
529  * amdgpu_atpx_init - verify the ATPX interface
530  *
531  * Verify the ATPX interface (all asics).
532  * Returns 0 on success, error on failure.
533  */
534 static int amdgpu_atpx_init(void)
535 {
536 	int r;
537 
538 	/* set up the ATPX handle */
539 	r = amdgpu_atpx_verify_interface(&amdgpu_atpx_priv.atpx);
540 	if (r)
541 		return r;
542 
543 	/* validate the atpx setup */
544 	r = amdgpu_atpx_validate(&amdgpu_atpx_priv.atpx);
545 	if (r)
546 		return r;
547 
548 	return 0;
549 }
550 
551 /**
552  * amdgpu_atpx_get_client_id - get the client id
553  *
554  * @pdev: pci device
555  *
556  * look up whether we are the integrated or discrete GPU (all asics).
557  * Returns the client id.
558  */
559 static enum vga_switcheroo_client_id amdgpu_atpx_get_client_id(struct pci_dev *pdev)
560 {
561 	if (amdgpu_atpx_priv.dhandle == ACPI_HANDLE(&pdev->dev))
562 		return VGA_SWITCHEROO_IGD;
563 	else
564 		return VGA_SWITCHEROO_DIS;
565 }
566 
567 static const struct vga_switcheroo_handler amdgpu_atpx_handler = {
568 	.switchto = amdgpu_atpx_switchto,
569 	.power_state = amdgpu_atpx_power_state,
570 	.get_client_id = amdgpu_atpx_get_client_id,
571 };
572 
573 static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
574 	/* HG _PR3 doesn't seem to work on this A+A weston board */
575 	{ 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },
576 	{ 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
577 	{ 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
578 	{ 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
579 	{ 0, 0, 0, 0, 0 },
580 };
581 
582 static void amdgpu_atpx_get_quirks(struct pci_dev *pdev)
583 {
584 	const struct amdgpu_px_quirk *p = amdgpu_px_quirk_list;
585 
586 	/* Apply PX quirks */
587 	while (p && p->chip_device != 0) {
588 		if (pdev->vendor == p->chip_vendor &&
589 		    pdev->device == p->chip_device &&
590 		    pdev->subsystem_vendor == p->subsys_vendor &&
591 		    pdev->subsystem_device == p->subsys_device) {
592 			amdgpu_atpx_priv.quirks |= p->px_quirk_flags;
593 			break;
594 		}
595 		++p;
596 	}
597 }
598 
599 /**
600  * amdgpu_atpx_detect - detect whether we have PX
601  *
602  * Check if we have a PX system (all asics).
603  * Returns true if we have a PX system, false if not.
604  */
605 static bool amdgpu_atpx_detect(void)
606 {
607 	char acpi_method_name[255] = { 0 };
608 	struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
609 	struct pci_dev *pdev = NULL;
610 	bool has_atpx = false;
611 	int vga_count = 0;
612 	bool d3_supported = false;
613 	struct pci_dev *parent_pdev;
614 
615 	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
616 		vga_count++;
617 
618 		has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true);
619 
620 		parent_pdev = pci_upstream_bridge(pdev);
621 		d3_supported |= parent_pdev && parent_pdev->bridge_d3;
622 		amdgpu_atpx_get_quirks(pdev);
623 	}
624 
625 	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
626 		vga_count++;
627 
628 		has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true);
629 
630 		parent_pdev = pci_upstream_bridge(pdev);
631 		d3_supported |= parent_pdev && parent_pdev->bridge_d3;
632 		amdgpu_atpx_get_quirks(pdev);
633 	}
634 
635 	if (has_atpx && vga_count == 2) {
636 		acpi_get_name(amdgpu_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
637 		pr_info("vga_switcheroo: detected switching method %s handle\n",
638 			acpi_method_name);
639 		amdgpu_atpx_priv.atpx_detected = true;
640 		amdgpu_atpx_priv.bridge_pm_usable = d3_supported;
641 		amdgpu_atpx_init();
642 		return true;
643 	}
644 	return false;
645 }
646 
647 /**
648  * amdgpu_register_atpx_handler - register with vga_switcheroo
649  *
650  * Register the PX callbacks with vga_switcheroo (all asics).
651  */
652 void amdgpu_register_atpx_handler(void)
653 {
654 	bool r;
655 	enum vga_switcheroo_handler_flags_t handler_flags = 0;
656 
657 	/* detect if we have any ATPX + 2 VGA in the system */
658 	r = amdgpu_atpx_detect();
659 	if (!r)
660 		return;
661 
662 	vga_switcheroo_register_handler(&amdgpu_atpx_handler, handler_flags);
663 }
664 
665 /**
666  * amdgpu_unregister_atpx_handler - unregister with vga_switcheroo
667  *
668  * Unregister the PX callbacks with vga_switcheroo (all asics).
669  */
670 void amdgpu_unregister_atpx_handler(void)
671 {
672 	vga_switcheroo_unregister_handler();
673 }
674