/*
 *  Driver for Freescale's 3-Axis Accelerometer MMA8450
 *
 *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 *  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/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input-polldev.h>

#define MMA8450_DRV_NAME	"mma8450"

#define MODE_CHANGE_DELAY_MS	100
#define POLL_INTERVAL		100
#define POLL_INTERVAL_MAX	500

/* register definitions */
#define MMA8450_STATUS		0x00
#define MMA8450_STATUS_ZXYDR	0x08

#define MMA8450_OUT_X8		0x01
#define MMA8450_OUT_Y8		0x02
#define MMA8450_OUT_Z8		0x03

#define MMA8450_OUT_X_LSB	0x05
#define MMA8450_OUT_X_MSB	0x06
#define MMA8450_OUT_Y_LSB	0x07
#define MMA8450_OUT_Y_MSB	0x08
#define MMA8450_OUT_Z_LSB	0x09
#define MMA8450_OUT_Z_MSB	0x0a

#define MMA8450_XYZ_DATA_CFG	0x16

#define MMA8450_CTRL_REG1	0x38
#define MMA8450_CTRL_REG2	0x39

/* mma8450 status */
struct mma8450 {
	struct i2c_client	*client;
	struct input_polled_dev	*idev;
};

static int mma8450_read(struct mma8450 *m, unsigned off)
{
	struct i2c_client *c = m->client;
	int ret;

	ret = i2c_smbus_read_byte_data(c, off);
	if (ret < 0)
		dev_err(&c->dev,
			"failed to read register 0x%02x, error %d\n",
			off, ret);

	return ret;
}

static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
{
	struct i2c_client *c = m->client;
	int error;

	error = i2c_smbus_write_byte_data(c, off, v);
	if (error < 0) {
		dev_err(&c->dev,
			"failed to write to register 0x%02x, error %d\n",
			off, error);
		return error;
	}

	return 0;
}

static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
{
	struct i2c_client *c = m->client;
	u8 buff[6];
	int err;

	err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff);
	if (err < 0) {
		dev_err(&c->dev,
			"failed to read block data at 0x%02x, error %d\n",
			MMA8450_OUT_X_LSB, err);
		return err;
	}

	*x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf);
	*y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf);
	*z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf);

	return 0;
}

static void mma8450_poll(struct input_polled_dev *dev)
{
	struct mma8450 *m = dev->private;
	int x, y, z;
	int ret;
	int err;

	ret = mma8450_read(m, MMA8450_STATUS);
	if (ret < 0)
		return;

	if (!(ret & MMA8450_STATUS_ZXYDR))
		return;

	err = mma8450_read_xyz(m, &x, &y, &z);
	if (err)
		return;

	input_report_abs(dev->input, ABS_X, x);
	input_report_abs(dev->input, ABS_Y, y);
	input_report_abs(dev->input, ABS_Z, z);
	input_sync(dev->input);
}

/* Initialize the MMA8450 chip */
static void mma8450_open(struct input_polled_dev *dev)
{
	struct mma8450 *m = dev->private;
	int err;

	/* enable all events from X/Y/Z, no FIFO */
	err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
	if (err)
		return;

	/*
	 * Sleep mode poll rate - 50Hz
	 * System output data rate - 400Hz
	 * Full scale selection - Active, +/- 2G
	 */
	err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
	if (err < 0)
		return;

	msleep(MODE_CHANGE_DELAY_MS);
}

static void mma8450_close(struct input_polled_dev *dev)
{
	struct mma8450 *m = dev->private;

	mma8450_write(m, MMA8450_CTRL_REG1, 0x00);
	mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
}

/*
 * I2C init/probing/exit functions
 */
static int __devinit mma8450_probe(struct i2c_client *c,
				   const struct i2c_device_id *id)
{
	struct input_polled_dev *idev;
	struct mma8450 *m;
	int err;

	m = kzalloc(sizeof(struct mma8450), GFP_KERNEL);
	idev = input_allocate_polled_device();
	if (!m || !idev) {
		err = -ENOMEM;
		goto err_free_mem;
	}

	m->client = c;
	m->idev = idev;

	idev->private		= m;
	idev->input->name	= MMA8450_DRV_NAME;
	idev->input->id.bustype	= BUS_I2C;
	idev->poll		= mma8450_poll;
	idev->poll_interval	= POLL_INTERVAL;
	idev->poll_interval_max	= POLL_INTERVAL_MAX;
	idev->open		= mma8450_open;
	idev->close		= mma8450_close;

	__set_bit(EV_ABS, idev->input->evbit);
	input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
	input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32);
	input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32);

	err = input_register_polled_device(idev);
	if (err) {
		dev_err(&c->dev, "failed to register polled input device\n");
		goto err_free_mem;
	}

	return 0;

err_free_mem:
	input_free_polled_device(idev);
	kfree(m);
	return err;
}

static int __devexit mma8450_remove(struct i2c_client *c)
{
	struct mma8450 *m = i2c_get_clientdata(c);
	struct input_polled_dev *idev = m->idev;

	input_unregister_polled_device(idev);
	input_free_polled_device(idev);
	kfree(m);

	return 0;
}

static const struct i2c_device_id mma8450_id[] = {
	{ MMA8450_DRV_NAME, 0 },
	{ },
};
MODULE_DEVICE_TABLE(i2c, mma8450_id);

static struct i2c_driver mma8450_driver = {
	.driver = {
		.name	= MMA8450_DRV_NAME,
		.owner	= THIS_MODULE,
	},
	.probe		= mma8450_probe,
	.remove		= __devexit_p(mma8450_remove),
	.id_table	= mma8450_id,
};

static int __init mma8450_init(void)
{
	return i2c_add_driver(&mma8450_driver);
}
module_init(mma8450_init);

static void __exit mma8450_exit(void)
{
	i2c_del_driver(&mma8450_driver);
}
module_exit(mma8450_exit);

MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver");
MODULE_LICENSE("GPL");
