/*
 *  Driver for tilt switches connected via GPIO lines
 *  not capable of generating interrupts
 *
 *  Copyright (C) 2011 Heiko Stuebner <heiko@sntech.de>
 *
 *  based on: drivers/input/keyboard/gpio_keys_polled.c
 *
 *  Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
 *  Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com>
 *
 *  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/slab.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/input/gpio_tilt.h>

#define DRV_NAME	"gpio-tilt-polled"

struct gpio_tilt_polled_dev {
	struct input_polled_dev *poll_dev;
	struct device *dev;
	const struct gpio_tilt_platform_data *pdata;

	int last_state;

	int threshold;
	int count;
};

static void gpio_tilt_polled_poll(struct input_polled_dev *dev)
{
	struct gpio_tilt_polled_dev *tdev = dev->private;
	const struct gpio_tilt_platform_data *pdata = tdev->pdata;
	struct input_dev *input = dev->input;
	struct gpio_tilt_state *tilt_state = NULL;
	int state, i;

	if (tdev->count < tdev->threshold) {
		tdev->count++;
	} else {
		state = 0;
		for (i = 0; i < pdata->nr_gpios; i++)
			state |= (!!gpio_get_value(pdata->gpios[i].gpio) << i);

		if (state != tdev->last_state) {
			for (i = 0; i < pdata->nr_states; i++)
				if (pdata->states[i].gpios == state)
					tilt_state = &pdata->states[i];

			if (tilt_state) {
				for (i = 0; i < pdata->nr_axes; i++)
					input_report_abs(input,
							 pdata->axes[i].axis,
							 tilt_state->axes[i]);

				input_sync(input);
			}

			tdev->count = 0;
			tdev->last_state = state;
		}
	}
}

static void gpio_tilt_polled_open(struct input_polled_dev *dev)
{
	struct gpio_tilt_polled_dev *tdev = dev->private;
	const struct gpio_tilt_platform_data *pdata = tdev->pdata;

	if (pdata->enable)
		pdata->enable(tdev->dev);

	/* report initial state of the axes */
	tdev->last_state = -1;
	tdev->count = tdev->threshold;
	gpio_tilt_polled_poll(tdev->poll_dev);
}

static void gpio_tilt_polled_close(struct input_polled_dev *dev)
{
	struct gpio_tilt_polled_dev *tdev = dev->private;
	const struct gpio_tilt_platform_data *pdata = tdev->pdata;

	if (pdata->disable)
		pdata->disable(tdev->dev);
}

static int gpio_tilt_polled_probe(struct platform_device *pdev)
{
	const struct gpio_tilt_platform_data *pdata =
			dev_get_platdata(&pdev->dev);
	struct device *dev = &pdev->dev;
	struct gpio_tilt_polled_dev *tdev;
	struct input_polled_dev *poll_dev;
	struct input_dev *input;
	int error, i;

	if (!pdata || !pdata->poll_interval)
		return -EINVAL;

	tdev = kzalloc(sizeof(struct gpio_tilt_polled_dev), GFP_KERNEL);
	if (!tdev) {
		dev_err(dev, "no memory for private data\n");
		return -ENOMEM;
	}

	error = gpio_request_array(pdata->gpios, pdata->nr_gpios);
	if (error) {
		dev_err(dev,
			"Could not request tilt GPIOs: %d\n", error);
		goto err_free_tdev;
	}

	poll_dev = input_allocate_polled_device();
	if (!poll_dev) {
		dev_err(dev, "no memory for polled device\n");
		error = -ENOMEM;
		goto err_free_gpios;
	}

	poll_dev->private = tdev;
	poll_dev->poll = gpio_tilt_polled_poll;
	poll_dev->poll_interval = pdata->poll_interval;
	poll_dev->open = gpio_tilt_polled_open;
	poll_dev->close = gpio_tilt_polled_close;

	input = poll_dev->input;

	input->name = pdev->name;
	input->phys = DRV_NAME"/input0";
	input->dev.parent = dev;

	input->id.bustype = BUS_HOST;
	input->id.vendor = 0x0001;
	input->id.product = 0x0001;
	input->id.version = 0x0100;

	__set_bit(EV_ABS, input->evbit);
	for (i = 0; i < pdata->nr_axes; i++)
		input_set_abs_params(input, pdata->axes[i].axis,
				     pdata->axes[i].min, pdata->axes[i].max,
				     pdata->axes[i].fuzz, pdata->axes[i].flat);

	tdev->threshold = DIV_ROUND_UP(pdata->debounce_interval,
				       pdata->poll_interval);

	tdev->poll_dev = poll_dev;
	tdev->dev = dev;
	tdev->pdata = pdata;

	error = input_register_polled_device(poll_dev);
	if (error) {
		dev_err(dev, "unable to register polled device, err=%d\n",
			error);
		goto err_free_polldev;
	}

	platform_set_drvdata(pdev, tdev);

	return 0;

err_free_polldev:
	input_free_polled_device(poll_dev);
err_free_gpios:
	gpio_free_array(pdata->gpios, pdata->nr_gpios);
err_free_tdev:
	kfree(tdev);

	return error;
}

static int gpio_tilt_polled_remove(struct platform_device *pdev)
{
	struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev);
	const struct gpio_tilt_platform_data *pdata = tdev->pdata;

	input_unregister_polled_device(tdev->poll_dev);
	input_free_polled_device(tdev->poll_dev);

	gpio_free_array(pdata->gpios, pdata->nr_gpios);

	kfree(tdev);

	return 0;
}

static struct platform_driver gpio_tilt_polled_driver = {
	.probe	= gpio_tilt_polled_probe,
	.remove	= gpio_tilt_polled_remove,
	.driver	= {
		.name	= DRV_NAME,
	},
};

module_platform_driver(gpio_tilt_polled_driver);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
MODULE_DESCRIPTION("Polled GPIO tilt driver");
MODULE_ALIAS("platform:" DRV_NAME);
