/*

    bt8xx GPIO abuser

    Copyright (C) 2008 Michael Buesch <m@bues.ch>

    Please do _only_ contact the people listed _above_ with issues related to this driver.
    All the other people listed below are not related to this driver. Their names
    are only here, because this driver is derived from the bt848 driver.


    Derived from the bt848 driver:

    Copyright (C) 1996,97,98 Ralph  Metzler
			   & Marcus Metzler
    (c) 1999-2002 Gerd Knorr

    some v4l2 code lines are taken from Justin's bttv2 driver which is
    (c) 2000 Justin Schoeman

    V4L1 removal from:
    (c) 2005-2006 Nickolay V. Shmyrev

    Fixes to be fully V4L2 compliant by
    (c) 2006 Mauro Carvalho Chehab

    Cropping and overscan support
    Copyright (C) 2005, 2006 Michael H. Schimek
    Sponsored by OPQ Systems AB

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/gpio/driver.h>
#include <linux/slab.h>

/* Steal the hardware definitions from the bttv driver. */
#include "../media/pci/bt8xx/bt848.h"


#define BT8XXGPIO_NR_GPIOS		24 /* We have 24 GPIO pins */


struct bt8xxgpio {
	spinlock_t lock;

	void __iomem *mmio;
	struct pci_dev *pdev;
	struct gpio_chip gpio;

#ifdef CONFIG_PM
	u32 saved_outen;
	u32 saved_data;
#endif
};

#define bgwrite(dat, adr)	writel((dat), bg->mmio+(adr))
#define bgread(adr)		readl(bg->mmio+(adr))


static int modparam_gpiobase = -1/* dynamic */;
module_param_named(gpiobase, modparam_gpiobase, int, 0444);
MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");


static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
{
	struct bt8xxgpio *bg = gpiochip_get_data(gpio);
	unsigned long flags;
	u32 outen, data;

	spin_lock_irqsave(&bg->lock, flags);

	data = bgread(BT848_GPIO_DATA);
	data &= ~(1 << nr);
	bgwrite(data, BT848_GPIO_DATA);

	outen = bgread(BT848_GPIO_OUT_EN);
	outen &= ~(1 << nr);
	bgwrite(outen, BT848_GPIO_OUT_EN);

	spin_unlock_irqrestore(&bg->lock, flags);

	return 0;
}

static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
{
	struct bt8xxgpio *bg = gpiochip_get_data(gpio);
	unsigned long flags;
	u32 val;

	spin_lock_irqsave(&bg->lock, flags);
	val = bgread(BT848_GPIO_DATA);
	spin_unlock_irqrestore(&bg->lock, flags);

	return !!(val & (1 << nr));
}

static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
					unsigned nr, int val)
{
	struct bt8xxgpio *bg = gpiochip_get_data(gpio);
	unsigned long flags;
	u32 outen, data;

	spin_lock_irqsave(&bg->lock, flags);

	outen = bgread(BT848_GPIO_OUT_EN);
	outen |= (1 << nr);
	bgwrite(outen, BT848_GPIO_OUT_EN);

	data = bgread(BT848_GPIO_DATA);
	if (val)
		data |= (1 << nr);
	else
		data &= ~(1 << nr);
	bgwrite(data, BT848_GPIO_DATA);

	spin_unlock_irqrestore(&bg->lock, flags);

	return 0;
}

static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
			    unsigned nr, int val)
{
	struct bt8xxgpio *bg = gpiochip_get_data(gpio);
	unsigned long flags;
	u32 data;

	spin_lock_irqsave(&bg->lock, flags);

	data = bgread(BT848_GPIO_DATA);
	if (val)
		data |= (1 << nr);
	else
		data &= ~(1 << nr);
	bgwrite(data, BT848_GPIO_DATA);

	spin_unlock_irqrestore(&bg->lock, flags);
}

static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
{
	struct gpio_chip *c = &bg->gpio;

	c->label = dev_name(&bg->pdev->dev);
	c->owner = THIS_MODULE;
	c->direction_input = bt8xxgpio_gpio_direction_input;
	c->get = bt8xxgpio_gpio_get;
	c->direction_output = bt8xxgpio_gpio_direction_output;
	c->set = bt8xxgpio_gpio_set;
	c->dbg_show = NULL;
	c->base = modparam_gpiobase;
	c->ngpio = BT8XXGPIO_NR_GPIOS;
	c->can_sleep = false;
}

static int bt8xxgpio_probe(struct pci_dev *dev,
			const struct pci_device_id *pci_id)
{
	struct bt8xxgpio *bg;
	int err;

	bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL);
	if (!bg)
		return -ENOMEM;

	bg->pdev = dev;
	spin_lock_init(&bg->lock);

	err = pci_enable_device(dev);
	if (err) {
		printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
		return err;
	}
	if (!devm_request_mem_region(&dev->dev, pci_resource_start(dev, 0),
				pci_resource_len(dev, 0),
				"bt8xxgpio")) {
		printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
		       (unsigned long long)pci_resource_start(dev, 0));
		err = -EBUSY;
		goto err_disable;
	}
	pci_set_master(dev);
	pci_set_drvdata(dev, bg);

	bg->mmio = devm_ioremap(&dev->dev, pci_resource_start(dev, 0), 0x1000);
	if (!bg->mmio) {
		printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
		err = -EIO;
		goto err_disable;
	}

	/* Disable interrupts */
	bgwrite(0, BT848_INT_MASK);

	/* gpio init */
	bgwrite(0, BT848_GPIO_DMA_CTL);
	bgwrite(0, BT848_GPIO_REG_INP);
	bgwrite(0, BT848_GPIO_OUT_EN);

	bt8xxgpio_gpio_setup(bg);
	err = gpiochip_add_data(&bg->gpio, bg);
	if (err) {
		printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
		goto err_disable;
	}

	return 0;

err_disable:
	pci_disable_device(dev);

	return err;
}

static void bt8xxgpio_remove(struct pci_dev *pdev)
{
	struct bt8xxgpio *bg = pci_get_drvdata(pdev);

	gpiochip_remove(&bg->gpio);

	bgwrite(0, BT848_INT_MASK);
	bgwrite(~0x0, BT848_INT_STAT);
	bgwrite(0x0, BT848_GPIO_OUT_EN);

	pci_disable_device(pdev);
}

#ifdef CONFIG_PM
static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
{
	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
	unsigned long flags;

	spin_lock_irqsave(&bg->lock, flags);

	bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
	bg->saved_data = bgread(BT848_GPIO_DATA);

	bgwrite(0, BT848_INT_MASK);
	bgwrite(~0x0, BT848_INT_STAT);
	bgwrite(0x0, BT848_GPIO_OUT_EN);

	spin_unlock_irqrestore(&bg->lock, flags);

	pci_save_state(pdev);
	pci_disable_device(pdev);
	pci_set_power_state(pdev, pci_choose_state(pdev, state));

	return 0;
}

static int bt8xxgpio_resume(struct pci_dev *pdev)
{
	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
	unsigned long flags;
	int err;

	pci_set_power_state(pdev, PCI_D0);
	err = pci_enable_device(pdev);
	if (err)
		return err;
	pci_restore_state(pdev);

	spin_lock_irqsave(&bg->lock, flags);

	bgwrite(0, BT848_INT_MASK);
	bgwrite(0, BT848_GPIO_DMA_CTL);
	bgwrite(0, BT848_GPIO_REG_INP);
	bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
	bgwrite(bg->saved_data & bg->saved_outen,
		BT848_GPIO_DATA);

	spin_unlock_irqrestore(&bg->lock, flags);

	return 0;
}
#else
#define bt8xxgpio_suspend NULL
#define bt8xxgpio_resume NULL
#endif /* CONFIG_PM */

static const struct pci_device_id bt8xxgpio_pci_tbl[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
	{ 0, },
};
MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);

static struct pci_driver bt8xxgpio_pci_driver = {
	.name		= "bt8xxgpio",
	.id_table	= bt8xxgpio_pci_tbl,
	.probe		= bt8xxgpio_probe,
	.remove		= bt8xxgpio_remove,
	.suspend	= bt8xxgpio_suspend,
	.resume		= bt8xxgpio_resume,
};

module_pci_driver(bt8xxgpio_pci_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michael Buesch");
MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
