S3C: Backported openmoko's touchscreen filters
[linux-2.6/mini2440.git] / drivers / input / touchscreen / ts_filter_linear.c
blobc336252d0ff5dd4f024f95b705c1bae1be3acb9b
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * Copyright (C) 2008 by Openmoko, Inc.
17 * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
18 * All rights reserved.
20 * Linearly scale touchscreen values.
22 * Expose the TS_FILTER_LINEAR_NCONSTANTS for the linear transformation
23 * using sysfs.
27 #include "ts_filter_linear.h"
28 #include <linux/kernel.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
33 /* sysfs functions */
36 static ssize_t const_attr_show(struct kobject *kobj,
37 struct attribute *attr,
38 char *buf)
40 struct const_attribute *a = to_const_attr(attr);
42 return a->show(to_const_obj(kobj), a, buf);
45 static ssize_t const_attr_store(struct kobject *kobj,
46 struct attribute *attr,
47 const char *buf, size_t len)
49 struct const_attribute *a = to_const_attr(attr);
51 return a->store(to_const_obj(kobj), a, buf, len);
54 static struct sysfs_ops const_sysfs_ops = {
55 .show = const_attr_show,
56 .store = const_attr_store,
59 static void const_release(struct kobject *kobj)
61 kfree(to_const_obj(kobj)->tsfl);
64 static ssize_t const_show(struct const_obj *obj, struct const_attribute *attr,
65 char *buf)
67 int who;
69 sscanf(attr->attr.name, "%d", &who);
70 return sprintf(buf, "%d\n", obj->tsfl->constants[who]);
73 static ssize_t const_store(struct const_obj *obj, struct const_attribute *attr,
74 const char *buf, size_t count)
76 int who;
78 sscanf(attr->attr.name, "%d", &who);
79 sscanf(buf, "%d", &obj->tsfl->constants[who]);
80 return count;
83 /* filter functions */
85 static struct ts_filter *ts_filter_linear_create(struct platform_device *pdev,
86 void *conf, int count_coords)
88 struct ts_filter_linear *tsfl;
89 int i;
90 int ret;
92 tsfl = kzalloc(sizeof(struct ts_filter_linear), GFP_KERNEL);
93 if (!tsfl)
94 return NULL;
96 tsfl->config = (struct ts_filter_linear_configuration *)conf;
97 tsfl->tsf.count_coords = count_coords;
99 for (i = 0; i < TS_FILTER_LINEAR_NCONSTANTS; ++i) {
100 tsfl->constants[i] = tsfl->config->constants[i];
102 /* sysfs */
103 sprintf(tsfl->attr_names[i], "%d", i);
104 tsfl->kattrs[i].attr.name = tsfl->attr_names[i];
105 tsfl->kattrs[i].attr.mode = 0666;
106 tsfl->kattrs[i].show = const_show;
107 tsfl->kattrs[i].store = const_store;
108 tsfl->attrs[i] = &tsfl->kattrs[i].attr;
110 tsfl->attrs[i] = NULL;
112 tsfl->const_ktype.sysfs_ops = &const_sysfs_ops;
113 tsfl->const_ktype.release = const_release;
114 tsfl->const_ktype.default_attrs = tsfl->attrs;
115 tsfl->c_obj.tsfl = tsfl; /* kernel frees tsfl in const_release */
117 ret = kobject_init_and_add(&tsfl->c_obj.kobj, &tsfl->const_ktype,
118 &pdev->dev.kobj, "calibration");
119 if (ret) {
120 kobject_put(&tsfl->c_obj.kobj);
121 return NULL;
124 printk(KERN_INFO" Created Linear ts filter depth %d\n", count_coords);
126 return &tsfl->tsf;
129 static void ts_filter_linear_destroy(struct platform_device *pdev,
130 struct ts_filter *tsf)
132 struct ts_filter_linear *tsfl = (struct ts_filter_linear *)tsf;
134 /* kernel frees tsfl in const_release */
135 kobject_put(&tsfl->c_obj.kobj);
138 static void ts_filter_linear_clear(struct ts_filter *tsf)
140 if (tsf->next) /* chain */
141 (tsf->next->api->clear)(tsf->next);
145 static void ts_filter_linear_scale(struct ts_filter *tsf, int *coords)
147 struct ts_filter_linear *tsfl = (struct ts_filter_linear *)tsf;
148 int *k = tsfl->constants;
149 int c0 = coords[tsfl->config->coord0];
150 int c1 = coords[tsfl->config->coord1];
152 coords[tsfl->config->coord0] = (k[2] + k[0] * c0 + k[1] * c1) / k[6];
153 coords[tsfl->config->coord1] = (k[5] + k[3] * c0 + k[4] * c1) / k[6];
155 if (tsf->next)
156 (tsf->next->api->scale)(tsf->next, coords);
159 static int ts_filter_linear_process(struct ts_filter *tsf, int *coords)
161 if (tsf->next)
162 return (tsf->next->api->process)(tsf->next, coords);
164 return 1;
167 struct ts_filter_api ts_filter_linear_api = {
168 .create = ts_filter_linear_create,
169 .destroy = ts_filter_linear_destroy,
170 .clear = ts_filter_linear_clear,
171 .process = ts_filter_linear_process,
172 .scale = ts_filter_linear_scale,