2 * Copyright (c) 2010 Red Hat Inc.
3 * Author : Dave Airlie <airlied@redhat.com>
8 * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
10 Switcher interface - methods require for ATPX and DCM
11 - switchto - this throws the output MUX switch
12 - discrete_set_power - sets the power state for the discrete card
15 - set_gpu_state - this should do the equiv of s/r for the card
16 - this should *not* set the discrete power state
17 - switch_check - check if the device is in a position to switch now
20 #include <linux/module.h>
21 #include <linux/dmi.h>
22 #include <linux/seq_file.h>
23 #include <linux/uaccess.h>
25 #include <linux/debugfs.h>
28 #include <linux/pci.h>
29 #include <linux/vga_switcheroo.h>
31 struct vga_switcheroo_client
{
33 struct fb_info
*fb_info
;
35 void (*set_gpu_state
)(struct pci_dev
*pdev
, enum vga_switcheroo_state
);
36 bool (*can_switch
)(struct pci_dev
*pdev
);
41 static DEFINE_MUTEX(vgasr_mutex
);
46 bool delayed_switch_active
;
47 enum vga_switcheroo_client_id delayed_client_id
;
49 struct dentry
*debugfs_root
;
50 struct dentry
*switch_file
;
52 int registered_clients
;
53 struct vga_switcheroo_client clients
[VGA_SWITCHEROO_MAX_CLIENTS
];
55 struct vga_switcheroo_handler
*handler
;
58 static int vga_switcheroo_debugfs_init(struct vgasr_priv
*priv
);
59 static void vga_switcheroo_debugfs_fini(struct vgasr_priv
*priv
);
61 /* only one switcheroo per system */
62 static struct vgasr_priv vgasr_priv
;
64 int vga_switcheroo_register_handler(struct vga_switcheroo_handler
*handler
)
66 mutex_lock(&vgasr_mutex
);
67 if (vgasr_priv
.handler
) {
68 mutex_unlock(&vgasr_mutex
);
72 vgasr_priv
.handler
= handler
;
73 mutex_unlock(&vgasr_mutex
);
76 EXPORT_SYMBOL(vga_switcheroo_register_handler
);
78 void vga_switcheroo_unregister_handler(void)
80 mutex_lock(&vgasr_mutex
);
81 vgasr_priv
.handler
= NULL
;
82 mutex_unlock(&vgasr_mutex
);
84 EXPORT_SYMBOL(vga_switcheroo_unregister_handler
);
86 static void vga_switcheroo_enable(void)
90 /* call the handler to init */
91 vgasr_priv
.handler
->init();
93 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
94 ret
= vgasr_priv
.handler
->get_client_id(vgasr_priv
.clients
[i
].pdev
);
98 vgasr_priv
.clients
[i
].id
= ret
;
100 vga_switcheroo_debugfs_init(&vgasr_priv
);
101 vgasr_priv
.active
= true;
104 int vga_switcheroo_register_client(struct pci_dev
*pdev
,
105 void (*set_gpu_state
)(struct pci_dev
*pdev
, enum vga_switcheroo_state
),
106 bool (*can_switch
)(struct pci_dev
*pdev
))
110 mutex_lock(&vgasr_mutex
);
111 /* don't do IGD vs DIS here */
112 if (vgasr_priv
.registered_clients
& 1)
117 vgasr_priv
.clients
[index
].pwr_state
= VGA_SWITCHEROO_ON
;
118 vgasr_priv
.clients
[index
].pdev
= pdev
;
119 vgasr_priv
.clients
[index
].set_gpu_state
= set_gpu_state
;
120 vgasr_priv
.clients
[index
].can_switch
= can_switch
;
121 vgasr_priv
.clients
[index
].id
= -1;
122 if (pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
)
123 vgasr_priv
.clients
[index
].active
= true;
125 vgasr_priv
.registered_clients
|= (1 << index
);
127 /* if we get two clients + handler */
128 if (vgasr_priv
.registered_clients
== 0x3 && vgasr_priv
.handler
) {
129 printk(KERN_INFO
"vga_switcheroo: enabled\n");
130 vga_switcheroo_enable();
132 mutex_unlock(&vgasr_mutex
);
135 EXPORT_SYMBOL(vga_switcheroo_register_client
);
137 void vga_switcheroo_unregister_client(struct pci_dev
*pdev
)
141 mutex_lock(&vgasr_mutex
);
142 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
143 if (vgasr_priv
.clients
[i
].pdev
== pdev
) {
144 vgasr_priv
.registered_clients
&= ~(1 << i
);
149 printk(KERN_INFO
"vga_switcheroo: disabled\n");
150 vga_switcheroo_debugfs_fini(&vgasr_priv
);
151 vgasr_priv
.active
= false;
152 mutex_unlock(&vgasr_mutex
);
154 EXPORT_SYMBOL(vga_switcheroo_unregister_client
);
156 void vga_switcheroo_client_fb_set(struct pci_dev
*pdev
,
157 struct fb_info
*info
)
161 mutex_lock(&vgasr_mutex
);
162 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
163 if (vgasr_priv
.clients
[i
].pdev
== pdev
) {
164 vgasr_priv
.clients
[i
].fb_info
= info
;
168 mutex_unlock(&vgasr_mutex
);
170 EXPORT_SYMBOL(vga_switcheroo_client_fb_set
);
172 static int vga_switcheroo_show(struct seq_file
*m
, void *v
)
175 mutex_lock(&vgasr_mutex
);
176 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
177 seq_printf(m
, "%d:%c:%s:%s\n", i
,
178 vgasr_priv
.clients
[i
].active
? '+' : ' ',
179 vgasr_priv
.clients
[i
].pwr_state
? "Pwr" : "Off",
180 pci_name(vgasr_priv
.clients
[i
].pdev
));
182 mutex_unlock(&vgasr_mutex
);
186 static int vga_switcheroo_debugfs_open(struct inode
*inode
, struct file
*file
)
188 return single_open(file
, vga_switcheroo_show
, NULL
);
191 static int vga_switchon(struct vga_switcheroo_client
*client
)
195 ret
= vgasr_priv
.handler
->power_state(client
->id
, VGA_SWITCHEROO_ON
);
196 /* call the driver callback to turn on device */
197 client
->set_gpu_state(client
->pdev
, VGA_SWITCHEROO_ON
);
198 client
->pwr_state
= VGA_SWITCHEROO_ON
;
202 static int vga_switchoff(struct vga_switcheroo_client
*client
)
204 /* call the driver callback to turn off device */
205 client
->set_gpu_state(client
->pdev
, VGA_SWITCHEROO_OFF
);
206 vgasr_priv
.handler
->power_state(client
->id
, VGA_SWITCHEROO_OFF
);
207 client
->pwr_state
= VGA_SWITCHEROO_OFF
;
211 static int vga_switchto(struct vga_switcheroo_client
*new_client
)
215 struct vga_switcheroo_client
*active
= NULL
;
217 if (new_client
->active
== true)
220 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
221 if (vgasr_priv
.clients
[i
].active
== true) {
222 active
= &vgasr_priv
.clients
[i
];
229 /* power up the first device */
230 ret
= pci_enable_device(new_client
->pdev
);
234 if (new_client
->pwr_state
== VGA_SWITCHEROO_OFF
)
235 vga_switchon(new_client
);
237 /* swap shadow resource to denote boot VGA device has changed so X starts on new device */
238 active
->active
= false;
240 active
->pdev
->resource
[PCI_ROM_RESOURCE
].flags
&= ~IORESOURCE_ROM_SHADOW
;
241 new_client
->pdev
->resource
[PCI_ROM_RESOURCE
].flags
|= IORESOURCE_ROM_SHADOW
;
243 if (new_client
->fb_info
) {
244 struct fb_event event
;
245 event
.info
= new_client
->fb_info
;
246 fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE
, &event
);
249 ret
= vgasr_priv
.handler
->switchto(new_client
->id
);
253 if (active
->pwr_state
== VGA_SWITCHEROO_ON
)
254 vga_switchoff(active
);
256 new_client
->active
= true;
261 vga_switcheroo_debugfs_write(struct file
*filp
, const char __user
*ubuf
,
262 size_t cnt
, loff_t
*ppos
)
265 const char *pdev_name
;
267 bool delay
= false, can_switch
;
269 struct vga_switcheroo_client
*client
= NULL
;
274 if (copy_from_user(usercmd
, ubuf
, cnt
))
277 mutex_lock(&vgasr_mutex
);
279 if (!vgasr_priv
.active
) {
284 /* pwr off the device not in use */
285 if (strncmp(usercmd
, "OFF", 3) == 0) {
286 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
287 if (vgasr_priv
.clients
[i
].active
)
289 if (vgasr_priv
.clients
[i
].pwr_state
== VGA_SWITCHEROO_ON
)
290 vga_switchoff(&vgasr_priv
.clients
[i
]);
294 /* pwr on the device not in use */
295 if (strncmp(usercmd
, "ON", 2) == 0) {
296 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
297 if (vgasr_priv
.clients
[i
].active
)
299 if (vgasr_priv
.clients
[i
].pwr_state
== VGA_SWITCHEROO_OFF
)
300 vga_switchon(&vgasr_priv
.clients
[i
]);
305 /* request a delayed switch - test can we switch now */
306 if (strncmp(usercmd
, "DIGD", 4) == 0) {
307 client_id
= VGA_SWITCHEROO_IGD
;
311 if (strncmp(usercmd
, "DDIS", 4) == 0) {
312 client_id
= VGA_SWITCHEROO_DIS
;
316 if (strncmp(usercmd
, "IGD", 3) == 0)
317 client_id
= VGA_SWITCHEROO_IGD
;
319 if (strncmp(usercmd
, "DIS", 3) == 0)
320 client_id
= VGA_SWITCHEROO_DIS
;
325 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
326 if (vgasr_priv
.clients
[i
].id
== client_id
) {
327 client
= &vgasr_priv
.clients
[i
];
332 vgasr_priv
.delayed_switch_active
= false;
333 /* okay we want a switch - test if devices are willing to switch */
335 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
336 can_switch
= vgasr_priv
.clients
[i
].can_switch(vgasr_priv
.clients
[i
].pdev
);
337 if (can_switch
== false) {
338 printk(KERN_ERR
"vga_switcheroo: client %d refused switch\n", i
);
343 if (can_switch
== false && delay
== false)
346 if (can_switch
== true) {
347 pdev_name
= pci_name(client
->pdev
);
348 ret
= vga_switchto(client
);
350 printk(KERN_ERR
"vga_switcheroo: switching failed %d\n", ret
);
352 printk(KERN_INFO
"vga_switcheroo: setting delayed switch to client %d\n", client
->id
);
353 vgasr_priv
.delayed_switch_active
= true;
354 vgasr_priv
.delayed_client_id
= client_id
;
356 /* we should at least power up the card to
357 make the switch faster */
358 if (client
->pwr_state
== VGA_SWITCHEROO_OFF
)
359 vga_switchon(client
);
363 mutex_unlock(&vgasr_mutex
);
367 static const struct file_operations vga_switcheroo_debugfs_fops
= {
368 .owner
= THIS_MODULE
,
369 .open
= vga_switcheroo_debugfs_open
,
370 .write
= vga_switcheroo_debugfs_write
,
373 .release
= single_release
,
376 static void vga_switcheroo_debugfs_fini(struct vgasr_priv
*priv
)
378 if (priv
->switch_file
) {
379 debugfs_remove(priv
->switch_file
);
380 priv
->switch_file
= NULL
;
382 if (priv
->debugfs_root
) {
383 debugfs_remove(priv
->debugfs_root
);
384 priv
->debugfs_root
= NULL
;
388 static int vga_switcheroo_debugfs_init(struct vgasr_priv
*priv
)
390 /* already initialised */
391 if (priv
->debugfs_root
)
393 priv
->debugfs_root
= debugfs_create_dir("vgaswitcheroo", NULL
);
395 if (!priv
->debugfs_root
) {
396 printk(KERN_ERR
"vga_switcheroo: Cannot create /sys/kernel/debug/vgaswitcheroo\n");
400 priv
->switch_file
= debugfs_create_file("switch", 0644,
401 priv
->debugfs_root
, NULL
, &vga_switcheroo_debugfs_fops
);
402 if (!priv
->switch_file
) {
403 printk(KERN_ERR
"vga_switcheroo: cannot create /sys/kernel/debug/vgaswitcheroo/switch\n");
408 vga_switcheroo_debugfs_fini(priv
);
412 int vga_switcheroo_process_delayed_switch(void)
414 struct vga_switcheroo_client
*client
= NULL
;
415 const char *pdev_name
;
416 bool can_switch
= true;
421 mutex_lock(&vgasr_mutex
);
422 if (!vgasr_priv
.delayed_switch_active
)
425 printk(KERN_INFO
"vga_switcheroo: processing delayed switch to %d\n", vgasr_priv
.delayed_client_id
);
427 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
428 if (vgasr_priv
.clients
[i
].id
== vgasr_priv
.delayed_client_id
)
429 client
= &vgasr_priv
.clients
[i
];
430 can_switch
= vgasr_priv
.clients
[i
].can_switch(vgasr_priv
.clients
[i
].pdev
);
431 if (can_switch
== false) {
432 printk(KERN_ERR
"vga_switcheroo: client %d refused switch\n", i
);
437 if (can_switch
== false || client
== NULL
)
440 pdev_name
= pci_name(client
->pdev
);
441 ret
= vga_switchto(client
);
443 printk(KERN_ERR
"vga_switcheroo: delayed switching failed %d\n", ret
);
445 vgasr_priv
.delayed_switch_active
= false;
448 mutex_unlock(&vgasr_mutex
);
451 EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch
);