diff options
author | Dave Airlie <airlied@linux.ie> | 2010-02-01 00:38:10 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-03-01 01:20:37 -0500 |
commit | 6a9ee8af344e3bd7dbd61e67037096cdf7f83289 (patch) | |
tree | 07cdb493a790cf45bc473f2fc2ea1b9a166d5191 /include | |
parent | 9fd1de52945e06ed88a440c99ca92dab74b9b33c (diff) |
vga_switcheroo: initial implementation (v15)
Many new laptops now come with 2 gpus, one to be used for low power
modes and one for gaming/on-ac applications. These GPUs are typically
wired to the laptop panel and VGA ports via a multiplexer unit which
is controlled via ACPI methods.
4 combinations of systems typically exist - with 2 ACPI methods.
Intel/ATI - Lenovo W500/T500 - use ATPX ACPI method
ATI/ATI - some ASUS - use ATPX ACPI Method
Intel/Nvidia - - use _DSM ACPI method
Nvidia/Nvidia - - use _DSM ACPI method.
TODO:
This patch adds support for the ATPX method and initial bits
for the _DSM methods that need to written by someone with
access to the hardware.
Add a proper non-debugfs interface - need to get some proper
testing first.
v2: add power up/down support for both devices
on W500 puts i915/radeon into D3 and cuts power to radeon.
v3: redo probing methods, no DMI list, drm devices call to
register with switcheroo, it tries to find an ATPX method on
any device and once there is two devices + ATPX it inits the
switcher.
v4: ATPX msg handling using buffers - should work on more machines
v5: rearchitect after more mjg59 discussion - move ATPX handling to
radeon driver.
v6: add file headers + initial nouveau bits (to be filled out).
v7: merge delayed switcher code.
v8: avoid suspend/resume of gpu that is off
v9: rearchitect - mjg59 is always right. - move all ATPX code to
radeon, should allow simpler DSM also proper ATRM handling
v10: add ATRM support for radeon BIOS, add mutex to lock vgasr_priv
v11: fix bug in resuming Intel for 2nd time.
v12: start fixing up nvidia code blindly.
v13: blindly guess at finishing nvidia code
v14: remove radeon audio hacks - fix up intel resume more like upstream
v15: clean up printks + remove unnecessary igd/dis pointers
mount debugfs
/sys/kernel/debug/vgaswitcheroo/switch - should exist if ATPX detected
+ 2 cards.
DIS - immediate change to discrete
IGD - immediate change to IGD
DDIS - delayed change to discrete
DIGD - delayed change to IGD
ON - turn on not in use
OFF - turn off not in use
Tested on W500 (Intel/ATI) and T500 (Intel/ATI)
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/fb.h | 2 | ||||
-rw-r--r-- | include/linux/vga_switcheroo.h | 58 |
2 files changed, 60 insertions, 0 deletions
diff --git a/include/linux/fb.h b/include/linux/fb.h index 369767bd873e..c10163b4c40e 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -543,6 +543,8 @@ struct fb_cursor_user { | |||
543 | #define FB_EVENT_GET_REQ 0x0D | 543 | #define FB_EVENT_GET_REQ 0x0D |
544 | /* Unbind from the console if possible */ | 544 | /* Unbind from the console if possible */ |
545 | #define FB_EVENT_FB_UNBIND 0x0E | 545 | #define FB_EVENT_FB_UNBIND 0x0E |
546 | /* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga switcheroo */ | ||
547 | #define FB_EVENT_REMAP_ALL_CONSOLE 0x0F | ||
546 | 548 | ||
547 | struct fb_event { | 549 | struct fb_event { |
548 | struct fb_info *info; | 550 | struct fb_info *info; |
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h new file mode 100644 index 000000000000..4b58ab1e8612 --- /dev/null +++ b/include/linux/vga_switcheroo.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Red Hat Inc. | ||
3 | * Author : Dave Airlie <airlied@redhat.com> | ||
4 | * | ||
5 | * Licensed under GPLv2 | ||
6 | * | ||
7 | * vga_switcheroo.h - Support for laptop with dual GPU using one set of outputs | ||
8 | */ | ||
9 | |||
10 | #include <acpi/acpi.h> | ||
11 | #include <linux/fb.h> | ||
12 | |||
13 | enum vga_switcheroo_state { | ||
14 | VGA_SWITCHEROO_OFF, | ||
15 | VGA_SWITCHEROO_ON, | ||
16 | }; | ||
17 | |||
18 | enum vga_switcheroo_client_id { | ||
19 | VGA_SWITCHEROO_IGD, | ||
20 | VGA_SWITCHEROO_DIS, | ||
21 | VGA_SWITCHEROO_MAX_CLIENTS, | ||
22 | }; | ||
23 | |||
24 | struct vga_switcheroo_handler { | ||
25 | int (*switchto)(enum vga_switcheroo_client_id id); | ||
26 | int (*power_state)(enum vga_switcheroo_client_id id, | ||
27 | enum vga_switcheroo_state state); | ||
28 | int (*init)(void); | ||
29 | int (*get_client_id)(struct pci_dev *pdev); | ||
30 | }; | ||
31 | |||
32 | |||
33 | #if defined(CONFIG_VGA_SWITCHEROO) | ||
34 | void vga_switcheroo_unregister_client(struct pci_dev *dev); | ||
35 | int vga_switcheroo_register_client(struct pci_dev *dev, | ||
36 | void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state), | ||
37 | bool (*can_switch)(struct pci_dev *dev)); | ||
38 | |||
39 | void vga_switcheroo_client_fb_set(struct pci_dev *dev, | ||
40 | struct fb_info *info); | ||
41 | |||
42 | int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler); | ||
43 | void vga_switcheroo_unregister_handler(void); | ||
44 | |||
45 | int vga_switcheroo_process_delayed_switch(void); | ||
46 | |||
47 | #else | ||
48 | |||
49 | static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {} | ||
50 | static inline int vga_switcheroo_register_client(struct pci_dev *dev, | ||
51 | void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state), | ||
52 | bool (*can_switch)(struct pci_dev *dev)) { return 0; } | ||
53 | static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {} | ||
54 | static inline int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { return 0; } | ||
55 | static inline void vga_switcheroo_unregister_handler(void) {} | ||
56 | static inline int vga_switcheroo_process_delayed_switch(void) { return 0; } | ||
57 | |||
58 | #endif | ||