2 * Copyright (c) 2010 Red Hat Inc.
3 * Author : Dave Airlie <airlied@redhat.com>
7 * ATPX support for both Intel/ATI
9 #include <linux/vga_switcheroo.h>
10 #include <linux/slab.h>
11 #include <acpi/acpi.h>
12 #include <acpi/acpi_bus.h>
13 #include <linux/pci.h>
15 #include "radeon_acpi.h"
17 struct radeon_atpx_functions
{
24 bool disp_connectors_mapping
;
25 bool disp_detetion_ports
;
30 struct radeon_atpx_functions functions
;
33 static struct radeon_atpx_priv
{
35 /* handle for device - and atpx */
37 acpi_handle other_handle
;
38 struct radeon_atpx atpx
;
41 struct atpx_verify_interface
{
42 u16 size
; /* structure size in bytes (includes size field) */
43 u16 version
; /* version */
44 u32 function_bits
; /* supported functions bit vector */
47 struct atpx_px_params
{
48 u16 size
; /* structure size in bytes (includes size field) */
49 u32 valid_flags
; /* which flags are valid */
50 u32 flags
; /* flags */
53 struct atpx_power_control
{
64 * radeon_atpx_call - call an ATPX method
66 * @handle: acpi handle
67 * @function: the ATPX function to execute
68 * @params: ATPX function params
70 * Executes the requested ATPX function (all asics).
71 * Returns a pointer to the acpi output buffer.
73 static union acpi_object
*radeon_atpx_call(acpi_handle handle
, int function
,
74 struct acpi_buffer
*params
)
77 union acpi_object atpx_arg_elements
[2];
78 struct acpi_object_list atpx_arg
;
79 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
82 atpx_arg
.pointer
= &atpx_arg_elements
[0];
84 atpx_arg_elements
[0].type
= ACPI_TYPE_INTEGER
;
85 atpx_arg_elements
[0].integer
.value
= function
;
88 atpx_arg_elements
[1].type
= ACPI_TYPE_BUFFER
;
89 atpx_arg_elements
[1].buffer
.length
= params
->length
;
90 atpx_arg_elements
[1].buffer
.pointer
= params
->pointer
;
92 /* We need a second fake parameter */
93 atpx_arg_elements
[1].type
= ACPI_TYPE_INTEGER
;
94 atpx_arg_elements
[1].integer
.value
= 0;
97 status
= acpi_evaluate_object(handle
, NULL
, &atpx_arg
, &buffer
);
99 /* Fail only if calling the method fails and ATPX is supported */
100 if (ACPI_FAILURE(status
) && status
!= AE_NOT_FOUND
) {
101 printk("failed to evaluate ATPX got %s\n",
102 acpi_format_exception(status
));
103 kfree(buffer
.pointer
);
107 return buffer
.pointer
;
111 * radeon_atpx_parse_functions - parse supported functions
113 * @f: supported functions struct
114 * @mask: supported functions mask from ATPX
116 * Use the supported functions mask from ATPX function
117 * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions
118 * are supported (all asics).
120 static void radeon_atpx_parse_functions(struct radeon_atpx_functions
*f
, u32 mask
)
122 f
->px_params
= mask
& ATPX_GET_PX_PARAMETERS_SUPPORTED
;
123 f
->power_cntl
= mask
& ATPX_POWER_CONTROL_SUPPORTED
;
124 f
->disp_mux_cntl
= mask
& ATPX_DISPLAY_MUX_CONTROL_SUPPORTED
;
125 f
->i2c_mux_cntl
= mask
& ATPX_I2C_MUX_CONTROL_SUPPORTED
;
126 f
->switch_start
= mask
& ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED
;
127 f
->switch_end
= mask
& ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED
;
128 f
->disp_connectors_mapping
= mask
& ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED
;
129 f
->disp_detetion_ports
= mask
& ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED
;
133 * radeon_atpx_validate_functions - validate ATPX functions
135 * @atpx: radeon atpx struct
137 * Validate that required functions are enabled (all asics).
138 * returns 0 on success, error on failure.
140 static int radeon_atpx_validate(struct radeon_atpx
*atpx
)
142 /* make sure required functions are enabled */
143 /* dGPU power control is required */
144 atpx
->functions
.power_cntl
= true;
146 if (atpx
->functions
.px_params
) {
147 union acpi_object
*info
;
148 struct atpx_px_params output
;
152 info
= radeon_atpx_call(atpx
->handle
, ATPX_FUNCTION_GET_PX_PARAMETERS
, NULL
);
156 memset(&output
, 0, sizeof(output
));
158 size
= *(u16
*) info
->buffer
.pointer
;
160 printk("ATPX buffer is too small: %zu\n", size
);
164 size
= min(sizeof(output
), size
);
166 memcpy(&output
, info
->buffer
.pointer
, size
);
168 valid_bits
= output
.flags
& output
.valid_flags
;
169 /* if separate mux flag is set, mux controls are required */
170 if (valid_bits
& ATPX_SEPARATE_MUX_FOR_I2C
) {
171 atpx
->functions
.i2c_mux_cntl
= true;
172 atpx
->functions
.disp_mux_cntl
= true;
174 /* if any outputs are muxed, mux controls are required */
175 if (valid_bits
& (ATPX_CRT1_RGB_SIGNAL_MUXED
|
176 ATPX_TV_SIGNAL_MUXED
|
177 ATPX_DFP_SIGNAL_MUXED
))
178 atpx
->functions
.disp_mux_cntl
= true;
186 * radeon_atpx_verify_interface - verify ATPX
188 * @atpx: radeon atpx struct
190 * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
191 * to initialize ATPX and determine what features are supported
193 * returns 0 on success, error on failure.
195 static int radeon_atpx_verify_interface(struct radeon_atpx
*atpx
)
197 union acpi_object
*info
;
198 struct atpx_verify_interface output
;
202 info
= radeon_atpx_call(atpx
->handle
, ATPX_FUNCTION_VERIFY_INTERFACE
, NULL
);
206 memset(&output
, 0, sizeof(output
));
208 size
= *(u16
*) info
->buffer
.pointer
;
210 printk("ATPX buffer is too small: %zu\n", size
);
214 size
= min(sizeof(output
), size
);
216 memcpy(&output
, info
->buffer
.pointer
, size
);
218 /* TODO: check version? */
219 printk("ATPX version %u, functions 0x%08x\n",
220 output
.version
, output
.function_bits
);
222 radeon_atpx_parse_functions(&atpx
->functions
, output
.function_bits
);
230 * radeon_atpx_set_discrete_state - power up/down discrete GPU
232 * @atpx: atpx info struct
233 * @state: discrete GPU state (0 = power down, 1 = power up)
235 * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to
236 * power down/up the discrete GPU (all asics).
237 * Returns 0 on success, error on failure.
239 static int radeon_atpx_set_discrete_state(struct radeon_atpx
*atpx
, u8 state
)
241 struct acpi_buffer params
;
242 union acpi_object
*info
;
243 struct atpx_power_control input
;
245 if (atpx
->functions
.power_cntl
) {
247 input
.dgpu_state
= state
;
248 params
.length
= input
.size
;
249 params
.pointer
= &input
;
250 info
= radeon_atpx_call(atpx
->handle
,
251 ATPX_FUNCTION_POWER_CONTROL
,
261 * radeon_atpx_switch_disp_mux - switch display mux
263 * @atpx: atpx info struct
264 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
266 * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to
267 * switch the display mux between the discrete GPU and integrated GPU
269 * Returns 0 on success, error on failure.
271 static int radeon_atpx_switch_disp_mux(struct radeon_atpx
*atpx
, u16 mux_id
)
273 struct acpi_buffer params
;
274 union acpi_object
*info
;
275 struct atpx_mux input
;
277 if (atpx
->functions
.disp_mux_cntl
) {
280 params
.length
= input
.size
;
281 params
.pointer
= &input
;
282 info
= radeon_atpx_call(atpx
->handle
,
283 ATPX_FUNCTION_DISPLAY_MUX_CONTROL
,
293 * radeon_atpx_switch_i2c_mux - switch i2c/hpd mux
295 * @atpx: atpx info struct
296 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
298 * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to
299 * switch the i2c/hpd mux between the discrete GPU and integrated GPU
301 * Returns 0 on success, error on failure.
303 static int radeon_atpx_switch_i2c_mux(struct radeon_atpx
*atpx
, u16 mux_id
)
305 struct acpi_buffer params
;
306 union acpi_object
*info
;
307 struct atpx_mux input
;
309 if (atpx
->functions
.i2c_mux_cntl
) {
312 params
.length
= input
.size
;
313 params
.pointer
= &input
;
314 info
= radeon_atpx_call(atpx
->handle
,
315 ATPX_FUNCTION_I2C_MUX_CONTROL
,
325 * radeon_atpx_switch_start - notify the sbios of a GPU switch
327 * @atpx: atpx info struct
328 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
330 * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX
331 * function to notify the sbios that a switch between the discrete GPU and
332 * integrated GPU has begun (all asics).
333 * Returns 0 on success, error on failure.
335 static int radeon_atpx_switch_start(struct radeon_atpx
*atpx
, u16 mux_id
)
337 struct acpi_buffer params
;
338 union acpi_object
*info
;
339 struct atpx_mux input
;
341 if (atpx
->functions
.switch_start
) {
344 params
.length
= input
.size
;
345 params
.pointer
= &input
;
346 info
= radeon_atpx_call(atpx
->handle
,
347 ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION
,
357 * radeon_atpx_switch_end - notify the sbios of a GPU switch
359 * @atpx: atpx info struct
360 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
362 * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX
363 * function to notify the sbios that a switch between the discrete GPU and
364 * integrated GPU has ended (all asics).
365 * Returns 0 on success, error on failure.
367 static int radeon_atpx_switch_end(struct radeon_atpx
*atpx
, u16 mux_id
)
369 struct acpi_buffer params
;
370 union acpi_object
*info
;
371 struct atpx_mux input
;
373 if (atpx
->functions
.switch_end
) {
376 params
.length
= input
.size
;
377 params
.pointer
= &input
;
378 info
= radeon_atpx_call(atpx
->handle
,
379 ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION
,
389 * radeon_atpx_switchto - switch to the requested GPU
391 * @id: GPU to switch to
393 * Execute the necessary ATPX functions to switch between the discrete GPU and
394 * integrated GPU (all asics).
395 * Returns 0 on success, error on failure.
397 static int radeon_atpx_switchto(enum vga_switcheroo_client_id id
)
401 if (id
== VGA_SWITCHEROO_IGD
)
402 gpu_id
= ATPX_INTEGRATED_GPU
;
404 gpu_id
= ATPX_DISCRETE_GPU
;
406 radeon_atpx_switch_start(&radeon_atpx_priv
.atpx
, gpu_id
);
407 radeon_atpx_switch_disp_mux(&radeon_atpx_priv
.atpx
, gpu_id
);
408 radeon_atpx_switch_i2c_mux(&radeon_atpx_priv
.atpx
, gpu_id
);
409 radeon_atpx_switch_end(&radeon_atpx_priv
.atpx
, gpu_id
);
415 * radeon_atpx_power_state - power down/up the requested GPU
417 * @id: GPU to power down/up
418 * @state: requested power state (0 = off, 1 = on)
420 * Execute the necessary ATPX function to power down/up the discrete GPU
422 * Returns 0 on success, error on failure.
424 static int radeon_atpx_power_state(enum vga_switcheroo_client_id id
,
425 enum vga_switcheroo_state state
)
427 /* on w500 ACPI can't change intel gpu state */
428 if (id
== VGA_SWITCHEROO_IGD
)
431 radeon_atpx_set_discrete_state(&radeon_atpx_priv
.atpx
, state
);
436 * radeon_atpx_pci_probe_handle - look up the ATPX handle
440 * Look up the ATPX handles (all asics).
441 * Returns true if the handles are found, false if not.
443 static bool radeon_atpx_pci_probe_handle(struct pci_dev
*pdev
)
445 acpi_handle dhandle
, atpx_handle
;
448 dhandle
= DEVICE_ACPI_HANDLE(&pdev
->dev
);
452 status
= acpi_get_handle(dhandle
, "ATPX", &atpx_handle
);
453 if (ACPI_FAILURE(status
)) {
454 radeon_atpx_priv
.other_handle
= dhandle
;
457 radeon_atpx_priv
.dhandle
= dhandle
;
458 radeon_atpx_priv
.atpx
.handle
= atpx_handle
;
463 * radeon_atpx_init - verify the ATPX interface
465 * Verify the ATPX interface (all asics).
466 * Returns 0 on success, error on failure.
468 static int radeon_atpx_init(void)
472 /* set up the ATPX handle */
473 r
= radeon_atpx_verify_interface(&radeon_atpx_priv
.atpx
);
477 /* validate the atpx setup */
478 r
= radeon_atpx_validate(&radeon_atpx_priv
.atpx
);
486 * radeon_atpx_get_client_id - get the client id
490 * look up whether we are the integrated or discrete GPU (all asics).
491 * Returns the client id.
493 static int radeon_atpx_get_client_id(struct pci_dev
*pdev
)
495 if (radeon_atpx_priv
.dhandle
== DEVICE_ACPI_HANDLE(&pdev
->dev
))
496 return VGA_SWITCHEROO_IGD
;
498 return VGA_SWITCHEROO_DIS
;
501 static struct vga_switcheroo_handler radeon_atpx_handler
= {
502 .switchto
= radeon_atpx_switchto
,
503 .power_state
= radeon_atpx_power_state
,
504 .init
= radeon_atpx_init
,
505 .get_client_id
= radeon_atpx_get_client_id
,
509 * radeon_atpx_detect - detect whether we have PX
511 * Check if we have a PX system (all asics).
512 * Returns true if we have a PX system, false if not.
514 static bool radeon_atpx_detect(void)
516 char acpi_method_name
[255] = { 0 };
517 struct acpi_buffer buffer
= {sizeof(acpi_method_name
), acpi_method_name
};
518 struct pci_dev
*pdev
= NULL
;
519 bool has_atpx
= false;
522 while ((pdev
= pci_get_class(PCI_CLASS_DISPLAY_VGA
<< 8, pdev
)) != NULL
) {
525 has_atpx
|= (radeon_atpx_pci_probe_handle(pdev
) == true);
528 /* some newer PX laptops mark the dGPU as a non-VGA display device */
529 while ((pdev
= pci_get_class(PCI_CLASS_DISPLAY_OTHER
<< 8, pdev
)) != NULL
) {
532 has_atpx
|= (radeon_atpx_pci_probe_handle(pdev
) == true);
535 if (has_atpx
&& vga_count
== 2) {
536 acpi_get_name(radeon_atpx_priv
.atpx
.handle
, ACPI_FULL_PATHNAME
, &buffer
);
537 printk(KERN_INFO
"VGA switcheroo: detected switching method %s handle\n",
539 radeon_atpx_priv
.atpx_detected
= true;
541 * On some systems hotplug events are generated for the device
542 * being switched off when ATPX is executed. They cause ACPI
543 * hotplug to trigger and attempt to remove the device from
544 * the system, which causes it to break down. Prevent that from
545 * happening by setting the no_hotplug flag for the involved
546 * ACPI device objects.
548 acpi_bus_no_hotplug(radeon_atpx_priv
.dhandle
);
549 acpi_bus_no_hotplug(radeon_atpx_priv
.other_handle
);
556 * radeon_register_atpx_handler - register with vga_switcheroo
558 * Register the PX callbacks with vga_switcheroo (all asics).
560 void radeon_register_atpx_handler(void)
564 /* detect if we have any ATPX + 2 VGA in the system */
565 r
= radeon_atpx_detect();
569 vga_switcheroo_register_handler(&radeon_atpx_handler
);
573 * radeon_unregister_atpx_handler - unregister with vga_switcheroo
575 * Unregister the PX callbacks with vga_switcheroo (all asics).
577 void radeon_unregister_atpx_handler(void)
579 vga_switcheroo_unregister_handler();