814 lines · 19.3 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* * Copyright (C) 2006-2008 Michael Hennerich, Analog Devices Inc. * * Description:	AD7877 based touchscreen, sensor (ADCs), DAC and GPIO driver * Based on:	ads7846.c * * Bugs:        Enter bugs at http://blackfin.uclinux.org/ * * History: * Copyright (c) 2005 David Brownell * Copyright (c) 2006 Nokia Corporation * Various changes: Imre Deak <imre.deak@nokia.com> * * Using code from: *  - corgi_ts.c *	Copyright (C) 2004-2005 Richard Purdie *  - omap_ts.[hc], ads7846.h, ts_osk.c *	Copyright (C) 2002 MontaVista Software *	Copyright (C) 2004 Texas Instruments *	Copyright (C) 2005 Dirk Behme */  #include <linux/device.h>#include <linux/delay.h>#include <linux/input.h>#include <linux/interrupt.h>#include <linux/pm.h>#include <linux/slab.h>#include <linux/spi/spi.h>#include <linux/spi/ad7877.h>#include <linux/module.h>#include <asm/irq.h> #define	TS_PEN_UP_TIMEOUT	msecs_to_jiffies(100) #define MAX_SPI_FREQ_HZ			20000000#define	MAX_12BIT			((1<<12)-1) #define AD7877_REG_ZEROS			0#define AD7877_REG_CTRL1			1#define AD7877_REG_CTRL2			2#define AD7877_REG_ALERT			3#define AD7877_REG_AUX1HIGH			4#define AD7877_REG_AUX1LOW			5#define AD7877_REG_BAT1HIGH			6#define AD7877_REG_BAT1LOW			7#define AD7877_REG_BAT2HIGH			8#define AD7877_REG_BAT2LOW			9#define AD7877_REG_TEMP1HIGH			10#define AD7877_REG_TEMP1LOW			11#define AD7877_REG_SEQ0				12#define AD7877_REG_SEQ1				13#define AD7877_REG_DAC				14#define AD7877_REG_NONE1			15#define AD7877_REG_EXTWRITE			15#define AD7877_REG_XPLUS			16#define AD7877_REG_YPLUS			17#define AD7877_REG_Z2				18#define AD7877_REG_aux1				19#define AD7877_REG_aux2				20#define AD7877_REG_aux3				21#define AD7877_REG_bat1				22#define AD7877_REG_bat2				23#define AD7877_REG_temp1			24#define AD7877_REG_temp2			25#define AD7877_REG_Z1				26#define AD7877_REG_GPIOCTRL1			27#define AD7877_REG_GPIOCTRL2			28#define AD7877_REG_GPIODATA			29#define AD7877_REG_NONE2			30#define AD7877_REG_NONE3			31 #define AD7877_SEQ_YPLUS_BIT			(1<<11)#define AD7877_SEQ_XPLUS_BIT			(1<<10)#define AD7877_SEQ_Z2_BIT			(1<<9)#define AD7877_SEQ_AUX1_BIT			(1<<8)#define AD7877_SEQ_AUX2_BIT			(1<<7)#define AD7877_SEQ_AUX3_BIT			(1<<6)#define AD7877_SEQ_BAT1_BIT			(1<<5)#define AD7877_SEQ_BAT2_BIT			(1<<4)#define AD7877_SEQ_TEMP1_BIT			(1<<3)#define AD7877_SEQ_TEMP2_BIT			(1<<2)#define AD7877_SEQ_Z1_BIT			(1<<1) enum {	AD7877_SEQ_YPOS  = 0,	AD7877_SEQ_XPOS  = 1,	AD7877_SEQ_Z2    = 2,	AD7877_SEQ_AUX1  = 3,	AD7877_SEQ_AUX2  = 4,	AD7877_SEQ_AUX3  = 5,	AD7877_SEQ_BAT1  = 6,	AD7877_SEQ_BAT2  = 7,	AD7877_SEQ_TEMP1 = 8,	AD7877_SEQ_TEMP2 = 9,	AD7877_SEQ_Z1    = 10,	AD7877_NR_SENSE  = 11,}; /* DAC Register Default RANGE 0 to Vcc, Volatge Mode, DAC On */#define AD7877_DAC_CONF			0x1 /* If gpio3 is set AUX3/GPIO3 acts as GPIO Output */#define AD7877_EXTW_GPIO_3_CONF		0x1C4#define AD7877_EXTW_GPIO_DATA		0x200 /* Control REG 2 */#define AD7877_TMR(x)			((x & 0x3) << 0)#define AD7877_REF(x)			((x & 0x1) << 2)#define AD7877_POL(x)			((x & 0x1) << 3)#define AD7877_FCD(x)			((x & 0x3) << 4)#define AD7877_PM(x)			((x & 0x3) << 6)#define AD7877_ACQ(x)			((x & 0x3) << 8)#define AD7877_AVG(x)			((x & 0x3) << 10) /* Control REG 1 */#define	AD7877_SER			(1 << 11)	/* non-differential */#define	AD7877_DFR			(0 << 11)	/* differential */ #define AD7877_MODE_NOC  (0)	/* Do not convert */#define AD7877_MODE_SCC  (1)	/* Single channel conversion */#define AD7877_MODE_SEQ0 (2)	/* Sequence 0 in Slave Mode */#define AD7877_MODE_SEQ1 (3)	/* Sequence 1 in Master Mode */ #define AD7877_CHANADD(x)		((x&0xF)<<7)#define AD7877_READADD(x)		((x)<<2)#define AD7877_WRITEADD(x)		((x)<<12) #define AD7877_READ_CHAN(x) (AD7877_WRITEADD(AD7877_REG_CTRL1) | AD7877_SER | \		AD7877_MODE_SCC | AD7877_CHANADD(AD7877_REG_ ## x) | \		AD7877_READADD(AD7877_REG_ ## x)) #define AD7877_MM_SEQUENCE (AD7877_SEQ_YPLUS_BIT | AD7877_SEQ_XPLUS_BIT | \		AD7877_SEQ_Z2_BIT | AD7877_SEQ_Z1_BIT) /* * Non-touchscreen sensors only use single-ended conversions. */ struct ser_req {	u16			reset;	u16			ref_on;	u16			command;	struct spi_message	msg;	struct spi_transfer	xfer[6]; 	/*	 * DMA (thus cache coherency maintenance) requires the	 * transfer buffers to live in their own cache lines.	 */	u16 sample ____cacheline_aligned;}; struct ad7877 {	struct input_dev	*input;	char			phys[32]; 	struct spi_device	*spi;	u16			model;	u16			vref_delay_usecs;	u16			x_plate_ohms;	u16			pressure_max; 	u16			cmd_crtl1;	u16			cmd_crtl2;	u16			cmd_dummy;	u16			dac; 	u8			stopacq_polarity;	u8			first_conversion_delay;	u8			acquisition_time;	u8			averaging;	u8			pen_down_acc_interval; 	struct spi_transfer	xfer[AD7877_NR_SENSE + 2];	struct spi_message	msg; 	struct mutex		mutex;	bool			disabled;	/* P: mutex */	bool			gpio3;		/* P: mutex */	bool			gpio4;		/* P: mutex */ 	spinlock_t		lock;	struct timer_list	timer;		/* P: lock */ 	/*	 * DMA (thus cache coherency maintenance) requires the	 * transfer buffers to live in their own cache lines.	 */	u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned;}; static bool gpio3;module_param(gpio3, bool, 0);MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3"); static int ad7877_read(struct spi_device *spi, u16 reg){	struct ser_req *req;	int status, ret; 	req = kzalloc_obj(*req);	if (!req)		return -ENOMEM; 	spi_message_init(&req->msg); 	req->command = (u16) (AD7877_WRITEADD(AD7877_REG_CTRL1) |			AD7877_READADD(reg));	req->xfer[0].tx_buf = &req->command;	req->xfer[0].len = 2;	req->xfer[0].cs_change = 1; 	req->xfer[1].rx_buf = &req->sample;	req->xfer[1].len = 2; 	spi_message_add_tail(&req->xfer[0], &req->msg);	spi_message_add_tail(&req->xfer[1], &req->msg); 	status = spi_sync(spi, &req->msg);	ret = status ? : req->sample; 	kfree(req); 	return ret;} static int ad7877_write(struct spi_device *spi, u16 reg, u16 val){	struct ser_req *req;	int status; 	req = kzalloc_obj(*req);	if (!req)		return -ENOMEM; 	spi_message_init(&req->msg); 	req->command = (u16) (AD7877_WRITEADD(reg) | (val & MAX_12BIT));	req->xfer[0].tx_buf = &req->command;	req->xfer[0].len = 2; 	spi_message_add_tail(&req->xfer[0], &req->msg); 	status = spi_sync(spi, &req->msg); 	kfree(req); 	return status;} static int ad7877_read_adc(struct spi_device *spi, unsigned command){	struct ad7877 *ts = spi_get_drvdata(spi);	struct ser_req *req;	int status;	int sample;	int i; 	req = kzalloc_obj(*req);	if (!req)		return -ENOMEM; 	spi_message_init(&req->msg); 	/* activate reference, so it has time to settle; */	req->ref_on = AD7877_WRITEADD(AD7877_REG_CTRL2) |			 AD7877_POL(ts->stopacq_polarity) |			 AD7877_AVG(0) | AD7877_PM(2) | AD7877_TMR(0) |			 AD7877_ACQ(ts->acquisition_time) | AD7877_FCD(0); 	req->reset = AD7877_WRITEADD(AD7877_REG_CTRL1) | AD7877_MODE_NOC; 	req->command = (u16) command; 	req->xfer[0].tx_buf = &req->reset;	req->xfer[0].len = 2;	req->xfer[0].cs_change = 1; 	req->xfer[1].tx_buf = &req->ref_on;	req->xfer[1].len = 2;	req->xfer[1].delay.value = ts->vref_delay_usecs;	req->xfer[1].delay.unit = SPI_DELAY_UNIT_USECS;	req->xfer[1].cs_change = 1; 	req->xfer[2].tx_buf = &req->command;	req->xfer[2].len = 2;	req->xfer[2].delay.value = ts->vref_delay_usecs;	req->xfer[2].delay.unit = SPI_DELAY_UNIT_USECS;	req->xfer[2].cs_change = 1; 	req->xfer[3].rx_buf = &req->sample;	req->xfer[3].len = 2;	req->xfer[3].cs_change = 1; 	req->xfer[4].tx_buf = &ts->cmd_crtl2;	/*REF OFF*/	req->xfer[4].len = 2;	req->xfer[4].cs_change = 1; 	req->xfer[5].tx_buf = &ts->cmd_crtl1;	/*DEFAULT*/	req->xfer[5].len = 2; 	/* group all the transfers together, so we can't interfere with	 * reading touchscreen state; disable penirq while sampling	 */	for (i = 0; i < 6; i++)		spi_message_add_tail(&req->xfer[i], &req->msg); 	status = spi_sync(spi, &req->msg);	sample = req->sample; 	kfree(req); 	return status ? : sample;} static int ad7877_process_data(struct ad7877 *ts){	struct input_dev *input_dev = ts->input;	unsigned Rt;	u16 x, y, z1, z2; 	x = ts->conversion_data[AD7877_SEQ_XPOS] & MAX_12BIT;	y = ts->conversion_data[AD7877_SEQ_YPOS] & MAX_12BIT;	z1 = ts->conversion_data[AD7877_SEQ_Z1] & MAX_12BIT;	z2 = ts->conversion_data[AD7877_SEQ_Z2] & MAX_12BIT; 	/*	 * The samples processed here are already preprocessed by the AD7877.	 * The preprocessing function consists of an averaging filter.	 * The combination of 'first conversion delay' and averaging provides a robust solution,	 * discarding the spurious noise in the signal and keeping only the data of interest.	 * The size of the averaging filter is programmable. (dev.platform_data, see linux/spi/ad7877.h)	 * Other user-programmable conversion controls include variable acquisition time,	 * and first conversion delay. Up to 16 averages can be taken per conversion.	 */ 	if (likely(x && z1)) {		/* compute touch pressure resistance using equation #1 */		Rt = (z2 - z1) * x * ts->x_plate_ohms;		Rt /= z1;		Rt = (Rt + 2047) >> 12; 		/*		 * Sample found inconsistent, pressure is beyond		 * the maximum. Don't report it to user space.		 */		if (Rt > ts->pressure_max)			return -EINVAL; 		if (!timer_pending(&ts->timer))			input_report_key(input_dev, BTN_TOUCH, 1); 		input_report_abs(input_dev, ABS_X, x);		input_report_abs(input_dev, ABS_Y, y);		input_report_abs(input_dev, ABS_PRESSURE, Rt);		input_sync(input_dev); 		return 0;	} 	return -EINVAL;} static inline void ad7877_ts_event_release(struct ad7877 *ts){	struct input_dev *input_dev = ts->input; 	input_report_abs(input_dev, ABS_PRESSURE, 0);	input_report_key(input_dev, BTN_TOUCH, 0);	input_sync(input_dev);} static void ad7877_timer(struct timer_list *t){	struct ad7877 *ts = timer_container_of(ts, t, timer); 	guard(spinlock_irqsave)(&ts->lock);	ad7877_ts_event_release(ts);} static irqreturn_t ad7877_irq(int irq, void *handle){	struct ad7877 *ts = handle;	int error; 	error = spi_sync(ts->spi, &ts->msg);	if (error) {		dev_err(&ts->spi->dev, "spi_sync --> %d\n", error);		goto out;	} 	scoped_guard(spinlock_irqsave, &ts->lock) {		error = ad7877_process_data(ts);		if (error)			goto out; 		mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);	} out:	return IRQ_HANDLED;} static void ad7877_disable(void *data){	struct ad7877 *ts = data; 	guard(mutex)(&ts->mutex); 	if (!ts->disabled) {		ts->disabled = true;		disable_irq(ts->spi->irq); 		if (timer_delete_sync(&ts->timer))			ad7877_ts_event_release(ts);	} 	/*	 * We know the chip's in lowpower mode since we always	 * leave it that way after every request	 */} static void ad7877_enable(struct ad7877 *ts){	guard(mutex)(&ts->mutex); 	if (ts->disabled) {		ts->disabled = false;		enable_irq(ts->spi->irq);	}} #define SHOW(name) static ssize_t \name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \{ \	struct ad7877 *ts = dev_get_drvdata(dev); \	ssize_t v = ad7877_read_adc(ts->spi, \			AD7877_READ_CHAN(name)); \	if (v < 0) \		return v; \	return sprintf(buf, "%u\n", (unsigned) v); \} \static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); SHOW(aux1)SHOW(aux2)SHOW(aux3)SHOW(bat1)SHOW(bat2)SHOW(temp1)SHOW(temp2) static ssize_t ad7877_disable_show(struct device *dev,				     struct device_attribute *attr, char *buf){	struct ad7877 *ts = dev_get_drvdata(dev); 	return sprintf(buf, "%u\n", ts->disabled);} static ssize_t ad7877_disable_store(struct device *dev,				     struct device_attribute *attr,				     const char *buf, size_t count){	struct ad7877 *ts = dev_get_drvdata(dev);	unsigned int val;	int error; 	error = kstrtouint(buf, 10, &val);	if (error)		return error; 	if (val)		ad7877_disable(ts);	else		ad7877_enable(ts); 	return count;} static DEVICE_ATTR(disable, 0664, ad7877_disable_show, ad7877_disable_store); static ssize_t ad7877_dac_show(struct device *dev,				     struct device_attribute *attr, char *buf){	struct ad7877 *ts = dev_get_drvdata(dev); 	return sprintf(buf, "%u\n", ts->dac);} static ssize_t ad7877_dac_store(struct device *dev,				     struct device_attribute *attr,				     const char *buf, size_t count){	struct ad7877 *ts = dev_get_drvdata(dev);	unsigned int val;

Lines 1–500 of 814.