14397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger/*
24397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger * AD7879-1/AD7889-1 touchscreen (I2C bus)
34397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger *
44397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger * Copyright (C) 2008-2010 Michael Hennerich, Analog Devices Inc.
54397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger *
64397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger * Licensed under the GPL-2 or later.
74397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger */
84397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
94397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger#include <linux/input.h>	/* BUS_I2C */
104397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger#include <linux/i2c.h>
114397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger#include <linux/module.h>
124397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger#include <linux/types.h>
13d5dc9ac3f6daf7df45c49e5a861c733a5f794c6bMark Brown#include <linux/pm.h>
144397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
154397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger#include "ad7879.h"
164397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
174397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger#define AD7879_DEVID		0x79	/* AD7879-1/AD7889-1 */
184397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
194397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger/* All registers are word-sized.
204397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger * AD7879 uses a high-byte first convention.
214397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger */
224397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic int ad7879_i2c_read(struct device *dev, u8 reg)
234397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger{
244397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	struct i2c_client *client = to_i2c_client(dev);
254397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
2675255b29d473613e2a5737d6fb368dc4009c90a8Jonathan Cameron	return i2c_smbus_read_word_swapped(client, reg);
274397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger}
284397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
294397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic int ad7879_i2c_multi_read(struct device *dev,
304397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger				 u8 first_reg, u8 count, u16 *buf)
314397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger{
3216ea10a7d557a0177cbbd716b4a06e5373d513baMichael Hennerich	struct i2c_client *client = to_i2c_client(dev);
334397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	u8 idx;
344397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
3516ea10a7d557a0177cbbd716b4a06e5373d513baMichael Hennerich	i2c_smbus_read_i2c_block_data(client, first_reg, count * 2, (u8 *)buf);
3616ea10a7d557a0177cbbd716b4a06e5373d513baMichael Hennerich
374397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	for (idx = 0; idx < count; ++idx)
3816ea10a7d557a0177cbbd716b4a06e5373d513baMichael Hennerich		buf[idx] = swab16(buf[idx]);
394397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
404397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	return 0;
414397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger}
424397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
434397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic int ad7879_i2c_write(struct device *dev, u8 reg, u16 val)
444397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger{
454397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	struct i2c_client *client = to_i2c_client(dev);
464397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
4775255b29d473613e2a5737d6fb368dc4009c90a8Jonathan Cameron	return i2c_smbus_write_word_swapped(client, reg, val);
484397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger}
494397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
504397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic const struct ad7879_bus_ops ad7879_i2c_bus_ops = {
514397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	.bustype	= BUS_I2C,
524397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	.read		= ad7879_i2c_read,
534397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	.multi_read	= ad7879_i2c_multi_read,
544397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	.write		= ad7879_i2c_write,
554397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger};
564397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
574397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic int __devinit ad7879_i2c_probe(struct i2c_client *client,
584397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger				      const struct i2c_device_id *id)
594397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger{
604397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	struct ad7879 *ts;
614397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
624397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	if (!i2c_check_functionality(client->adapter,
634397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger				     I2C_FUNC_SMBUS_WORD_DATA)) {
644397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		dev_err(&client->dev, "SMBUS Word Data not Supported\n");
654397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		return -EIO;
664397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	}
674397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
684397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ts = ad7879_probe(&client->dev, AD7879_DEVID, client->irq,
694397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger			  &ad7879_i2c_bus_ops);
704397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	if (IS_ERR(ts))
714397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		return PTR_ERR(ts);
724397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
734397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	i2c_set_clientdata(client, ts);
744397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
754397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	return 0;
764397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger}
774397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
784397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic int __devexit ad7879_i2c_remove(struct i2c_client *client)
794397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger{
804397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	struct ad7879 *ts = i2c_get_clientdata(client);
814397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
824397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ad7879_remove(ts);
834397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
844397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	return 0;
854397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger}
864397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
874397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic const struct i2c_device_id ad7879_id[] = {
884397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	{ "ad7879", 0 },
894397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	{ "ad7889", 0 },
904397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	{ }
914397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger};
924397c98a8a60ba029f2d0051d0cbafe600f05d8cMike FrysingerMODULE_DEVICE_TABLE(i2c, ad7879_id);
934397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
944397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic struct i2c_driver ad7879_i2c_driver = {
954397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	.driver = {
964397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		.name	= "ad7879",
974397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		.owner	= THIS_MODULE,
988672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov		.pm	= &ad7879_pm_ops,
994397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	},
1004397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	.probe		= ad7879_i2c_probe,
1014397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	.remove		= __devexit_p(ad7879_i2c_remove),
1024397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	.id_table	= ad7879_id,
1034397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger};
1044397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
1051b92c1cf6b638e7cbe9fdaac3f6efb8874f5cc02Axel Linmodule_i2c_driver(ad7879_i2c_driver);
1064397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
1074397c98a8a60ba029f2d0051d0cbafe600f05d8cMike FrysingerMODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
1084397c98a8a60ba029f2d0051d0cbafe600f05d8cMike FrysingerMODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver");
1094397c98a8a60ba029f2d0051d0cbafe600f05d8cMike FrysingerMODULE_LICENSE("GPL");
110