/*
 * 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);
	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),
				   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].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:%c:%s:%s\n", i,
			   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)
{
	int ret;

	ret = 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);
	vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
	client->pwr_state = VGA_SWITCHEROO_OFF;
	return 0;
}

static int vga_switchto(struct vga_switcheroo_client *new_client)
{
	int ret;
	int i;
	struct vga_switcheroo_client *active = NULL;

	if (new_client->active == true)
		return 0;

	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;

	/* power up the first device */
	ret = pci_enable_device(new_client->pdev);
	if (ret)
		return ret;

	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->active = false;

	active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW;
	new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;

	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 (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;
	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)
		return -EINVAL;

	/* 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 (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;
	/* 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(client);
		if (ret)
			printk(KERN_ERR "vga_switcheroo: switching failed %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);
	}

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(client);
	if (ret)
		printk(KERN_ERR "vga_switcheroo: delayed switching failed %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);

