diff options
author | Xinyu Chen <xinyu.chen@freescale.com> | 2010-02-11 09:52:16 +0800 |
---|---|---|
committer | Alejandro Gonzalez <alex.gonzalez@digi.com> | 2010-05-24 12:24:59 +0200 |
commit | a5bd196d5dafdc85b5244fb6196389104c8d1228 (patch) | |
tree | 4ed3acd0c67152386d264f6c74d2be017e4c6aae /drivers/input | |
parent | 2c5c5f9bdf4f3291aa836c672dcbb21050bf1ff0 (diff) |
ENGR00120162 Add calibration support to touchscreen driver
Add touchscreen calibration support and the BTN_TOUCH.
The calibration algorithm is from Carlos E. Vidales.
and the calibration data is passed to driver by module param.
This driver passes test on ubuntu and android.
Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com>
Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/touchscreen/mxc_ts.c | 117 |
1 files changed, 94 insertions, 23 deletions
diff --git a/drivers/input/touchscreen/mxc_ts.c b/drivers/input/touchscreen/mxc_ts.c index d60cd51a535e..02b34aceac47 100644 --- a/drivers/input/touchscreen/mxc_ts.c +++ b/drivers/input/touchscreen/mxc_ts.c @@ -1,20 +1,27 @@ /* - * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: + * 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. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * 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. + * @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 @@ -35,20 +42,33 @@ #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 = NULL; -static u32 input_ts_installed; +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, wait2 = 0; - daemonize("mxc_ts"); - while (input_ts_installed) { - try_to_freeze(); + do { + int x, y; + static int last_x = -1, last_y = -1, last_press = -1; + memset(&ts_sample, 0, sizeof(t_touch_screen)); /* After 2 consecutive samples with the pen up, enable irq waiting */ @@ -58,15 +78,59 @@ static int ts_thread(void *arg) if (!(ts_sample.contact_resistance || wait)) continue; - input_report_abs(mxc_inputdev, ABS_X, ts_sample.x_position); - input_report_abs(mxc_inputdev, ABS_Y, ts_sample.y_position); + 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; wait2 = wait; wait = ts_sample.contact_resistance; msleep(20); - } + } while (!kthread_should_stop()); return 0; } @@ -81,7 +145,7 @@ static int __init mxc_ts_init(void) mxc_inputdev = input_allocate_device(); if (!mxc_inputdev) { printk(KERN_ERR - "mxc_ts_init: not enough memory for input device\n"); + "mxc_ts_init: not enough memory\n"); return -ENOMEM; } @@ -96,15 +160,22 @@ static int __init mxc_ts_init(void) return retval; } - input_ts_installed = 1; - kernel_thread(ts_thread, NULL, CLONE_VM | CLONE_FS); + 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) { - input_ts_installed = 0; + if (tstask) + kthread_stop(tstask); + input_unregister_device(mxc_inputdev); if (mxc_inputdev) { @@ -116,6 +187,6 @@ static void __exit mxc_ts_exit(void) late_initcall(mxc_ts_init); module_exit(mxc_ts_exit); -MODULE_DESCRIPTION("MXC input touchscreen driver"); +MODULE_DESCRIPTION("MXC touchscreen driver with calibration"); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_LICENSE("GPL"); |