aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/vga
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-12-06 23:24:25 -0500
committerDave Airlie <airlied@redhat.com>2011-01-04 22:45:46 -0500
commit66b37c6777c4686f121fe4a83176e535a7f4b1af (patch)
tree9fcea9832dd3a9a349e1ea001e1038bbb1148440 /drivers/gpu/vga
parent5bcf719b7db0f9366cedaf102b081f99b1c325ae (diff)
vga_switcheroo: split switching into two stages.
stage 1: turn card on, switch boot vga pointer. stage 2: switch fbs, switch mux and power off old card. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/vga')
-rw-r--r--drivers/gpu/vga/vga_switcheroo.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 2b8e1d25e8d..d2d8543686d 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -212,7 +212,8 @@ static int vga_switchoff(struct vga_switcheroo_client *client)
212 return 0; 212 return 0;
213} 213}
214 214
215static int vga_switchto(struct vga_switcheroo_client *new_client) 215/* stage one happens before delay */
216static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
216{ 217{
217 int ret; 218 int ret;
218 int i; 219 int i;
@@ -239,10 +240,28 @@ static int vga_switchto(struct vga_switcheroo_client *new_client)
239 vga_switchon(new_client); 240 vga_switchon(new_client);
240 241
241 /* swap shadow resource to denote boot VGA device has changed so X starts on new device */ 242 /* swap shadow resource to denote boot VGA device has changed so X starts on new device */
242 active->active = false;
243
244 active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW; 243 active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW;
245 new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; 244 new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
245 return 0;
246}
247
248/* post delay */
249static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
250{
251 int ret;
252 int i;
253 struct vga_switcheroo_client *active = NULL;
254
255 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
256 if (vgasr_priv.clients[i].active == true) {
257 active = &vgasr_priv.clients[i];
258 break;
259 }
260 }
261 if (!active)
262 return 0;
263
264 active->active = false;
246 265
247 if (new_client->fb_info) { 266 if (new_client->fb_info) {
248 struct fb_event event; 267 struct fb_event event;
@@ -368,18 +387,22 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
368 387
369 if (can_switch == true) { 388 if (can_switch == true) {
370 pdev_name = pci_name(client->pdev); 389 pdev_name = pci_name(client->pdev);
371 ret = vga_switchto(client); 390 ret = vga_switchto_stage1(client);
391 if (ret)
392 printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret);
393
394 ret = vga_switchto_stage2(client);
372 if (ret) 395 if (ret)
373 printk(KERN_ERR "vga_switcheroo: switching failed %d\n", ret); 396 printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret);
397
374 } else { 398 } else {
375 printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id); 399 printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id);
376 vgasr_priv.delayed_switch_active = true; 400 vgasr_priv.delayed_switch_active = true;
377 vgasr_priv.delayed_client_id = client_id; 401 vgasr_priv.delayed_client_id = client_id;
378 402
379 /* we should at least power up the card to 403 ret = vga_switchto_stage1(client);
380 make the switch faster */ 404 if (ret)
381 if (client->pwr_state == VGA_SWITCHEROO_OFF) 405 printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret);
382 vga_switchon(client);
383 } 406 }
384 407
385out: 408out:
@@ -461,9 +484,9 @@ int vga_switcheroo_process_delayed_switch(void)
461 goto err; 484 goto err;
462 485
463 pdev_name = pci_name(client->pdev); 486 pdev_name = pci_name(client->pdev);
464 ret = vga_switchto(client); 487 ret = vga_switchto_stage2(client);
465 if (ret) 488 if (ret)
466 printk(KERN_ERR "vga_switcheroo: delayed switching failed %d\n", ret); 489 printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret);
467 490
468 vgasr_priv.delayed_switch_active = false; 491 vgasr_priv.delayed_switch_active = false;
469 err = 0; 492 err = 0;