/*
 * linux/drivers/input/keyboard/pxa27x_keyboard.c
 *
 * Driver for the pxa27x matrix keyboard controller.
 *
 * Created:	Feb 22, 2007
 * Author:	Rodolfo Giometti <giometti@linux.it>
 *
 * Based on a previous implementations by Kevin O'Connor
 * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
 * on some suggestions by Nicolas Pitre <nico@cam.org>.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/device.h>
#include <linux/platform_device.h>

#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/irqs.h>
#include <asm/arch/pxa27x_keyboard.h>

#define DRIVER_NAME		"pxa27x-keyboard"

#define KPASMKP(col)		(col/2 == 0 ? KPASMKP0 : \
				 col/2 == 1 ? KPASMKP1 : \
				 col/2 == 2 ? KPASMKP2 : KPASMKP3)
#define KPASMKPx_MKC(row, col)	(1 << (row + 16 * (col % 2)))

static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
{
	struct platform_device *pdev = dev_id;
	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
	struct input_dev *input_dev = platform_get_drvdata(pdev);
	unsigned long kpc = KPC;
	int p, row, col, rel;

	if (kpc & KPC_DI) {
		unsigned long kpdk = KPDK;

		if (!(kpdk & KPDK_DKP)) {
			/* better luck next time */
		} else if (kpc & KPC_REE0) {
			unsigned long kprec = KPREC;
			KPREC = 0x7f;

			if (kprec & KPREC_OF0)
				rel = (kprec & 0xff) + 0x7f;
			else if (kprec & KPREC_UF0)
				rel = (kprec & 0xff) - 0x7f - 0xff;
			else
				rel = (kprec & 0xff) - 0x7f;

			if (rel) {
				input_report_rel(input_dev, REL_WHEEL, rel);
				input_sync(input_dev);
			}
		}
	}

	if (kpc & KPC_MI) {
		/* report the status of every button */
		for (row = 0; row < pdata->nr_rows; row++) {
			for (col = 0; col < pdata->nr_cols; col++) {
				p = KPASMKP(col) & KPASMKPx_MKC(row, col) ?
					1 : 0;
				pr_debug("keycode %x - pressed %x\n",
						pdata->keycodes[row][col], p);
				input_report_key(input_dev,
						pdata->keycodes[row][col], p);
			}
		}
		input_sync(input_dev);
	}

	return IRQ_HANDLED;
}

static int pxakbd_open(struct input_dev *dev)
{
	/* Set keypad control register */
	KPC |= (KPC_ASACT |
		KPC_MS_ALL |
		(2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL |
		KPC_ME | KPC_MIE | KPC_DE | KPC_DIE);

	KPC &= ~KPC_AS;         /* disable automatic scan */
	KPC &= ~KPC_IMKP;       /* do not ignore multiple keypresses */

	/* Set rotary count to mid-point value */
	KPREC = 0x7F;

	/* Enable unit clock */
	pxa_set_cken(CKEN_KEYPAD, 1);

	return 0;
}

static void pxakbd_close(struct input_dev *dev)
{
	/* Disable clock unit */
	pxa_set_cken(CKEN_KEYPAD, 0);
}

#ifdef CONFIG_PM
static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;

	/* Save controller status */
	pdata->reg_kpc = KPC;
	pdata->reg_kprec = KPREC;

	return 0;
}

static int pxakbd_resume(struct platform_device *pdev)
{
	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
	struct input_dev *input_dev = platform_get_drvdata(pdev);

	mutex_lock(&input_dev->mutex);

	if (input_dev->users) {
		/* Restore controller status */
		KPC = pdata->reg_kpc;
		KPREC = pdata->reg_kprec;

		/* Enable unit clock */
		pxa_set_cken(CKEN19_KEYPAD, 1);
	}

	mutex_unlock(&input_dev->mutex);

	return 0;
}
#else
#define pxakbd_suspend	NULL
#define pxakbd_resume	NULL
#endif

static int __devinit pxakbd_probe(struct platform_device *pdev)
{
	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
	struct input_dev *input_dev;
	int i, row, col, error;

	/* Create and register the input driver. */
	input_dev = input_allocate_device();
	if (!input_dev) {
		printk(KERN_ERR "Cannot request keypad device\n");
		return -ENOMEM;
	}

	input_dev->name = DRIVER_NAME;
	input_dev->id.bustype = BUS_HOST;
	input_dev->open = pxakbd_open;
	input_dev->close = pxakbd_close;
	input_dev->dev.parent = &pdev->dev;

	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
	input_dev->relbit[LONG(REL_WHEEL)] = BIT(REL_WHEEL);
	for (row = 0; row < pdata->nr_rows; row++) {
		for (col = 0; col < pdata->nr_cols; col++) {
			int code = pdata->keycodes[row][col];
			if (code > 0)
				set_bit(code, input_dev->keybit);
		}
	}

	error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED,
			    DRIVER_NAME, pdev);
	if (error) {
		printk(KERN_ERR "Cannot request keypad IRQ\n");
		pxa_set_cken(CKEN_KEYPAD, 0);
		goto err_free_dev;
	}

	platform_set_drvdata(pdev, input_dev);

	/* Register the input device */
	error = input_register_device(input_dev);
	if (error)
		goto err_free_irq;

	/* Setup GPIOs. */
	for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++)
		pxa_gpio_mode(pdata->gpio_modes[i]);

	/*
	 * Store rows/cols info into keyboard registers.
	 */

	KPC |= (pdata->nr_rows - 1) << 26;
	KPC |= (pdata->nr_cols - 1) << 23;

	for (col = 0; col < pdata->nr_cols; col++)
		KPC |= KPC_MS0 << col;

	return 0;

 err_free_irq:
	platform_set_drvdata(pdev, NULL);
	free_irq(IRQ_KEYPAD, pdev);
 err_free_dev:
	input_free_device(input_dev);
	return error;
}

static int __devexit pxakbd_remove(struct platform_device *pdev)
{
	struct input_dev *input_dev = platform_get_drvdata(pdev);

	input_unregister_device(input_dev);
	free_irq(IRQ_KEYPAD, pdev);
	platform_set_drvdata(pdev, NULL);

	return 0;
}

static struct platform_driver pxakbd_driver = {
	.probe		= pxakbd_probe,
	.remove		= __devexit_p(pxakbd_remove),
	.suspend	= pxakbd_suspend,
	.resume		= pxakbd_resume,
	.driver		= {
		.name	= DRIVER_NAME,
	},
};

static int __init pxakbd_init(void)
{
	return platform_driver_register(&pxakbd_driver);
}

static void __exit pxakbd_exit(void)
{
	platform_driver_unregister(&pxakbd_driver);
}

module_init(pxakbd_init);
module_exit(pxakbd_exit);

MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver");
MODULE_LICENSE("GPL");
