/*
 * Copyright (c) 2010 Red Hat Inc.
 * Author : Dave Airlie <airlied@redhat.com>
 *
 *
 * Licensed under GPLv2
 *
 * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs

 Switcher interface - methods require for ATPX and DCM
 - switchto - this throws the output MUX switch
 - discrete_set_power - sets the power state for the discrete card

 GPU driver interface
 - set_gpu_state - this should do the equiv of s/r for the card
		  - this should *not* set the discrete power state
 - switch_check  - check if the device is in a position to switch now
 */

#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/debugfs.h>
#include <linux/fb.h>

#include <linux/pci.h>
#include <linux/vga_switcheroo.h>

struct vga_switcheroo_client {
	struct pci_dev *pdev;
	struct fb_info *fb_info;
	int pwr_state;
	void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state);
	void (*reprobe)(struct pci_dev *pdev);
	bool (*can_switch)(struct pci_dev *pdev);
	int id;
	bool active;
};

static DEFINE_MUTEX(vgasr_mutex);

struct vgasr_priv {

	bool active;
	bool delayed_switch_active;
	enum vga_switcheroo_client_id delayed_client_id;

	struct dentry *debugfs_root;
	struct dentry *switch_file;

	int registered_clients;
	struct vga_switcheroo_client clients[VGA_SWITCHEROO_MAX_CLIENTS];

	struct vga_switcheroo_handler *handler;
};

static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv);
static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv);

/* only one switcheroo per system */
static struct vgasr_priv vgasr_priv;

int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
{
	mutex_lock(&vgasr_mutex);
	if (vgasr_priv.handler) {
		mutex_unlock(&vgasr_mutex);
		return -EINVAL;
	}

	vgasr_priv.handler = handler;
	mutex_unlock(&vgasr_mutex);
	return 0;
}
EXPORT_SYMBOL(vga_switcheroo_register_handler);

void vga_switcheroo_unregister_handler(void)
{
	mutex_lock(&vgasr_mutex);
	vgasr_priv.handler = NULL;
	mutex_unlock(&vgasr_mutex);
}
EXPORT_SYMBOL(vga_switcheroo_unregister_handler);

static void vga_switcheroo_enable(void)
{
	int i;
	int ret;
	/* call the handler to init */
	vgasr_priv.handler->init();

	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
		ret = vgasr_priv.handler->get_client_id(vgasr_priv.clients[i].pdev);
		if (ret < 0)
			return;

		vgasr_priv.clients[i].id = ret;
	}
	vga_switcheroo_debugfs_init(&vgasr_priv);
	vgasr_priv.active = true;
}

int vga_switcheroo_register_client(struct pci_dev *pdev,
				   void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state),
				   void (*reprobe)(struct pci_dev *pdev),
				   bool (*can_switch)(struct pci_dev *pdev))
{
	int index;

	mutex_lock(&vgasr_mutex);
	/* don't do IGD vs DIS here */
	if (vgasr_priv.registered_clients & 1)
		index = 1;
	else
		index = 0;

	vgasr_priv.clients[index].pwr_state = VGA_SWITCHEROO_ON;
	vgasr_priv.clients[index].pdev = pdev;
	vgasr_priv.clients[index].set_gpu_state = set_gpu_state;
	vgasr_priv.clients[index].reprobe = reprobe;
	vgasr_priv.clients[index].can_switch = can_switch;
	vgasr_priv.clients[index].id = -1;
	if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
		vgasr_priv.clients[index].active = true;

	vgasr_priv.registered_clients |= (1 << index);

	/* if we get two clients + handler */
	if (vgasr_priv.registered_clients == 0x3 && vgasr_priv.handler) {
		printk(KERN_INFO "vga_switcheroo: enabled\n");
		vga_switcheroo_enable();
	}
	mutex_unlock(&vgasr_mutex);
	return 0;
}
EXPORT_SYMBOL(vga_switcheroo_register_client);

void vga_switcheroo_unregister_client(struct pci_dev *pdev)
{
	int i;

	mutex_lock(&vgasr_mutex);
	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
		if (vgasr_priv.clients[i].pdev == pdev) {
			vgasr_priv.registered_clients &= ~(1 << i);
			break;
		}
	}

	printk(KERN_INFO "vga_switcheroo: disabled\n");
	vga_switcheroo_debugfs_fini(&vgasr_priv);
	vgasr_priv.active = false;
	mutex_unlock(&vgasr_mutex);
}
EXPORT_SYMBOL(vga_switcheroo_unregister_client);

void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
				 struct fb_info *info)
{
	int i;

	mutex_lock(&vgasr_mutex);
	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
		if (vgasr_priv.clients[i].pdev == pdev) {
			vgasr_priv.clients[i].fb_info = info;
			break;
		}
	}
	mutex_unlock(&vgasr_mutex);
}
EXPORT_SYMBOL(vga_switcheroo_client_fb_set);

static int vga_switcheroo_show(struct seq_file *m, void *v)
{
	int i;
	mutex_lock(&vgasr_mutex);
	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
		seq_printf(m, "%d:%s:%c:%s:%s\n", i,
			   vgasr_priv.clients[i].id == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
			   vgasr_priv.clients[i].active ? '+' : ' ',
			   vgasr_priv.clients[i].pwr_state ? "Pwr" : "Off",
			   pci_name(vgasr_priv.clients[i].pdev));
	}
	mutex_unlock(&vgasr_mutex);
	return 0;
}

static int vga_switcheroo_debugfs_open(struct inode *inode, struct file *file)
{
	return single_open(file, vga_switcheroo_show, NULL);
}

static int vga_switchon(struct vga_switcheroo_client *client)
{
	if (vgasr_priv.handler->power_state)
		vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON);
	/* call the driver callback to turn on device */
	client->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON);
	client->pwr_state = VGA_SWITCHEROO_ON;
	return 0;
}

static int vga_switchoff(struct vga_switcheroo_client *client)
{
	/* call the driver callback to turn off device */
	client->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF);
	if (vgasr_priv.handler->power_state)
		vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
	client->pwr_state = VGA_SWITCHEROO_OFF;
	return 0;
}

/* stage one happens before delay */
static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
{
	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;

	if (new_client->pwr_state == VGA_SWITCHEROO_OFF)
		vga_switchon(new_client);

	/* swap shadow resource to denote boot VGA device has changed so X starts on new device */
	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;
		event.info = new_client->fb_info;
		fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
	}

	ret = vgasr_priv.handler->switchto(new_client->id);
	if (ret)
		return ret;

	if (new_client->reprobe)
		new_client->reprobe(new_client->pdev);

	if (active->pwr_state == VGA_SWITCHEROO_ON)
		vga_switchoff(active);

	new_client->active = true;
	return 0;
}

static ssize_t
vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
			     size_t cnt, loff_t *ppos)
{
	char usercmd[64];
	const char *pdev_name;
	int i, ret;
	bool delay = false, can_switch;
	bool just_mux = false;
	int client_id = -1;
	struct vga_switcheroo_client *client = NULL;

	if (cnt > 63)
		cnt = 63;

	if (copy_from_user(usercmd, ubuf, cnt))
		return -EFAULT;

	mutex_lock(&vgasr_mutex);

	if (!vgasr_priv.active) {
		cnt = -EINVAL;
		goto out;
	}

	/* pwr off the device not in use */
	if (strncmp(usercmd, "OFF", 3) == 0) {
		for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
			if (vgasr_priv.clients[i].active)
				continue;
			if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_ON)
				vga_switchoff(&vgasr_priv.clients[i]);
		}
		goto out;
	}
	/* pwr on the device not in use */
	if (strncmp(usercmd, "ON", 2) == 0) {
		for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
			if (vgasr_priv.clients[i].active)
				continue;
			if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_OFF)
				vga_switchon(&vgasr_priv.clients[i]);
		}
		goto out;
	}

	/* request a delayed switch - test can we switch now */
	if (strncmp(usercmd, "DIGD", 4) == 0) {
		client_id = VGA_SWITCHEROO_IGD;
		delay = true;
	}

	if (strncmp(usercmd, "DDIS", 4) == 0) {
		client_id = VGA_SWITCHEROO_DIS;
		delay = true;
	}

	if (strncmp(usercmd, "IGD", 3) == 0)
		client_id = VGA_SWITCHEROO_IGD;

	if (strncmp(usercmd, "DIS", 3) == 0)
		client_id = VGA_SWITCHEROO_DIS;

	if (strncmp(usercmd, "MIGD", 4) == 0) {
		just_mux = true;
		client_id = VGA_SWITCHEROO_IGD;
	}
	if (strncmp(usercmd, "MDIS", 4) == 0) {
		just_mux = true;
		client_id = VGA_SWITCHEROO_DIS;
	}

	if (client_id == -1)
		goto out;

	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
		if (vgasr_priv.clients[i].id == client_id) {
			client = &vgasr_priv.clients[i];
			break;
		}
	}

	vgasr_priv.delayed_switch_active = false;

	if (just_mux) {
		ret = vgasr_priv.handler->switchto(client_id);
		goto out;
	}

	if (client->active == true)
		goto out;

	/* okay we want a switch - test if devices are willing to switch */
	can_switch = true;
	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
		can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev);
		if (can_switch == false) {
			printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i);
			break;
		}
	}

	if (can_switch == false && delay == false)
		goto out;

	if (can_switch == true) {
		pdev_name = pci_name(client->pdev);
		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 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;

		ret = vga_switchto_stage1(client);
		if (ret)
			printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret);
	}

out:
	mutex_unlock(&vgasr_mutex);
	return cnt;
}

static const struct file_operations vga_switcheroo_debugfs_fops = {
	.owner = THIS_MODULE,
	.open = vga_switcheroo_debugfs_open,
	.write = vga_switcheroo_debugfs_write,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
};

static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv)
{
	if (priv->switch_file) {
		debugfs_remove(priv->switch_file);
		priv->switch_file = NULL;
	}
	if (priv->debugfs_root) {
		debugfs_remove(priv->debugfs_root);
		priv->debugfs_root = NULL;
	}
}

static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv)
{
	/* already initialised */
	if (priv->debugfs_root)
		return 0;
	priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL);

	if (!priv->debugfs_root) {
		printk(KERN_ERR "vga_switcheroo: Cannot create /sys/kernel/debug/vgaswitcheroo\n");
		goto fail;
	}

	priv->switch_file = debugfs_create_file("switch", 0644,
						priv->debugfs_root, NULL, &vga_switcheroo_debugfs_fops);
	if (!priv->switch_file) {
		printk(KERN_ERR "vga_switcheroo: cannot create /sys/kernel/debug/vgaswitcheroo/switch\n");
		goto fail;
	}
	return 0;
fail:
	vga_switcheroo_debugfs_fini(priv);
	return -1;
}

int vga_switcheroo_process_delayed_switch(void)
{
	struct vga_switcheroo_client *client = NULL;
	const char *pdev_name;
	bool can_switch = true;
	int i;
	int ret;
	int err = -EINVAL;

	mutex_lock(&vgasr_mutex);
	if (!vgasr_priv.delayed_switch_active)
		goto err;

	printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id);

	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
		if (vgasr_priv.clients[i].id == vgasr_priv.delayed_client_id)
			client = &vgasr_priv.clients[i];
		can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev);
		if (can_switch == false) {
			printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i);
			break;
		}
	}

	if (can_switch == false || client == NULL)
		goto err;

	pdev_name = pci_name(client->pdev);
	ret = vga_switchto_stage2(client);
	if (ret)
		printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret);

	vgasr_priv.delayed_switch_active = false;
	err = 0;
err:
	mutex_unlock(&vgasr_mutex);
	return err;
}
EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);

