• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7800-V1.0.2.28/target/linux/s3c24xx/files-2.6.30/drivers/input/touchscreen/
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.
6 *
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.
11 *
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
15 *
16 * Copyright (C) 2008,2009 by Openmoko, Inc.
17 * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
18 * All rights reserved.
19 *
20 * Linearly scale touchscreen values.
21 *
22 * Expose the TS_FILTER_LINEAR_NCONSTANTS for the linear transformation
23 * using sysfs.
24 *
25 */
26
27#include <linux/kernel.h>
28#include <linux/slab.h>
29#include <linux/string.h>
30
31#include <linux/touchscreen/ts_filter_linear.h>
32
33struct ts_filter_linear;
34
35/* Sysfs code. */
36
37struct const_obj {
38	/* The actual private object. */
39	struct ts_filter_linear *tsfl;
40	/* Our kobject. */
41	struct kobject kobj;
42};
43
44#define to_const_obj(x) container_of(x, struct const_obj, kobj)
45
46struct const_attribute {
47	struct attribute attr;
48	ssize_t (*show)(struct const_obj *const, struct const_attribute *attr,
49			char *buf);
50	ssize_t (*store)(struct const_obj *const, struct const_attribute *attr,
51			 const char *buf, size_t count);
52};
53
54#define to_const_attr(x) container_of(x, struct const_attribute, attr)
55
56
57/* Private linear filter structure. */
58
59struct ts_filter_linear {
60	/* Private configuration for this filter. */
61	struct ts_filter_linear_configuration *config;
62
63	/* Generic filter API. */
64	struct ts_filter tsf;
65
66	/* Linear constants for the transformation. */
67	int constants[TS_FILTER_LINEAR_NCONSTANTS];
68
69	/* Sysfs. */
70
71	/* Our const_object. */
72	struct const_obj c_obj;
73	/* Our type. We will stick operations to it. */
74	struct kobj_type const_ktype;
75	/* Attrs. of the virtual files. */
76	struct const_attribute kattrs[TS_FILTER_LINEAR_NCONSTANTS];
77	/* Default Attrs. Always NULL for us. */
78	struct attribute *attrs[TS_FILTER_LINEAR_NCONSTANTS + 1];
79	/* Storage for the name of the virtual files. */
80	char attr_names[TS_FILTER_LINEAR_NCONSTANTS][2];
81};
82
83#define ts_filter_to_filter_linear(f) \
84	container_of(f, struct ts_filter_linear, tsf)
85
86/* Sysfs functions. */
87
88static ssize_t const_attr_show(struct kobject *kobj,
89			       struct attribute *attr,
90			       char *buf)
91{
92	struct const_attribute *a = to_const_attr(attr);
93
94	return a->show(to_const_obj(kobj), a, buf);
95}
96
97static ssize_t const_attr_store(struct kobject *kobj,
98				struct attribute *attr,
99				const char *buf, size_t len)
100{
101	struct const_attribute *a = to_const_attr(attr);
102
103	return a->store(to_const_obj(kobj), a, buf, len);
104}
105
106static struct sysfs_ops const_sysfs_ops = {
107	.show =		const_attr_show,
108	.store =	const_attr_store,
109};
110
111static void const_release(struct kobject *kobj)
112{
113	kfree(to_const_obj(kobj)->tsfl);
114}
115
116static ssize_t const_show(struct const_obj *obj, struct const_attribute *attr,
117			  char *buf)
118{
119	int who;
120
121	sscanf(attr->attr.name, "%d", &who);
122	return sprintf(buf, "%d\n", obj->tsfl->constants[who]);
123}
124
125static ssize_t const_store(struct const_obj *obj, struct const_attribute *attr,
126			   const char *buf, size_t count)
127{
128	int who;
129
130	sscanf(attr->attr.name, "%d", &who);
131	sscanf(buf, "%d", &obj->tsfl->constants[who]);
132	return count;
133}
134
135/* Filter functions. */
136
137static struct ts_filter *ts_filter_linear_create(
138	struct platform_device *pdev,
139	const struct ts_filter_configuration *conf,
140	int count_coords)
141{
142	struct ts_filter_linear *tsfl;
143	int i;
144	int ret;
145
146	tsfl = kzalloc(sizeof(struct ts_filter_linear), GFP_KERNEL);
147	if (!tsfl)
148		return NULL;
149
150	tsfl->config = container_of(conf,
151				    struct ts_filter_linear_configuration,
152				    config);
153
154	tsfl->tsf.count_coords = count_coords;
155
156	for (i = 0; i < TS_FILTER_LINEAR_NCONSTANTS; ++i) {
157		tsfl->constants[i] = tsfl->config->constants[i];
158
159		/* sysfs */
160		sprintf(tsfl->attr_names[i], "%d", i);
161		tsfl->kattrs[i].attr.name = tsfl->attr_names[i];
162		tsfl->kattrs[i].attr.mode = 0666;
163		tsfl->kattrs[i].show = const_show;
164		tsfl->kattrs[i].store = const_store;
165		tsfl->attrs[i] = &tsfl->kattrs[i].attr;
166	}
167	tsfl->attrs[i] = NULL;
168
169	tsfl->const_ktype.sysfs_ops = &const_sysfs_ops;
170	tsfl->const_ktype.release = const_release;
171	tsfl->const_ktype.default_attrs = tsfl->attrs;
172	tsfl->c_obj.tsfl = tsfl; /* kernel frees tsfl in const_release */
173
174	ret = kobject_init_and_add(&tsfl->c_obj.kobj, &tsfl->const_ktype,
175				   &pdev->dev.kobj, "calibration");
176	if (ret) {
177		kobject_put(&tsfl->c_obj.kobj);
178		return NULL;
179	}
180
181	dev_info(&pdev->dev, "Created Linear filter coords:%d\n", count_coords);
182
183	return &tsfl->tsf;
184}
185
186static void ts_filter_linear_destroy(struct ts_filter *tsf)
187{
188	struct ts_filter_linear *tsfl = ts_filter_to_filter_linear(tsf);
189
190	/* Kernel frees tsfl in const_release. */
191	kobject_put(&tsfl->c_obj.kobj);
192}
193
194static void ts_filter_linear_scale(struct ts_filter *tsf, int *coords)
195{
196	struct ts_filter_linear *tsfl = ts_filter_to_filter_linear(tsf);
197
198	int *k = tsfl->constants;
199	int c0 = coords[tsfl->config->coord0];
200	int c1 = coords[tsfl->config->coord1];
201
202	coords[tsfl->config->coord0] = (k[2] + k[0] * c0 + k[1] * c1) / k[6];
203	coords[tsfl->config->coord1] = (k[5] + k[3] * c0 + k[4] * c1) / k[6];
204}
205
206const struct ts_filter_api ts_filter_linear_api = {
207	.create =	ts_filter_linear_create,
208	.destroy =	ts_filter_linear_destroy,
209	.scale =	ts_filter_linear_scale,
210};
211EXPORT_SYMBOL_GPL(ts_filter_linear_api);
212
213