Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66b37c67 authored by Dave Airlie's avatar Dave Airlie
Browse files

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: default avatarDave Airlie <airlied@redhat.com>
parent 5bcf719b
Loading
Loading
Loading
Loading
+34 −11
Original line number Diff line number Diff line
@@ -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;