From 9c48494440a35521c09f9e318a5d3daa00efb6fe Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E6=B2=88=E7=9D=BF=E6=B1=80?= Date: Tue, 18 May 2010 12:40:54 +0000 Subject: [PATCH] modify to xpt2046_ts.c xpt2046_ts.h --- arch/arm/mach-rk2818/board-midsdk.c | 2 +- .../input/touchscreen/rk2818_spi_xpt2046_ts.c | 928 ------------------ .../input/touchscreen/rk2818_spi_xpt2046_ts.h | 54 - 3 files changed, 1 insertion(+), 983 deletions(-) delete mode 100644 drivers/input/touchscreen/rk2818_spi_xpt2046_ts.c delete mode 100644 drivers/input/touchscreen/rk2818_spi_xpt2046_ts.h diff --git a/arch/arm/mach-rk2818/board-midsdk.c b/arch/arm/mach-rk2818/board-midsdk.c index 4d975322cd27..1269251d2001 100644 --- a/arch/arm/mach-rk2818/board-midsdk.c +++ b/arch/arm/mach-rk2818/board-midsdk.c @@ -237,7 +237,7 @@ static struct spi_board_info board_spi_devices[] = { .mode = SPI_MODE_0, }, #endif -#if defined(CONFIG_TOUCHSCREEN_RK2818_SPI_XPT2046) || defined(CONFIG_TOUCHSCREEN_RK2818_SPI_XPT2046_CBN) +#if defined(CONFIG_TOUCHSCREEN_XPT2046_SPI) || defined(CONFIG_TOUCHSCREEN_XPT2046_CBN_SPI) { .modalias = "xpt2046_ts", .chip_select = 0, diff --git a/drivers/input/touchscreen/rk2818_spi_xpt2046_ts.c b/drivers/input/touchscreen/rk2818_spi_xpt2046_ts.c deleted file mode 100644 index 46e4591c58f0..000000000000 --- a/drivers/input/touchscreen/rk2818_spi_xpt2046_ts.c +++ /dev/null @@ -1,928 +0,0 @@ -/* - * drivers/input/touchscreen/rk2818_spi_xpt2046_ts.c - driver for rk2818 spi xpt2046 device and console - * - * Copyright (C) 2010 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rk2818_spi_xpt2046_ts.h" - -/* - * This code has been heavily tested on a Nokia 770, and lightly - * tested on other xpt2046 devices (OSK/Mistral, Lubbock). - * TSC2046 is just newer xpt2046 silicon. - * Support for ads7843 tested on Atmel at91sam926x-EK. - * Support for ads7845 has only been stubbed in. - * - * IRQ handling needs a workaround because of a shortcoming in handling - * edge triggered IRQs on some platforms like the OMAP1/2. These - * platforms don't handle the ARM lazy IRQ disabling properly, thus we - * have to maintain our own SW IRQ disabled status. This should be - * removed as soon as the affected platform's IRQ handling is fixed. - * - * app note sbaa036 talks in more detail about accurate sampling... - * that ought to help in situations like LCDs inducing noise (which - * can also be helped by using synch signals) and more generally. - * This driver tries to utilize the measures described in the app - * note. The strength of filtering can be set in the board-* specific - * files. - */ -#define XPT2046_DEBUG 0 -#if XPT2046_DEBUG - #define xpt2046printk(msg...) printk(msg); -#else - #define xpt2046printk(msg...) -#endif -#define LCD_MAX_LENGTH 800 -#define LCD_MAX_WIDTH 480 -#define PT2046_TOUCH_AD_LEFT 3855 -#define PT2046_TOUCH_AD_RIGHT 260 -#define PT2046_TOUCH_AD_TOP 300 -#define PT2046_TOUCH_AD_BOTTOM 3755 -#define AD_TO_X(adx) (LCD_MAX_WIDTH * (adx - PT2046_TOUCH_AD_TOP) / ( PT2046_TOUCH_AD_BOTTOM - PT2046_TOUCH_AD_TOP )) -#define AD_TO_Y(ady) (LCD_MAX_LENGTH * (PT2046_TOUCH_AD_LEFT - ady) / (PT2046_TOUCH_AD_LEFT - PT2046_TOUCH_AD_RIGHT)) - -#define TS_POLL_DELAY (15 * 1000000) /* ns delay before the first sample */ -#define TS_POLL_PERIOD (15 * 1000000) /* ns delay between samples */ - -#define DEBOUNCE_REPTIME 3 -/* this driver doesn't aim at the peak continuous sample rate */ -#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) - -struct ts_event { - /* For portability, we can't read 12 bit values using SPI (which - * would make the controller deliver them as native byteorder u16 - * with msbs zeroed). Instead, we read them as two 8-bit values, - * *** WHICH NEED BYTESWAPPING *** and range adjustment. - */ - u16 x; - u16 y; - int ignore; -}; - -/* - * We allocate this separately to avoid cache line sharing issues when - * driver is used with DMA-based SPI controllers (like atmel_spi) on - * systems where main memory is not DMA-coherent (most non-x86 boards). - */ -struct xpt2046_packet { - u8 read_x, read_y, pwrdown; - u16 dummy; /* for the pwrdown read */ - struct ts_event tc; -}; - -struct xpt2046 { - struct input_dev *input; - char phys[32]; - char name[32]; - - struct spi_device *spi; - - u16 model; - bool swap_xy; - - struct xpt2046_packet *packet; - - struct spi_transfer xfer[18]; - struct spi_message msg[5]; - struct spi_message *last_msg; - int msg_idx; - int read_cnt; - int read_rep; - int last_read; - - u16 debounce_max; - u16 debounce_tol; - u16 debounce_rep; - - u16 penirq_recheck_delay_usecs; - - spinlock_t lock; - struct hrtimer timer; - unsigned pendown:1; /* P: lock */ - unsigned pending:1; /* P: lock */ -// FIXME remove "irq_disabled" - unsigned irq_disabled:1; /* P: lock */ - unsigned disabled:1; - unsigned is_suspended:1; - - int (*filter)(void *data, int data_idx, int *val); - void *filter_data; - void (*filter_cleanup)(void *data); - int (*get_pendown_state)(void); - int gpio_pendown; - - void (*wait_for_sync)(void); -}; - -/* leave chip selected when we're done, for quicker re-select? */ -#if 0 -#define CS_CHANGE(xfer) ((xfer).cs_change = 1) -#else -#define CS_CHANGE(xfer) ((xfer).cs_change = 0) -#endif - -/*--------------------------------------------------------------------------*/ - -/* The xpt2046 has touchscreen and other sensors. - * Earlier xpt2046 chips are somewhat compatible. - */ -#define XPT2046_START (1 << 7) -#define XPT2046_A2A1A0_d_y (1 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z1 (3 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z2 (4 << 4) /* differential */ -#define XPT2046_A2A1A0_d_x (5 << 4) /* differential */ -#define XPT2046_A2A1A0_temp0 (0 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vbatt (2 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vaux (6 << 4) /* non-differential */ -#define XPT2046_A2A1A0_temp1 (7 << 4) /* non-differential */ -#define XPT2046_8_BIT (1 << 3) -#define XPT2046_12_BIT (0 << 3) -#define XPT2046_SER (1 << 2) /* non-differential */ -#define XPT2046_DFR (0 << 2) /* differential */ -#define XPT2046_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ -#define XPT2046_PD10_ADC_ON (1 << 0) /* ADC on */ -#define XPT2046_PD10_REF_ON (2 << 0) /* vREF on + penirq */ -#define XPT2046_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ - -#define MAX_12BIT ((1<<12)-1) - -/* leave ADC powered up (disables penirq) between differential samples */ -#define READ_12BIT_DFR(x, adc, vref) (XPT2046_START | XPT2046_A2A1A0_d_ ## x \ - | XPT2046_12_BIT | XPT2046_DFR | \ - (adc ? XPT2046_PD10_ADC_ON : 0) | (vref ? XPT2046_PD10_REF_ON : 0)) - -#define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) -#define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) -#define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) - -#define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) -#define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ - -/* single-ended samples need to first power up reference voltage; - * we leave both ADC and VREF powered - */ -#define READ_12BIT_SER(x) (XPT2046_START | XPT2046_A2A1A0_ ## x \ - | XPT2046_12_BIT | XPT2046_SER) - -#define REF_ON (READ_12BIT_DFR(x, 1, 1)) -#define REF_OFF (READ_12BIT_DFR(y, 0, 0)) - -/*--------------------------------------------------------------------------*/ -/* - * touchscreen sensors use differential conversions. - */ - -struct dfr_req { - u8 command; - u8 pwrdown; - u16 dummy; /* for the pwrdown read */ - __be16 sample; - struct spi_message msg; - struct spi_transfer xfer[4]; -}; - -static struct xpt2046_platform_data xpt2046_info = { - .model = 2046, - .keep_vref_on = 1, - .swap_xy = 1, - .x_min = 0, - .x_max = 800, - .y_min = 0, - .y_max = 480, - .debounce_max = 7, - .debounce_rep = DEBOUNCE_REPTIME, - .debounce_tol = 20, - .gpio_pendown = RK2818_PIN_PE3, - -}; -static void xpt2046_enable(struct xpt2046 *ts); -static void xpt2046_disable(struct xpt2046 *ts); - -static int device_suspended(struct device *dev) -{ - struct xpt2046 *ts = dev_get_drvdata(dev); - return ts->is_suspended || ts->disabled; -} - -static int xpt2046_read12_dfr(struct device *dev, unsigned command) -{ - struct spi_device *spi = to_spi_device(dev); - struct xpt2046 *ts = dev_get_drvdata(dev); - struct dfr_req *req = kzalloc(sizeof *req, GFP_KERNEL); - int status; - - if (!req) - return -ENOMEM; - - spi_message_init(&req->msg); - - /* take sample */ - req->command = (u8) command; - req->xfer[0].tx_buf = &req->command; - req->xfer[0].len = 1; - spi_message_add_tail(&req->xfer[0], &req->msg); - - req->xfer[1].rx_buf = &req->sample; - req->xfer[1].len = 2; - spi_message_add_tail(&req->xfer[1], &req->msg); - - /* converter in low power mode & enable PENIRQ */ - req->pwrdown= PWRDOWN; - req->xfer[2].tx_buf = &req->pwrdown; - req->xfer[2].len = 1; - spi_message_add_tail(&req->xfer[2], &req->msg); - - req->xfer[3].rx_buf = &req->dummy; - req->xfer[3].len = 2; - CS_CHANGE(req->xfer[3]); - spi_message_add_tail(&req->xfer[3], &req->msg); - - ts->irq_disabled = 1; - disable_irq(spi->irq); - status = spi_sync(spi, &req->msg); - ts->irq_disabled = 0; - enable_irq(spi->irq); - - if (status == 0) { - /* on-wire is a must-ignore bit, a BE12 value, then padding */ - status = be16_to_cpu(req->sample); - status = status >> 3; - status &= 0x0fff; - printk("***>%s:status=%d\n",__FUNCTION__,status); - } - - kfree(req); - return status; -} - - - -/*--------------------------------------------------------------------------*/ - -static int get_pendown_state(struct xpt2046 *ts) -{ - if (ts->get_pendown_state) - return ts->get_pendown_state(); - - return !gpio_get_value(ts->gpio_pendown); -} - -static void null_wait_for_sync(void) -{ - -} - -/* - * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, - * to retrieve touchscreen status. - * - * The SPI transfer completion callback does the real work. It reports - * touchscreen events and reactivates the timer (or IRQ) as appropriate. - */ - -static void xpt2046_rx(void *xpt) -{ - struct xpt2046 *ts = xpt; - struct xpt2046_packet *packet = ts->packet; - unsigned Rt = 1; - u16 x, y; - - /* xpt2046_rx_val() did in-place conversion (including byteswap) from - * on-the-wire format as part of debouncing to get stable readings. - */ - x = packet->tc.x; - y = packet->tc.y; - - xpt2046printk("***>%s:x=%d,y=%d\n",__FUNCTION__,x,y); - - /* range filtering */ - if (x == MAX_12BIT) - x = 0; - - /* Sample found inconsistent by debouncing or pressure is beyond - * the maximum. Don't report it to user space, repeat at least - * once more the measurement - */ - if (packet->tc.ignore) { - - xpt2046printk("***>%s:ignored=%d\n",__FUNCTION__,packet->tc.ignore); - - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), - HRTIMER_MODE_REL); - return; - } - - /* Maybe check the pendown state before reporting. This discards - * false readings when the pen is lifted. - */ - if (ts->penirq_recheck_delay_usecs) { - udelay(ts->penirq_recheck_delay_usecs); - if (!get_pendown_state(ts)) - { - printk("***>%s:get_pendown_state(ts)==0,discard false reading\n",__FUNCTION__); - Rt = 0; - } - } - - /* NOTE: We can't rely on the pressure to determine the pen down - * state, even this controller has a pressure sensor. The pressure - * value can fluctuate for quite a while after lifting the pen and - * in some cases may not even settle at the expected value. - * - * The only safe way to check for the pen up condition is in the - * timer by reading the pen signal state (it's a GPIO _and_ IRQ). - */ - if (Rt) { - struct input_dev *input = ts->input; - if (!ts->pendown) { - input_report_key(input, BTN_TOUCH, 1); - ts->pendown = 1; - printk("***>%s:input_report_key(pen down)\n",__FUNCTION__); - } - - x = AD_TO_X(x); - y = AD_TO_Y(y); - - if (ts->swap_xy) - swap(x, y); - - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - - input_sync(input); - xpt2046printk("***>%s:input_report_abs(%4d/%4d)\n",__FUNCTION__,x, y); - } - - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), - HRTIMER_MODE_REL); -} - -static int xpt2046_debounce(void *xpt, int data_idx, int *val) -{ - struct xpt2046 *ts = xpt; - static int average_val[2]; - - - xpt2046printk("***>%s:%d,%d,%d,%d,%d,%d,%d,%d\n",__FUNCTION__, - data_idx,ts->last_read, - ts->read_cnt,ts->debounce_max, - abs(ts->last_read - *val),ts->debounce_tol, - ts->read_rep,ts->debounce_rep); - - /* discard the first sample. */ - if(!ts->read_cnt) - { - udelay(100); - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } - - if (ts->read_cnt==1 || (abs(ts->last_read - *val) > ts->debounce_tol)) { - /* Start over collecting consistent readings. */ - ts->read_rep = 1; - average_val[data_idx] = *val; - /* Repeat it, if this was the first read or the read - * wasn't consistent enough. */ - if (ts->read_cnt < ts->debounce_max) { - ts->last_read = *val; - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } else { - /* Maximum number of debouncing reached and still - * not enough number of consistent readings. Abort - * the whole sample, repeat it in the next sampling - * period. - */ - ts->read_cnt = 0; - ts->last_read = 0; - memset(average_val,0,sizeof(average_val)); - xpt2046printk("***>%s:XPT2046_FILTER_IGNORE\n",__FUNCTION__); - return XPT2046_FILTER_IGNORE; - } - } - else { - average_val[data_idx] += *val; - - if (++ts->read_rep >= ts->debounce_rep) { - /* Got a good reading for this coordinate, - * go for the next one. */ - ts->read_cnt = 0; - ts->read_rep = 0; - ts->last_read = 0; - *val = average_val[data_idx]/(ts->debounce_rep); - return XPT2046_FILTER_OK; - } else { - /* Read more values that are consistent. */ - ts->read_cnt++; - - return XPT2046_FILTER_REPEAT; - } - } -} - -static int xpt2046_no_filter(void *xpt, int data_idx, int *val) -{ - return XPT2046_FILTER_OK; -} - -static void xpt2046_rx_val(void *xpt) -{ - struct xpt2046 *ts = xpt; - struct xpt2046_packet *packet = ts->packet; - struct spi_message *m; - struct spi_transfer *t; - int val; - int action; - int status; - - m = &ts->msg[ts->msg_idx]; - t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); - - /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; - * built from two 8 bit values written msb-first. - */ - val = (be16_to_cpup((__be16 *)t->rx_buf) >> 3) & 0x0fff; - - xpt2046printk("***>%s:value=%d\n",__FUNCTION__,val); - - action = ts->filter(ts->filter_data, ts->msg_idx, &val); - switch (action) { - case XPT2046_FILTER_REPEAT: - break; - case XPT2046_FILTER_IGNORE: - packet->tc.ignore = 1; - /* Last message will contain xpt2046_rx() as the - * completion function. - */ - m = ts->last_msg; - break; - case XPT2046_FILTER_OK: - *(u16 *)t->rx_buf = val; - packet->tc.ignore = 0; - m = &ts->msg[++ts->msg_idx]; - break; - default: - BUG(); - } - ts->wait_for_sync(); - status = spi_async(ts->spi, m); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", - status); -} - -static enum hrtimer_restart xpt2046_timer(struct hrtimer *handle) -{ - struct xpt2046 *ts = container_of(handle, struct xpt2046, timer); - int status = 0; - - spin_lock(&ts->lock); - - if (unlikely(!get_pendown_state(ts) || - device_suspended(&ts->spi->dev))) { - if (ts->pendown) { - struct input_dev *input = ts->input; - input_report_key(input, BTN_TOUCH, 0); - input_sync(input); - - ts->pendown = 0; - - printk("***>%s:input_report_key(The touchscreen up)\n",__FUNCTION__); - } - - /* measurement cycle ended */ - if (!device_suspended(&ts->spi->dev)) { - printk("***>%s:device_suspended==0\n",__FUNCTION__); - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); - } - ts->pending = 0; - } else { - /* pen is still down, continue with the measurement */ - xpt2046printk("***>%s:pen is still down, continue with the measurement\n",__FUNCTION__); - ts->msg_idx = 0; - ts->wait_for_sync(); - status = spi_async(ts->spi, &ts->msg[0]); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", status); - } - - spin_unlock(&ts->lock); - return HRTIMER_NORESTART; -} - -static irqreturn_t xpt2046_irq(int irq, void *handle) -{ - struct xpt2046 *ts = handle; - unsigned long flags; - - xpt2046printk("***>%s.....%s.....%d\n",__FILE__,__FUNCTION__,__LINE__); - - spin_lock_irqsave(&ts->lock, flags); - - if (likely(get_pendown_state(ts))) { - if (!ts->irq_disabled) { - /* The ARM do_simple_IRQ() dispatcher doesn't act - * like the other dispatchers: it will report IRQs - * even after they've been disabled. We work around - * that here. (The "generic irq" framework may help...) - */ - ts->irq_disabled = 1; - disable_irq_nosync(ts->spi->irq); - ts->pending = 1; - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), - HRTIMER_MODE_REL); - } - } - spin_unlock_irqrestore(&ts->lock, flags); - - return IRQ_HANDLED; -} - -/*--------------------------------------------------------------------------*/ - -/* Must be called with ts->lock held */ -static void xpt2046_disable(struct xpt2046 *ts) -{ - if (ts->disabled) - return; - - ts->disabled = 1; - - /* are we waiting for IRQ, or polling? */ - if (!ts->pending) { - ts->irq_disabled = 1; - disable_irq(ts->spi->irq); - } else { - /* the timer will run at least once more, and - * leave everything in a clean state, IRQ disabled - */ - while (ts->pending) { - spin_unlock_irq(&ts->lock); - msleep(1); - spin_lock_irq(&ts->lock); - } - } - - /* we know the chip's in lowpower mode since we always - * leave it that way after every request - */ -} - -/* Must be called with ts->lock held */ -static void xpt2046_enable(struct xpt2046 *ts) -{ - if (!ts->disabled) - return; - - ts->disabled = 0; - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); -} - -static int xpt2046_suspend(struct spi_device *spi, pm_message_t message) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - spin_lock_irq(&ts->lock); - - ts->is_suspended = 1; - xpt2046_disable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; - -} - -static int xpt2046_resume(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - spin_lock_irq(&ts->lock); - - ts->is_suspended = 0; - xpt2046_enable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; -} - -static int __devinit setup_pendown(struct spi_device *spi, struct xpt2046 *ts) -{ - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - int err; - - /* REVISIT when the irq can be triggered active-low, or if for some - * reason the touchscreen isn't hooked up, we don't need to access - * the pendown state. - */ - if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { - dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); - return -EINVAL; - } - - if (pdata->get_pendown_state) { - ts->get_pendown_state = pdata->get_pendown_state; - return 0; - } - - err = gpio_request(pdata->gpio_pendown, "xpt2046_pendown"); - if (err) { - dev_err(&spi->dev, "failed to request pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - - ts->gpio_pendown = pdata->gpio_pendown; - return 0; -} - -static int __devinit xpt2046_probe(struct spi_device *spi) -{ - struct xpt2046 *ts; - struct xpt2046_packet *packet; - struct input_dev *input_dev; - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - struct spi_message *m; - struct spi_transfer *x; - int vref; - int err; - - - - if (!spi->irq) { - dev_dbg(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } - else{ - spi->irq = gpio_to_irq(spi->irq); - dev_dbg(&spi->dev, "no IRQ?\n"); - } - - if (!pdata) { - spi->dev.platform_data = &xpt2046_info; - pdata = spi->dev.platform_data; - } - - /* don't exceed max specified sample rate */ - if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { - dev_dbg(&spi->dev, "f(sample) %d KHz?\n", - (spi->max_speed_hz/SAMPLE_BITS)/1000); - return -EINVAL; - } - - /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except - * that even if the hardware can do that, the SPI controller driver - * may not. So we stick to very-portable 8 bit words, both RX and TX. - */ - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - err = spi_setup(spi); - if (err < 0) - return err; - - ts = kzalloc(sizeof(struct xpt2046), GFP_KERNEL); - packet = kzalloc(sizeof(struct xpt2046_packet), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !packet || !input_dev) { - err = -ENOMEM; - goto err_free_mem; - } - - dev_set_drvdata(&spi->dev, ts); - - ts->packet = packet; - ts->spi = spi; - ts->input = input_dev; - ts->swap_xy = pdata->swap_xy; - - hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - ts->timer.function = xpt2046_timer; - - spin_lock_init(&ts->lock); - - ts->model = pdata->model ? : 2046; - - if (pdata->filter != NULL) { - if (pdata->filter_init != NULL) { - err = pdata->filter_init(pdata, &ts->filter_data); - if (err < 0) - goto err_free_mem; - } - ts->filter = pdata->filter; - ts->filter_cleanup = pdata->filter_cleanup; - } else if (pdata->debounce_max) { - ts->debounce_max = pdata->debounce_max; - if (ts->debounce_max < DEBOUNCE_REPTIME) - ts->debounce_max = DEBOUNCE_REPTIME; - ts->debounce_tol = pdata->debounce_tol; - ts->debounce_rep = pdata->debounce_rep; - ts->filter = xpt2046_debounce; - ts->filter_data = ts; - } else - ts->filter = xpt2046_no_filter; - - err = setup_pendown(spi, ts); - if (err) - goto err_cleanup_filter; - - if (pdata->penirq_recheck_delay_usecs) - ts->penirq_recheck_delay_usecs = - pdata->penirq_recheck_delay_usecs; - - ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; - - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); - snprintf(ts->name, sizeof(ts->name), "XPT%d Touchscreen", ts->model); - - input_dev->name = ts->name; - input_dev->phys = ts->phys; - input_dev->dev.parent = &spi->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, - pdata->x_min ? : 0, - pdata->x_max ? : MAX_12BIT, - 0, 0); - input_set_abs_params(input_dev, ABS_Y, - pdata->y_min ? : 0, - pdata->y_max ? : MAX_12BIT, - 0, 0); - - vref = pdata->keep_vref_on; - - /* set up the transfers to read touchscreen state; this assumes we - * use formula #2 for pressure, not #3. - */ - m = &ts->msg[0]; - x = ts->xfer; - - spi_message_init(m); - - /* y- still on; turn on only y+ (and ADC) */ - packet->read_y = READ_Y(vref); - x->tx_buf = &packet->read_y; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.y; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - m++; - spi_message_init(m); - - /* turn y- off, x+ on, then leave in lowpower */ - x++; - packet->read_x = READ_X(vref); - x->tx_buf = &packet->read_x; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.x; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - /* power down */ - m++; - spi_message_init(m); - - x++; - packet->pwrdown = PWRDOWN; - x->tx_buf = &packet->pwrdown; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->dummy; - x->len = 2; - CS_CHANGE(*x); - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx; - m->context = ts; - - ts->last_msg = m; - - if (request_irq(spi->irq, xpt2046_irq, IRQF_TRIGGER_FALLING, - spi->dev.driver->name, ts)) { - printk("***>%s:trying pin change workaround on irq %d\n",__FUNCTION__,spi->irq); - err = request_irq(spi->irq, xpt2046_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - spi->dev.driver->name, ts); - if (err) { - dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - goto err_free_gpio; - } - } - printk("***>%s:touchscreen irq %d\n",__FUNCTION__,spi->irq); - - /* take a first sample, leaving nPENIRQ active and vREF off; avoid - * the touchscreen, in case it's not connected. - */ - xpt2046_read12_dfr(&spi->dev,READ_X(1)); - - err = input_register_device(input_dev); - if (err) - goto err_remove_attr_group; - - return 0; - - err_remove_attr_group: - free_irq(spi->irq, ts); - err_free_gpio: - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - err_cleanup_filter: - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - err_free_mem: - input_free_device(input_dev); - kfree(packet); - kfree(ts); - return err; -} - -static int __devexit xpt2046_remove(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - input_unregister_device(ts->input); - - xpt2046_suspend(spi, PMSG_SUSPEND); - - free_irq(ts->spi->irq, ts); - /* suspend left the IRQ disabled */ - enable_irq(ts->spi->irq); - - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - - kfree(ts->packet); - kfree(ts); - - dev_dbg(&spi->dev, "unregistered touchscreen\n"); - return 0; -} - -static struct spi_driver xpt2046_driver = { - .driver = { - .name = "xpt2046_ts", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = xpt2046_probe, - .remove = __devexit_p(xpt2046_remove), - .suspend = xpt2046_suspend, - .resume = xpt2046_resume, -}; - -static int __init xpt2046_init(void) -{ - return spi_register_driver(&xpt2046_driver); -} -module_init(xpt2046_init); - -static void __exit xpt2046_exit(void) -{ - spi_unregister_driver(&xpt2046_driver); -} -module_exit(xpt2046_exit); - -MODULE_DESCRIPTION("rk2818 spi xpt2046 TouchScreen Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:xpt2046"); diff --git a/drivers/input/touchscreen/rk2818_spi_xpt2046_ts.h b/drivers/input/touchscreen/rk2818_spi_xpt2046_ts.h deleted file mode 100644 index 131c0696e8e9..000000000000 --- a/drivers/input/touchscreen/rk2818_spi_xpt2046_ts.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * drivers/input/touchscreen/rk2818_spi_xpt2046_ts.h - * - * Copyright (C) 2010 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - */ - -#ifndef __DRIVERS_TOUCHSCREEN_RK2818_SPI_XPT2046_TS_H -#define __DRIVERS_TOUCHSCREEN_RK2818_SPI_XPT2046_TS_H -enum xpt2046_filter { - XPT2046_FILTER_OK, - XPT2046_FILTER_REPEAT, - XPT2046_FILTER_IGNORE, -}; - -struct xpt2046_platform_data { - u16 model; /* 2046. */ - bool keep_vref_on; /* set to keep vref on for differential - * measurements as well */ - bool swap_xy; /* swap x and y axes */ - - /* If set to non-zero, after samples are taken this delay is applied - * and penirq is rechecked, to help avoid false events. This value - * is affected by the material used to build the touch layer. - */ - u16 penirq_recheck_delay_usecs; - - u16 x_min, x_max; - u16 y_min, y_max; - - u16 debounce_max; /* max number of additional readings - * per sample */ - u16 debounce_tol; /* tolerance used for filtering */ - u16 debounce_rep; /* additional consecutive good readings - * required after the first two */ - int gpio_pendown; /* the GPIO used to decide the pendown - * state if get_pendown_state == NULL - */ - int (*get_pendown_state)(void); - int (*filter_init) (struct xpt2046_platform_data *pdata, - void **filter_data); - int (*filter) (void *filter_data, int data_idx, int *val); - void (*filter_cleanup)(void *filter_data); - void (*wait_for_sync)(void); -}; -#endif /* __DRIVERS_TOUCHSCREEN_RK2818_SPI_XPT2046_TS_H*/ -- 2.34.1