[PATCH 2/3] Add Linear Filter

Nelson Castillo nelsoneci at gmail.com
Mon Dec 15 06:49:45 CET 2008


This filter allows us to modify the coordinates of the
touchscreen output with the calibration values for the device.

It adds a /sys/ts-calibration directory with 7 files (0..6) that
you can use to change the calibration constants.

This path is not correct. Please do not rely on it because we
will change it really soon.

Signed-off-by: Nelson Castillo <nelsoneci at gmail.com>
---

 drivers/input/touchscreen/Kconfig            |    9 +
 drivers/input/touchscreen/Makefile           |    1 
 drivers/input/touchscreen/ts_filter_linear.c |  177 ++++++++++++++++++++++++++
 3 files changed, 186 insertions(+), 1 deletions(-)
 create mode 100644 drivers/input/touchscreen/ts_filter_linear.c

diff --git a/arch/arm/configs/gta02-moredrivers-defconfig b/arch/arm/configs/gta02-moredrivers-defconfig
index 0d67185..9294b53 100644
--- a/arch/arm/configs/gta02-moredrivers-defconfig
+++ b/arch/arm/configs/gta02-moredrivers-defconfig
@@ -983,6 +983,7 @@ CONFIG_TOUCHSCREEN_FILTER=y
 CONFIG_TOUCHSCREEN_FILTER_GROUP=y
 CONFIG_TOUCHSCREEN_FILTER_MEDIAN=y
 CONFIG_TOUCHSCREEN_FILTER_MEAN=y
+CONFIG_TOUCHSCREEN_FILTER_LINEAR=y
 # CONFIG_TOUCHSCREEN_ADS7846 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 CONFIG_TOUCHSCREEN_S3C2410=y
diff --git a/arch/arm/configs/gta02-packaging-defconfig b/arch/arm/configs/gta02-packaging-defconfig
index 0f8ee7e..0256022 100644
--- a/arch/arm/configs/gta02-packaging-defconfig
+++ b/arch/arm/configs/gta02-packaging-defconfig
@@ -987,6 +987,7 @@ CONFIG_TOUCHSCREEN_FILTER=y
 CONFIG_TOUCHSCREEN_FILTER_GROUP=y
 CONFIG_TOUCHSCREEN_FILTER_MEDIAN=y
 CONFIG_TOUCHSCREEN_FILTER_MEAN=y
+CONFIG_TOUCHSCREEN_FILTER_LINEAR=y
 # CONFIG_TOUCHSCREEN_ADS7846 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 CONFIG_TOUCHSCREEN_S3C2410=y
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index e90f82b..cd0a7c0 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -103,6 +103,7 @@
 
 #include "../plat-s3c24xx/neo1973_pm_gps.h"
 
+#include <linux/ts_filter_linear.h>
 #include <linux/ts_filter_mean.h>
 #include <linux/ts_filter_median.h>
 #include <linux/ts_filter_group.h>
@@ -1019,6 +1020,12 @@ static struct s3c2410_udc_mach_info gta02_udc_cfg = {
 
 /* touchscreen configuration */
 
+static struct ts_filter_linear_configuration gta02_ts_linear_config = {
+	.constants = {1, 0, 0, 0, 1, 0, 1},	/* don't modify coords */
+	.coord0 = 0,
+	.coord1 = 1,
+};
+
 static struct ts_filter_group_configuration gta02_ts_group_config = {
 	.extent = 12,
 	.close_enough = 10,
@@ -1044,11 +1051,13 @@ static struct s3c2410_ts_mach_info gta02_ts_cfg = {
 		[0] = &ts_filter_group_api,
 		[1] = &ts_filter_median_api,
 		[2] = &ts_filter_mean_api,
+		[3] = &ts_filter_linear_api,
 	},
 	.filter_config = {
 		[0] = &gta02_ts_group_config,
 		[1] = &gta02_ts_median_config,
 		[2] = &gta02_ts_mean_config,
+		[3] = &gta02_ts_linear_config,
 	},
 };
 
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index a0f8599..2d5adf8 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -29,7 +29,6 @@ config TOUCHSCREEN_FILTER_GROUP
 	  Say Y here if you want to use the Group touchscreen filter, it
 	  avoids using atypical samples.
 
-
 config TOUCHSCREEN_FILTER_MEDIAN
 	bool "Median Average Touchscreen Filter"
 	depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
@@ -46,6 +45,14 @@ config TOUCHSCREEN_FILTER_MEAN
 	  Say Y here if you want to use the Mean touchscreen filter, it
 	  can further improve decent quality data by removing jitter
 
+config TOUCHSCREEN_FILTER_LINEAR
+	bool "Linear Touchscreen Filter"
+	depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
+	default Y
+	help
+	  Say Y here if you want to use the Mean touchscreen filter, it
+	  enables the use of calibration data for the touchscreen.
+
 endif
 
 config TOUCHSCREEN_ADS7846
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 9a6162c..f0c221f 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -34,5 +34,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)	+= mainstone-wm97xx.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_FILTER)	+= ts_filter.o
 obj-$(CONFIG_TOUCHSCREEN_FILTER_GROUP)	+= ts_filter_group.o
+obj-$(CONFIG_TOUCHSCREEN_FILTER_LINEAR)	+= ts_filter_linear.o
 obj-$(CONFIG_TOUCHSCREEN_FILTER_MEDIAN)	+= ts_filter_median.o
 obj-$(CONFIG_TOUCHSCREEN_FILTER_MEAN)	+= ts_filter_mean.o
diff --git a/drivers/input/touchscreen/ts_filter_linear.c b/drivers/input/touchscreen/ts_filter_linear.c
new file mode 100644
index 0000000..01b66a1
--- /dev/null
+++ b/drivers/input/touchscreen/ts_filter_linear.c
@@ -0,0 +1,177 @@
+/*
+ * 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; 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
+ *
+ * Copyright (C) 2008 by Openmoko, Inc.
+ * Author: Nelson Castillo <arhuaco at freaks-unidos.net>
+ * All rights reserved.
+ *
+ * Linearly scale touchscreen values.
+ *
+ * Expose the TS_FILTER_LINEAR_NCONSTANTS for the linear transformation
+ * using sysfs.
+ *
+ */
+
+#include <linux/ts_filter_linear.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+
+/*
+ * sysfs functions
+ */
+
+
+static ssize_t const_attr_show(struct kobject *kobj,
+			       struct attribute *attr,
+			       char *buf)
+{
+	struct const_attribute *a = to_const_attr(attr);
+
+	return a->show(to_const_obj(kobj), a, buf);
+}
+
+static ssize_t const_attr_store(struct kobject *kobj,
+				struct attribute *attr,
+				const char *buf, size_t len)
+{
+	struct const_attribute *a = to_const_attr(attr);
+
+	return a->store(to_const_obj(kobj), a, buf, len);
+}
+
+static struct sysfs_ops const_sysfs_ops = {
+	.show =		const_attr_show,
+	.store =	const_attr_store,
+};
+
+static void const_release(struct kobject *kobj)
+{
+	kfree(to_const_obj(kobj)->tsfl);
+}
+
+static ssize_t const_show(struct const_obj *obj, struct const_attribute *attr,
+			  char *buf)
+{
+	int who;
+
+	sscanf(attr->attr.name, "%d", &who);
+	return sprintf(buf, "%d\n", obj->tsfl->constants[who]);
+}
+
+static ssize_t const_store(struct const_obj *obj, struct const_attribute *attr,
+			   const char *buf, size_t count)
+{
+	int who;
+
+	sscanf(attr->attr.name, "%d", &who);
+	sscanf(buf, "%d", &obj->tsfl->constants[who]);
+	return count;
+}
+
+/*
+ * filter functions
+ */
+
+static struct ts_filter *ts_filter_linear_create(void *conf, int count_coords)
+{
+	struct ts_filter_linear *tsfl;
+	int i;
+	int ret;
+
+	tsfl = kzalloc(sizeof(struct ts_filter_linear), GFP_KERNEL);
+	if (!tsfl)
+		return NULL;
+
+	tsfl->config = (struct ts_filter_linear_configuration *)conf;
+	tsfl->tsf.count_coords = count_coords;
+
+	for (i = 0; i < TS_FILTER_LINEAR_NCONSTANTS; ++i) {
+		tsfl->constants[i] = tsfl->config->constants[i];
+
+		/* sysfs */
+		sprintf(tsfl->attr_names[i], "%d", i);
+		tsfl->kattrs[i].attr.name = tsfl->attr_names[i];
+		tsfl->kattrs[i].attr.mode = 0666;
+		tsfl->kattrs[i].show = const_show;
+		tsfl->kattrs[i].store = const_store;
+		tsfl->attrs[i] = &tsfl->kattrs[i].attr;
+	}
+	tsfl->attrs[i] = NULL;
+
+	tsfl->const_ktype.sysfs_ops = &const_sysfs_ops;
+	tsfl->const_ktype.release = const_release;
+	tsfl->const_ktype.default_attrs = tsfl->attrs;
+	tsfl->c_obj.tsfl = tsfl; /* kernel frees tsfl in const_release */
+
+	/* TODO: /sys/ts-calibration is not OK */
+	ret = kobject_init_and_add(&tsfl->c_obj.kobj, &tsfl->const_ktype, NULL,
+				   "ts-calibration");
+	if (ret) {
+		kobject_put(&tsfl->c_obj.kobj);
+		return NULL;
+	}
+
+	printk(KERN_INFO"  Created Linear ts filter depth %d\n", count_coords);
+
+	return &tsfl->tsf;
+}
+
+
+static void ts_filter_linear_destroy(struct ts_filter *tsf)
+{
+	struct ts_filter_linear *tsfl = (struct ts_filter_linear *)tsf;
+
+	/* kernel frees tsfl in const_release */
+	kobject_put(&tsfl->c_obj.kobj);
+}
+
+static void ts_filter_linear_clear(struct ts_filter *tsf)
+{
+	if (tsf->next) /* chain */
+		(tsf->next->api->clear)(tsf->next);
+}
+
+
+static void ts_filter_linear_scale(struct ts_filter *tsf, int *coords)
+{
+	struct ts_filter_linear *tsfl = (struct ts_filter_linear *)tsf;
+	int *k = tsfl->constants;
+	int c0 = coords[tsfl->config->coord0];
+	int c1 = coords[tsfl->config->coord1];
+
+	coords[tsfl->config->coord0] = (k[2] + k[0] * c0 + k[1] * c1) / k[6];
+	coords[tsfl->config->coord1] = (k[5] + k[3] * c0 + k[4] * c1) / k[6];
+
+	if (tsf->next)
+		(tsf->next->api->scale)(tsf->next, coords);
+}
+
+static int ts_filter_linear_process(struct ts_filter *tsf, int *coords)
+{
+	if (tsf->next)
+		return (tsf->next->api->process)(tsf->next, coords);
+
+	return 1;
+}
+
+struct ts_filter_api ts_filter_linear_api = {
+	.create = ts_filter_linear_create,
+	.destroy = ts_filter_linear_destroy,
+	.clear = ts_filter_linear_clear,
+	.process = ts_filter_linear_process,
+	.scale = ts_filter_linear_scale,
+};
diff --git a/include/linux/ts_filter_linear.h b/include/linux/ts_filter_linear.h
new file mode 100644
index 0000000..dab5390
--- /dev/null
+++ b/include/linux/ts_filter_linear.h
@@ -0,0 +1,64 @@
+#ifndef __TS_FILTER_LINEAR_H__
+#define __TS_FILTER_LINEAR_H__
+
+#include <linux/ts_filter.h>
+#include <linux/kobject.h>
+
+/*
+ * touchscreen linear filter.
+ *
+ * Copyright (C) 2008 by Openmoko, Inc.
+ * Author: Nelson Castillo <arhuaco at freaks-unidos.net>
+ *
+ */
+
+#define TS_FILTER_LINEAR_NCONSTANTS 7
+
+/* sysfs */
+
+struct ts_filter_linear;
+
+struct const_obj {
+	struct ts_filter_linear *tsfl;
+	struct kobject kobj;
+};
+
+#define to_const_obj(x) container_of(x, struct const_obj, kobj)
+
+struct const_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct const_obj *const, struct const_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct const_obj *const, struct const_attribute *attr,
+			 const char *buf, size_t count);
+};
+
+#define to_const_attr(x) container_of(x, struct const_attribute, attr)
+
+/* filter configuration */
+
+struct ts_filter_linear_configuration {
+	int constants[TS_FILTER_LINEAR_NCONSTANTS];
+	int coord0;
+	int coord1;
+};
+
+/* the filter */
+
+struct ts_filter_linear {
+	struct ts_filter tsf;
+	struct ts_filter_linear_configuration *config;
+
+	int constants[TS_FILTER_LINEAR_NCONSTANTS];
+
+	/* sysfs */
+	struct const_obj c_obj;
+	struct kobj_type const_ktype;
+	struct const_attribute kattrs[TS_FILTER_LINEAR_NCONSTANTS];
+	struct attribute *attrs[TS_FILTER_LINEAR_NCONSTANTS + 1];
+	char attr_names[TS_FILTER_LINEAR_NCONSTANTS][2];
+};
+
+extern struct ts_filter_api ts_filter_linear_api;
+
+#endif




More information about the openmoko-kernel mailing list