Path: blob/master/drivers/input/touchscreen/ad7879.c
15111 views
/*1* AD7879/AD7889 based touchscreen and GPIO driver2*3* Copyright (C) 2008-2010 Michael Hennerich, Analog Devices Inc.4*5* Licensed under the GPL-2 or later.6*7* History:8* Copyright (c) 2005 David Brownell9* Copyright (c) 2006 Nokia Corporation10* Various changes: Imre Deak <[email protected]>11*12* Using code from:13* - corgi_ts.c14* Copyright (C) 2004-2005 Richard Purdie15* - omap_ts.[hc], ads7846.h, ts_osk.c16* Copyright (C) 2002 MontaVista Software17* Copyright (C) 2004 Texas Instruments18* Copyright (C) 2005 Dirk Behme19* - ad7877.c20* Copyright (C) 2006-2008 Analog Devices Inc.21*/2223#include <linux/device.h>24#include <linux/init.h>25#include <linux/delay.h>26#include <linux/input.h>27#include <linux/interrupt.h>28#include <linux/irq.h>29#include <linux/slab.h>30#include <linux/spi/spi.h>31#include <linux/i2c.h>32#include <linux/gpio.h>3334#include <linux/spi/ad7879.h>35#include "ad7879.h"3637#define AD7879_REG_ZEROS 038#define AD7879_REG_CTRL1 139#define AD7879_REG_CTRL2 240#define AD7879_REG_CTRL3 341#define AD7879_REG_AUX1HIGH 442#define AD7879_REG_AUX1LOW 543#define AD7879_REG_TEMP1HIGH 644#define AD7879_REG_TEMP1LOW 745#define AD7879_REG_XPLUS 846#define AD7879_REG_YPLUS 947#define AD7879_REG_Z1 1048#define AD7879_REG_Z2 1149#define AD7879_REG_AUXVBAT 1250#define AD7879_REG_TEMP 1351#define AD7879_REG_REVID 145253/* Control REG 1 */54#define AD7879_TMR(x) ((x & 0xFF) << 0)55#define AD7879_ACQ(x) ((x & 0x3) << 8)56#define AD7879_MODE_NOC (0 << 10) /* Do not convert */57#define AD7879_MODE_SCC (1 << 10) /* Single channel conversion */58#define AD7879_MODE_SEQ0 (2 << 10) /* Sequence 0 in Slave Mode */59#define AD7879_MODE_SEQ1 (3 << 10) /* Sequence 1 in Master Mode */60#define AD7879_MODE_INT (1 << 15) /* PENIRQ disabled INT enabled */6162/* Control REG 2 */63#define AD7879_FCD(x) ((x & 0x3) << 0)64#define AD7879_RESET (1 << 4)65#define AD7879_MFS(x) ((x & 0x3) << 5)66#define AD7879_AVG(x) ((x & 0x3) << 7)67#define AD7879_SER (1 << 9) /* non-differential */68#define AD7879_DFR (0 << 9) /* differential */69#define AD7879_GPIOPOL (1 << 10)70#define AD7879_GPIODIR (1 << 11)71#define AD7879_GPIO_DATA (1 << 12)72#define AD7879_GPIO_EN (1 << 13)73#define AD7879_PM(x) ((x & 0x3) << 14)74#define AD7879_PM_SHUTDOWN (0)75#define AD7879_PM_DYN (1)76#define AD7879_PM_FULLON (2)7778/* Control REG 3 */79#define AD7879_TEMPMASK_BIT (1<<15)80#define AD7879_AUXVBATMASK_BIT (1<<14)81#define AD7879_INTMODE_BIT (1<<13)82#define AD7879_GPIOALERTMASK_BIT (1<<12)83#define AD7879_AUXLOW_BIT (1<<11)84#define AD7879_AUXHIGH_BIT (1<<10)85#define AD7879_TEMPLOW_BIT (1<<9)86#define AD7879_TEMPHIGH_BIT (1<<8)87#define AD7879_YPLUS_BIT (1<<7)88#define AD7879_XPLUS_BIT (1<<6)89#define AD7879_Z1_BIT (1<<5)90#define AD7879_Z2_BIT (1<<4)91#define AD7879_AUX_BIT (1<<3)92#define AD7879_VBAT_BIT (1<<2)93#define AD7879_TEMP_BIT (1<<1)9495enum {96AD7879_SEQ_XPOS = 0,97AD7879_SEQ_YPOS = 1,98AD7879_SEQ_Z1 = 2,99AD7879_SEQ_Z2 = 3,100AD7879_NR_SENSE = 4,101};102103#define MAX_12BIT ((1<<12)-1)104#define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50)105106struct ad7879 {107const struct ad7879_bus_ops *bops;108109struct device *dev;110struct input_dev *input;111struct timer_list timer;112#ifdef CONFIG_GPIOLIB113struct gpio_chip gc;114struct mutex mutex;115#endif116unsigned int irq;117bool disabled; /* P: input->mutex */118bool suspended; /* P: input->mutex */119u16 conversion_data[AD7879_NR_SENSE];120char phys[32];121u8 first_conversion_delay;122u8 acquisition_time;123u8 averaging;124u8 pen_down_acc_interval;125u8 median;126u16 x_plate_ohms;127u16 pressure_max;128u16 cmd_crtl1;129u16 cmd_crtl2;130u16 cmd_crtl3;131int x;132int y;133int Rt;134};135136static int ad7879_read(struct ad7879 *ts, u8 reg)137{138return ts->bops->read(ts->dev, reg);139}140141static int ad7879_multi_read(struct ad7879 *ts, u8 first_reg, u8 count, u16 *buf)142{143return ts->bops->multi_read(ts->dev, first_reg, count, buf);144}145146static int ad7879_write(struct ad7879 *ts, u8 reg, u16 val)147{148return ts->bops->write(ts->dev, reg, val);149}150151static int ad7879_report(struct ad7879 *ts)152{153struct input_dev *input_dev = ts->input;154unsigned Rt;155u16 x, y, z1, z2;156157x = ts->conversion_data[AD7879_SEQ_XPOS] & MAX_12BIT;158y = ts->conversion_data[AD7879_SEQ_YPOS] & MAX_12BIT;159z1 = ts->conversion_data[AD7879_SEQ_Z1] & MAX_12BIT;160z2 = ts->conversion_data[AD7879_SEQ_Z2] & MAX_12BIT;161162/*163* The samples processed here are already preprocessed by the AD7879.164* The preprocessing function consists of a median and an averaging165* filter. The combination of these two techniques provides a robust166* solution, discarding the spurious noise in the signal and keeping167* only the data of interest. The size of both filters is168* programmable. (dev.platform_data, see linux/spi/ad7879.h) Other169* user-programmable conversion controls include variable acquisition170* time, and first conversion delay. Up to 16 averages can be taken171* per conversion.172*/173174if (likely(x && z1)) {175/* compute touch pressure resistance using equation #1 */176Rt = (z2 - z1) * x * ts->x_plate_ohms;177Rt /= z1;178Rt = (Rt + 2047) >> 12;179180/*181* Sample found inconsistent, pressure is beyond182* the maximum. Don't report it to user space.183*/184if (Rt > ts->pressure_max)185return -EINVAL;186187/*188* Note that we delay reporting events by one sample.189* This is done to avoid reporting last sample of the190* touch sequence, which may be incomplete if finger191* leaves the surface before last reading is taken.192*/193if (timer_pending(&ts->timer)) {194/* Touch continues */195input_report_key(input_dev, BTN_TOUCH, 1);196input_report_abs(input_dev, ABS_X, ts->x);197input_report_abs(input_dev, ABS_Y, ts->y);198input_report_abs(input_dev, ABS_PRESSURE, ts->Rt);199input_sync(input_dev);200}201202ts->x = x;203ts->y = y;204ts->Rt = Rt;205206return 0;207}208209return -EINVAL;210}211212static void ad7879_ts_event_release(struct ad7879 *ts)213{214struct input_dev *input_dev = ts->input;215216input_report_abs(input_dev, ABS_PRESSURE, 0);217input_report_key(input_dev, BTN_TOUCH, 0);218input_sync(input_dev);219}220221static void ad7879_timer(unsigned long handle)222{223struct ad7879 *ts = (void *)handle;224225ad7879_ts_event_release(ts);226}227228static irqreturn_t ad7879_irq(int irq, void *handle)229{230struct ad7879 *ts = handle;231232ad7879_multi_read(ts, AD7879_REG_XPLUS, AD7879_NR_SENSE, ts->conversion_data);233234if (!ad7879_report(ts))235mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);236237return IRQ_HANDLED;238}239240static void __ad7879_enable(struct ad7879 *ts)241{242ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);243ad7879_write(ts, AD7879_REG_CTRL3, ts->cmd_crtl3);244ad7879_write(ts, AD7879_REG_CTRL1, ts->cmd_crtl1);245246enable_irq(ts->irq);247}248249static void __ad7879_disable(struct ad7879 *ts)250{251disable_irq(ts->irq);252253if (del_timer_sync(&ts->timer))254ad7879_ts_event_release(ts);255256ad7879_write(ts, AD7879_REG_CTRL2, AD7879_PM(AD7879_PM_SHUTDOWN));257}258259260static int ad7879_open(struct input_dev *input)261{262struct ad7879 *ts = input_get_drvdata(input);263264/* protected by input->mutex */265if (!ts->disabled && !ts->suspended)266__ad7879_enable(ts);267268return 0;269}270271static void ad7879_close(struct input_dev* input)272{273struct ad7879 *ts = input_get_drvdata(input);274275/* protected by input->mutex */276if (!ts->disabled && !ts->suspended)277__ad7879_disable(ts);278}279280void ad7879_suspend(struct ad7879 *ts)281{282mutex_lock(&ts->input->mutex);283284if (!ts->suspended && !ts->disabled && ts->input->users)285__ad7879_disable(ts);286287ts->suspended = true;288289mutex_unlock(&ts->input->mutex);290}291EXPORT_SYMBOL(ad7879_suspend);292293void ad7879_resume(struct ad7879 *ts)294{295mutex_lock(&ts->input->mutex);296297if (ts->suspended && !ts->disabled && ts->input->users)298__ad7879_enable(ts);299300ts->suspended = false;301302mutex_unlock(&ts->input->mutex);303}304EXPORT_SYMBOL(ad7879_resume);305306static void ad7879_toggle(struct ad7879 *ts, bool disable)307{308mutex_lock(&ts->input->mutex);309310if (!ts->suspended && ts->input->users != 0) {311312if (disable) {313if (ts->disabled)314__ad7879_enable(ts);315} else {316if (!ts->disabled)317__ad7879_disable(ts);318}319}320321ts->disabled = disable;322323mutex_unlock(&ts->input->mutex);324}325326static ssize_t ad7879_disable_show(struct device *dev,327struct device_attribute *attr, char *buf)328{329struct ad7879 *ts = dev_get_drvdata(dev);330331return sprintf(buf, "%u\n", ts->disabled);332}333334static ssize_t ad7879_disable_store(struct device *dev,335struct device_attribute *attr,336const char *buf, size_t count)337{338struct ad7879 *ts = dev_get_drvdata(dev);339unsigned long val;340int error;341342error = strict_strtoul(buf, 10, &val);343if (error)344return error;345346ad7879_toggle(ts, val);347348return count;349}350351static DEVICE_ATTR(disable, 0664, ad7879_disable_show, ad7879_disable_store);352353static struct attribute *ad7879_attributes[] = {354&dev_attr_disable.attr,355NULL356};357358static const struct attribute_group ad7879_attr_group = {359.attrs = ad7879_attributes,360};361362#ifdef CONFIG_GPIOLIB363static int ad7879_gpio_direction_input(struct gpio_chip *chip,364unsigned gpio)365{366struct ad7879 *ts = container_of(chip, struct ad7879, gc);367int err;368369mutex_lock(&ts->mutex);370ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIODIR | AD7879_GPIOPOL;371err = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);372mutex_unlock(&ts->mutex);373374return err;375}376377static int ad7879_gpio_direction_output(struct gpio_chip *chip,378unsigned gpio, int level)379{380struct ad7879 *ts = container_of(chip, struct ad7879, gc);381int err;382383mutex_lock(&ts->mutex);384ts->cmd_crtl2 &= ~AD7879_GPIODIR;385ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIOPOL;386if (level)387ts->cmd_crtl2 |= AD7879_GPIO_DATA;388else389ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;390391err = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);392mutex_unlock(&ts->mutex);393394return err;395}396397static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio)398{399struct ad7879 *ts = container_of(chip, struct ad7879, gc);400u16 val;401402mutex_lock(&ts->mutex);403val = ad7879_read(ts, AD7879_REG_CTRL2);404mutex_unlock(&ts->mutex);405406return !!(val & AD7879_GPIO_DATA);407}408409static void ad7879_gpio_set_value(struct gpio_chip *chip,410unsigned gpio, int value)411{412struct ad7879 *ts = container_of(chip, struct ad7879, gc);413414mutex_lock(&ts->mutex);415if (value)416ts->cmd_crtl2 |= AD7879_GPIO_DATA;417else418ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;419420ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);421mutex_unlock(&ts->mutex);422}423424static int ad7879_gpio_add(struct ad7879 *ts,425const struct ad7879_platform_data *pdata)426{427int ret = 0;428429mutex_init(&ts->mutex);430431if (pdata->gpio_export) {432ts->gc.direction_input = ad7879_gpio_direction_input;433ts->gc.direction_output = ad7879_gpio_direction_output;434ts->gc.get = ad7879_gpio_get_value;435ts->gc.set = ad7879_gpio_set_value;436ts->gc.can_sleep = 1;437ts->gc.base = pdata->gpio_base;438ts->gc.ngpio = 1;439ts->gc.label = "AD7879-GPIO";440ts->gc.owner = THIS_MODULE;441ts->gc.dev = ts->dev;442443ret = gpiochip_add(&ts->gc);444if (ret)445dev_err(ts->dev, "failed to register gpio %d\n",446ts->gc.base);447}448449return ret;450}451452static void ad7879_gpio_remove(struct ad7879 *ts)453{454const struct ad7879_platform_data *pdata = ts->dev->platform_data;455int ret;456457if (pdata->gpio_export) {458ret = gpiochip_remove(&ts->gc);459if (ret)460dev_err(ts->dev, "failed to remove gpio %d\n",461ts->gc.base);462}463}464#else465static inline int ad7879_gpio_add(struct ad7879 *ts,466const struct ad7879_platform_data *pdata)467{468return 0;469}470471static inline void ad7879_gpio_remove(struct ad7879 *ts)472{473}474#endif475476struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,477const struct ad7879_bus_ops *bops)478{479struct ad7879_platform_data *pdata = dev->platform_data;480struct ad7879 *ts;481struct input_dev *input_dev;482int err;483u16 revid;484485if (!irq) {486dev_err(dev, "no IRQ?\n");487err = -EINVAL;488goto err_out;489}490491if (!pdata) {492dev_err(dev, "no platform data?\n");493err = -EINVAL;494goto err_out;495}496497ts = kzalloc(sizeof(*ts), GFP_KERNEL);498input_dev = input_allocate_device();499if (!ts || !input_dev) {500err = -ENOMEM;501goto err_free_mem;502}503504ts->bops = bops;505ts->dev = dev;506ts->input = input_dev;507ts->irq = irq;508509setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts);510511ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;512ts->pressure_max = pdata->pressure_max ? : ~0;513514ts->first_conversion_delay = pdata->first_conversion_delay;515ts->acquisition_time = pdata->acquisition_time;516ts->averaging = pdata->averaging;517ts->pen_down_acc_interval = pdata->pen_down_acc_interval;518ts->median = pdata->median;519520snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));521522input_dev->name = "AD7879 Touchscreen";523input_dev->phys = ts->phys;524input_dev->dev.parent = dev;525input_dev->id.bustype = bops->bustype;526527input_dev->open = ad7879_open;528input_dev->close = ad7879_close;529530input_set_drvdata(input_dev, ts);531532__set_bit(EV_ABS, input_dev->evbit);533__set_bit(ABS_X, input_dev->absbit);534__set_bit(ABS_Y, input_dev->absbit);535__set_bit(ABS_PRESSURE, input_dev->absbit);536537__set_bit(EV_KEY, input_dev->evbit);538__set_bit(BTN_TOUCH, input_dev->keybit);539540input_set_abs_params(input_dev, ABS_X,541pdata->x_min ? : 0,542pdata->x_max ? : MAX_12BIT,5430, 0);544input_set_abs_params(input_dev, ABS_Y,545pdata->y_min ? : 0,546pdata->y_max ? : MAX_12BIT,5470, 0);548input_set_abs_params(input_dev, ABS_PRESSURE,549pdata->pressure_min, pdata->pressure_max, 0, 0);550551err = ad7879_write(ts, AD7879_REG_CTRL2, AD7879_RESET);552if (err < 0) {553dev_err(dev, "Failed to write %s\n", input_dev->name);554goto err_free_mem;555}556557revid = ad7879_read(ts, AD7879_REG_REVID);558input_dev->id.product = (revid & 0xff);559input_dev->id.version = revid >> 8;560if (input_dev->id.product != devid) {561dev_err(dev, "Failed to probe %s (%x vs %x)\n",562input_dev->name, devid, revid);563err = -ENODEV;564goto err_free_mem;565}566567ts->cmd_crtl3 = AD7879_YPLUS_BIT |568AD7879_XPLUS_BIT |569AD7879_Z2_BIT |570AD7879_Z1_BIT |571AD7879_TEMPMASK_BIT |572AD7879_AUXVBATMASK_BIT |573AD7879_GPIOALERTMASK_BIT;574575ts->cmd_crtl2 = AD7879_PM(AD7879_PM_DYN) | AD7879_DFR |576AD7879_AVG(ts->averaging) |577AD7879_MFS(ts->median) |578AD7879_FCD(ts->first_conversion_delay);579580ts->cmd_crtl1 = AD7879_MODE_INT | AD7879_MODE_SEQ1 |581AD7879_ACQ(ts->acquisition_time) |582AD7879_TMR(ts->pen_down_acc_interval);583584err = request_threaded_irq(ts->irq, NULL, ad7879_irq,585IRQF_TRIGGER_FALLING,586dev_name(dev), ts);587if (err) {588dev_err(dev, "irq %d busy?\n", ts->irq);589goto err_free_mem;590}591592__ad7879_disable(ts);593594err = sysfs_create_group(&dev->kobj, &ad7879_attr_group);595if (err)596goto err_free_irq;597598err = ad7879_gpio_add(ts, pdata);599if (err)600goto err_remove_attr;601602err = input_register_device(input_dev);603if (err)604goto err_remove_gpio;605606return ts;607608err_remove_gpio:609ad7879_gpio_remove(ts);610err_remove_attr:611sysfs_remove_group(&dev->kobj, &ad7879_attr_group);612err_free_irq:613free_irq(ts->irq, ts);614err_free_mem:615input_free_device(input_dev);616kfree(ts);617err_out:618return ERR_PTR(err);619}620EXPORT_SYMBOL(ad7879_probe);621622void ad7879_remove(struct ad7879 *ts)623{624ad7879_gpio_remove(ts);625sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group);626free_irq(ts->irq, ts);627input_unregister_device(ts->input);628kfree(ts);629}630EXPORT_SYMBOL(ad7879_remove);631632MODULE_AUTHOR("Michael Hennerich <[email protected]>");633MODULE_DESCRIPTION("AD7879(-1) touchscreen Driver");634MODULE_LICENSE("GPL");635636637