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
)
282 /* pwr off the device not in use */
283 if (strncmp(usercmd
, "OFF", 3) == 0) {
284 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
285 if (vgasr_priv
.clients
[i
].active
)
287 if (vgasr_priv
.clients
[i
].pwr_state
== VGA_SWITCHEROO_ON
)
288 vga_switchoff(&vgasr_priv
.clients
[i
]);
292 /* pwr on the device not in use */
293 if (strncmp(usercmd
, "ON", 2) == 0) {
294 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
295 if (vgasr_priv
.clients
[i
].active
)
297 if (vgasr_priv
.clients
[i
].pwr_state
== VGA_SWITCHEROO_OFF
)
298 vga_switchon(&vgasr_priv
.clients
[i
]);
303 /* request a delayed switch - test can we switch now */
304 if (strncmp(usercmd
, "DIGD", 4) == 0) {
305 client_id
= VGA_SWITCHEROO_IGD
;
309 if (strncmp(usercmd
, "DDIS", 4) == 0) {
310 client_id
= VGA_SWITCHEROO_DIS
;
314 if (strncmp(usercmd
, "IGD", 3) == 0)
315 client_id
= VGA_SWITCHEROO_IGD
;
317 if (strncmp(usercmd
, "DIS", 3) == 0)
318 client_id
= VGA_SWITCHEROO_DIS
;
323 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
324 if (vgasr_priv
.clients
[i
].id
== client_id
) {
325 client
= &vgasr_priv
.clients
[i
];
330 vgasr_priv
.delayed_switch_active
= false;
331 /* okay we want a switch - test if devices are willing to switch */
333 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
334 can_switch
= vgasr_priv
.clients
[i
].can_switch(vgasr_priv
.clients
[i
].pdev
);
335 if (can_switch
== false) {
336 printk(KERN_ERR
"vga_switcheroo: client %d refused switch\n", i
);
341 if (can_switch
== false && delay
== false)
344 if (can_switch
== true) {
345 pdev_name
= pci_name(client
->pdev
);
346 ret
= vga_switchto(client
);
348 printk(KERN_ERR
"vga_switcheroo: switching failed %d\n", ret
);
350 printk(KERN_INFO
"vga_switcheroo: setting delayed switch to client %d\n", client
->id
);
351 vgasr_priv
.delayed_switch_active
= true;
352 vgasr_priv
.delayed_client_id
= client_id
;
354 /* we should at least power up the card to
355 make the switch faster */
356 if (client
->pwr_state
== VGA_SWITCHEROO_OFF
)
357 vga_switchon(client
);
361 mutex_unlock(&vgasr_mutex
);
365 static const struct file_operations vga_switcheroo_debugfs_fops
= {
366 .owner
= THIS_MODULE
,
367 .open
= vga_switcheroo_debugfs_open
,
368 .write
= vga_switcheroo_debugfs_write
,
371 .release
= single_release
,
374 static void vga_switcheroo_debugfs_fini(struct vgasr_priv
*priv
)
376 if (priv
->switch_file
) {
377 debugfs_remove(priv
->switch_file
);
378 priv
->switch_file
= NULL
;
380 if (priv
->debugfs_root
) {
381 debugfs_remove(priv
->debugfs_root
);
382 priv
->debugfs_root
= NULL
;
386 static int vga_switcheroo_debugfs_init(struct vgasr_priv
*priv
)
388 /* already initialised */
389 if (priv
->debugfs_root
)
391 priv
->debugfs_root
= debugfs_create_dir("vgaswitcheroo", NULL
);
393 if (!priv
->debugfs_root
) {
394 printk(KERN_ERR
"vga_switcheroo: Cannot create /sys/kernel/debug/vgaswitcheroo\n");
398 priv
->switch_file
= debugfs_create_file("switch", 0644,
399 priv
->debugfs_root
, NULL
, &vga_switcheroo_debugfs_fops
);
400 if (!priv
->switch_file
) {
401 printk(KERN_ERR
"vga_switcheroo: cannot create /sys/kernel/debug/vgaswitcheroo/switch\n");
406 vga_switcheroo_debugfs_fini(priv
);
410 int vga_switcheroo_process_delayed_switch(void)
412 struct vga_switcheroo_client
*client
= NULL
;
413 const char *pdev_name
;
414 bool can_switch
= true;
419 mutex_lock(&vgasr_mutex
);
420 if (!vgasr_priv
.delayed_switch_active
)
423 printk(KERN_INFO
"vga_switcheroo: processing delayed switch to %d\n", vgasr_priv
.delayed_client_id
);
425 for (i
= 0; i
< VGA_SWITCHEROO_MAX_CLIENTS
; i
++) {
426 if (vgasr_priv
.clients
[i
].id
== vgasr_priv
.delayed_client_id
)
427 client
= &vgasr_priv
.clients
[i
];
428 can_switch
= vgasr_priv
.clients
[i
].can_switch(vgasr_priv
.clients
[i
].pdev
);
429 if (can_switch
== false) {
430 printk(KERN_ERR
"vga_switcheroo: client %d refused switch\n", i
);
435 if (can_switch
== false || client
== NULL
)
438 pdev_name
= pci_name(client
->pdev
);
439 ret
= vga_switchto(client
);
441 printk(KERN_ERR
"vga_switcheroo: delayed switching failed %d\n", ret
);
443 vgasr_priv
.delayed_switch_active
= false;
446 mutex_unlock(&vgasr_mutex
);
449 EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch
);