diff options
author | Roshni Shah <shah.roshni@yahoo.com> | 2011-03-14 06:49:42 -0400 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2012-03-02 16:59:46 -0500 |
commit | 2731b2eadeaa141e6f305fa8086106608112bbaa (patch) | |
tree | 2702d45bac84073cd580ccb1bd3eafb9a000d3b6 /drivers/input/touchscreen/mxc_ts.c | |
parent | 6d23f5084c975be637f7d748db82116bf84d3872 (diff) |
Add support for the i.MX53 QSB2.6.35.3-mx53-early-201103141049
This patch seems to have originated from the 11.01.00 release
from Freescale, which is no longer available except through the
gitweb interface from Freescale.
http://opensource.freescale.com/git?p=imx/linux-2.6-imx.git;a=commit;h=27fdf7bae11978d21e8aba09bb635f49b07edd4a
Diffstat (limited to 'drivers/input/touchscreen/mxc_ts.c')
-rw-r--r-- | drivers/input/touchscreen/mxc_ts.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/mxc_ts.c b/drivers/input/touchscreen/mxc_ts.c new file mode 100644 index 000000000000..0783188e8376 --- /dev/null +++ b/drivers/input/touchscreen/mxc_ts.c @@ -0,0 +1,189 @@ +/* + * Freescale touchscreen driver + * + * Copyright (C) 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! + * @file mxc_ts.c + * + * @brief Driver for the Freescale Semiconductor MXC touchscreen with calibration support. + * + * The touchscreen driver is designed as a standard input driver which is a + * wrapper over low level PMIC driver. Most of the hardware configuration and + * touchscreen functionality is implemented in the low level PMIC driver. During + * initialization, this driver creates a kernel thread. This thread then calls + * PMIC driver to obtain touchscreen values continously. These values are then + * passed to the input susbsystem. + * + * @ingroup touchscreen + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/input.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/freezer.h> +#include <linux/pmic_external.h> +#include <linux/pmic_adc.h> +#include <linux/kthread.h> + +#define MXC_TS_NAME "mxc_ts" + +static struct input_dev *mxc_inputdev; +static struct task_struct *tstask; +/** + * calibration array refers to + * (delta_x[0], delta_x[1], delta_x[2], delta_y[0], delta_y[1], delta_y[2], delta). + * Which generated by calibration service. + * In this driver when we got touch pointer (x', y') from PMIC ADC, + * we calculate the display pointer (x,y) by: + * x = (delta_x[0] * x' + delta_x[1] * y' + delta_x[2]) / delta; + * y = (delta_y[0] * x' + delta_y[1] * y' + delta_y[2]) / delta; + */ +static int calibration[7]; +module_param_array(calibration, int, NULL, S_IRUGO | S_IWUSR); + +static int ts_thread(void *arg) +{ + t_touch_screen ts_sample; + s32 wait = 0; + + do { + int x, y; + static int last_x = -1, last_y = -1, last_press = -1; + + memset(&ts_sample, 0, sizeof(t_touch_screen)); + if (0 != pmic_adc_get_touch_sample(&ts_sample, !wait)) + continue; + if (!(ts_sample.contact_resistance || wait)) + continue; + + if (ts_sample.x_position == 0 && ts_sample.y_position == 0 && + ts_sample.contact_resistance == 0) { + x = last_x; + y = last_y; + } else if (calibration[6] == 0) { + x = ts_sample.x_position; + y = ts_sample.y_position; + } else { + x = calibration[0] * (int)ts_sample.x_position + + calibration[1] * (int)ts_sample.y_position + + calibration[2]; + x /= calibration[6]; + if (x < 0) + x = 0; + y = calibration[3] * (int)ts_sample.x_position + + calibration[4] * (int)ts_sample.y_position + + calibration[5]; + y /= calibration[6]; + if (y < 0) + y = 0; + } + + if (x != last_x) { + input_report_abs(mxc_inputdev, ABS_X, x); + last_x = x; + } + if (y != last_y) { + input_report_abs(mxc_inputdev, ABS_Y, y); + last_y = y; + } + + /* report pressure */ + input_report_abs(mxc_inputdev, ABS_PRESSURE, + ts_sample.contact_resistance); +#ifdef CONFIG_MXC_PMIC_MC13892 + /* workaround for aplite ADC resistance large range value */ + if (ts_sample.contact_resistance > 22) + ts_sample.contact_resistance = 1; + else + ts_sample.contact_resistance = 0; +#endif + /* report the BTN_TOUCH */ + if (ts_sample.contact_resistance != last_press) + input_event(mxc_inputdev, EV_KEY, + BTN_TOUCH, ts_sample.contact_resistance); + + input_sync(mxc_inputdev); + last_press = ts_sample.contact_resistance; + + wait = ts_sample.contact_resistance; + msleep(20); + + } while (!kthread_should_stop()); + + return 0; +} + +static int __init mxc_ts_init(void) +{ + int retval; + + if (!is_pmic_adc_ready()) + return -ENODEV; + + mxc_inputdev = input_allocate_device(); + if (!mxc_inputdev) { + printk(KERN_ERR + "mxc_ts_init: not enough memory\n"); + return -ENOMEM; + } + + mxc_inputdev->name = MXC_TS_NAME; + mxc_inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + mxc_inputdev->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); + mxc_inputdev->absbit[0] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | BIT_MASK(ABS_PRESSURE); + retval = input_register_device(mxc_inputdev); + if (retval < 0) { + input_free_device(mxc_inputdev); + return retval; + } + + tstask = kthread_run(ts_thread, NULL, "mxc_ts"); + if (IS_ERR(tstask)) { + printk(KERN_ERR + "mxc_ts_init: failed to create kthread"); + tstask = NULL; + return -1; + } + printk("mxc input touchscreen loaded\n"); + return 0; +} + +static void __exit mxc_ts_exit(void) +{ + if (tstask) + kthread_stop(tstask); + + input_unregister_device(mxc_inputdev); + + if (mxc_inputdev) { + input_free_device(mxc_inputdev); + mxc_inputdev = NULL; + } +} + +late_initcall(mxc_ts_init); +module_exit(mxc_ts_exit); + +MODULE_DESCRIPTION("MXC touchscreen driver with calibration"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_LICENSE("GPL"); |