diff options
author | Dave Airlie <airlied@redhat.com> | 2010-12-06 23:24:25 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-01-04 22:45:46 -0500 |
commit | 66b37c6777c4686f121fe4a83176e535a7f4b1af (patch) | |
tree | 9fcea9832dd3a9a349e1ea001e1038bbb1148440 /drivers | |
parent | 5bcf719b7db0f9366cedaf102b081f99b1c325ae (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')
-rw-r--r-- | drivers/gpu/vga/vga_switcheroo.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 2b8e1d25e8d0..d2d8543686d3 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 | ||
215 | static int vga_switchto(struct vga_switcheroo_client *new_client) | 215 | /* stage one happens before delay */ |
216 | static 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 */ | ||
249 | static 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 | ||
385 | out: | 408 | out: |
@@ -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; |