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