From 66b37c6777c4686f121fe4a83176e535a7f4b1af Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 7 Dec 2010 14:24:25 +1000 Subject: 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 --- drivers/gpu/vga/vga_switcheroo.c | 45 ++++++++++++++++++++++++++++++---------- 1 file 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) return 0; } -static int vga_switchto(struct vga_switcheroo_client *new_client) +/* stage one happens before delay */ +static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) { int ret; int i; @@ -239,10 +240,28 @@ static int vga_switchto(struct vga_switcheroo_client *new_client) vga_switchon(new_client); /* swap shadow resource to denote boot VGA device has changed so X starts on new device */ - active->active = false; - active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW; new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; + return 0; +} + +/* post delay */ +static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) +{ + int ret; + int i; + struct vga_switcheroo_client *active = NULL; + + for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { + if (vgasr_priv.clients[i].active == true) { + active = &vgasr_priv.clients[i]; + break; + } + } + if (!active) + return 0; + + active->active = false; if (new_client->fb_info) { struct fb_event event; @@ -368,18 +387,22 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, if (can_switch == true) { pdev_name = pci_name(client->pdev); - ret = vga_switchto(client); + ret = vga_switchto_stage1(client); + if (ret) + printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret); + + ret = vga_switchto_stage2(client); if (ret) - printk(KERN_ERR "vga_switcheroo: switching failed %d\n", ret); + printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret); + } else { printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id); vgasr_priv.delayed_switch_active = true; vgasr_priv.delayed_client_id = client_id; - /* we should at least power up the card to - make the switch faster */ - if (client->pwr_state == VGA_SWITCHEROO_OFF) - vga_switchon(client); + ret = vga_switchto_stage1(client); + if (ret) + printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret); } out: @@ -461,9 +484,9 @@ int vga_switcheroo_process_delayed_switch(void) goto err; pdev_name = pci_name(client->pdev); - ret = vga_switchto(client); + ret = vga_switchto_stage2(client); if (ret) - printk(KERN_ERR "vga_switcheroo: delayed switching failed %d\n", ret); + printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret); vgasr_priv.delayed_switch_active = false; err = 0; -- cgit v1.2.3