aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/rmi4/rmi_f09.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/rmi4/rmi_f09.c')
-rw-r--r--drivers/input/touchscreen/rmi4/rmi_f09.c298
1 files changed, 298 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/rmi4/rmi_f09.c b/drivers/input/touchscreen/rmi4/rmi_f09.c
new file mode 100644
index 00000000000..0ec980d7db0
--- /dev/null
+++ b/drivers/input/touchscreen/rmi4/rmi_f09.c
@@ -0,0 +1,298 @@
1/*
2 * Copyright (c) 2011 Synaptics Incorporated
3 * Copyright (c) 2011 Unixphere
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19#include <linux/kernel.h>
20#include <linux/rmi.h>
21#include <linux/input.h>
22#include <linux/slab.h>
23
24#define QUERY_BASE_INDEX 1
25#define MAX_LEN 256
26
27/* data specific to fn $09 that needs to be kept around */
28struct f09_query {
29 u8 Limit_Register_Count;
30 union {
31 struct {
32 u8 Result_Register_Count:3;
33 u8 Reserved:3;
34 u8 InternalLimits:1;
35 u8 HostTestEn:1;
36 };
37 u8 f09_bist_query1;
38 };
39};
40
41struct f09_control {
42 /* test1 */
43 u8 Test1LimitLo;
44 u8 Test1LimitHi;
45 u8 Test1LimitDiff;
46 /* test2 */
47 u8 Test2LimitLo;
48 u8 Test2LimitHi;
49 u8 Test2LimitDiff;
50};
51
52struct f09_data {
53 u8 TestNumberControl;
54 u8 Overall_BIST_Result;
55 u8 TestResult1;
56 u8 TestResult2;
57 u8 Transmitter_Number;
58
59 union {
60 struct {
61 u8 Receiver_Number:6;
62 u8 Limit_Failure_Code:2;
63 };
64 u8 f09_bist_data2;
65 };
66};
67
68struct f09_cmd {
69 union {
70 struct {
71 u8 RunBIST:1;
72 };
73 u8 f09_bist_cmd0;
74 };
75};
76
77struct rmi_fn_09_data {
78 struct f09_query query;
79};
80
81static ssize_t rmi_f09_Limit_Register_Count_show(struct device *dev,
82 struct device_attribute *attr, char *buf);
83
84static ssize_t rmi_f09_HostTestEn_show(struct device *dev,
85 struct device_attribute *attr, char *buf);
86
87static ssize_t rmi_f09_HostTestEn_store(struct device *dev,
88 struct device_attribute *attr,
89 char *buf, size_t count);
90
91static ssize_t rmi_f09_InternalLimits_show(struct device *dev,
92 struct device_attribute *attr, char *buf);
93
94static ssize_t rmi_f09_Result_Register_Count_show(struct device *dev,
95 struct device_attribute *attr, char *buf);
96
97static ssize_t rmi_f09_Overall_BIST_Result_show(struct device *dev,
98 struct device_attribute *attr, char *buf);
99
100static ssize_t rmi_f09_Overall_BIST_Result_store(struct device *dev,
101 struct device_attribute *attr,
102 const char *buf, size_t count);
103
104static struct device_attribute attrs[] = {
105 __ATTR(Limit_Register_Count, RMI_RO_ATTR,
106 rmi_f09_Limit_Register_Count_show, rmi_store_error),
107 __ATTR(HostTestEn, RMI_RW_ATTR,
108 rmi_f09_HostTestEn_show, rmi_f09_HostTestEn_store),
109 __ATTR(InternalLimits, RMI_RO_ATTR,
110 rmi_f09_Limit_Register_Count_show, rmi_store_error),
111 __ATTR(Result_Register_Count, RMI_RO_ATTR,
112 rmi_f09_Result_Register_Count_show, rmi_store_error),
113};
114
115static int rmi_f09_init(struct rmi_function_container *fc)
116{
117 struct rmi_device *rmi_dev = fc->rmi_dev;
118 struct rmi_device_platform_data *pdata;
119 struct rmi_fn_09_data *f09;
120 u8 query_base_addr;
121 int rc;
122 int i;
123 int attr_count = 0;
124 int retval = 0;
125
126 dev_info(&fc->dev, "Intializing F09 values.");
127
128 f09 = kzalloc(sizeof(struct rmi_fn_09_data), GFP_KERNEL);
129 if (!f09) {
130 dev_err(&fc->dev, "Failed to allocate rmi_fn_09_data.\n");
131 retval = -ENOMEM;
132 goto error_exit;
133 }
134 fc->data = f09;
135
136 pdata = to_rmi_platform_data(rmi_dev);
137 query_base_addr = fc->fd.query_base_addr;
138
139 /* initial all default values for f09 query here */
140 rc = rmi_read_block(rmi_dev, query_base_addr,
141 (u8 *)&f09->query, sizeof(f09->query));
142 if (rc < 0) {
143 dev_err(&fc->dev, "Failed to read query register."
144 " from 0x%04x\n", query_base_addr);
145 goto error_exit;
146 }
147
148 dev_dbg(&fc->dev, "Creating sysfs files.");
149 /* Set up sysfs device attributes. */
150 for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
151 if (sysfs_create_file
152 (&fc->dev.kobj, &attrs[attr_count].attr) < 0) {
153 dev_err(&fc->dev, "Failed to create sysfs file for %s.",
154 attrs[attr_count].attr.name);
155 retval = -ENODEV;
156 goto error_exit;
157 }
158 }
159 return 0;
160
161error_exit:
162 dev_err(&fc->dev, "An error occured in F09 init!\n");
163 for (attr_count--; attr_count >= 0; attr_count--)
164 sysfs_remove_file(&fc->dev.kobj,
165 &attrs[attr_count].attr);
166 kfree(f09);
167 return retval;
168}
169
170static void rmi_f09_remove(struct rmi_function_container *fc)
171{
172 struct rmi_fn_09_data *data = fc->data;
173 if (data) {
174 kfree(data->query.Limit_Register_Count);
175 kfree(data->query.f09_bist_query1);
176 }
177 kfree(fc->data);
178}
179
180static struct rmi_function_handler function_handler = {
181 .func = 0x09,
182 .init = rmi_f09_init,
183 .remove = rmi_f09_remove
184};
185
186static int __init rmi_f09_module_init(void)
187{
188 int error;
189
190 error = rmi_register_function_driver(&function_handler);
191 if (error < 0) {
192 pr_err("%s: register failed!\n", __func__);
193 return error;
194 }
195
196 return 0;
197}
198
199static void rmi_f09_module_exit(void)
200{
201 rmi_unregister_function_driver(&function_handler);
202}
203
204
205static ssize_t rmi_f09_Limit_Register_Count_show(struct device *dev,
206 struct device_attribute *attr,
207 char *buf)
208{
209 struct rmi_function_container *fc;
210 struct rmi_fn_09_data *data;
211
212 fc = to_rmi_function_container(dev);
213 data = fc->data;
214 return snprintf(buf, PAGE_SIZE, "%u\n",
215 data->query.Limit_Register_Count);
216}
217
218static ssize_t rmi_f09_HostTestEn_show(struct device *dev,
219 struct device_attribute *attr,
220 char *buf)
221{
222 struct rmi_function_container *fc;
223 struct rmi_fn_09_data *data;
224
225 fc = to_rmi_function_container(dev);
226 data = fc->data;
227 return snprintf(buf, PAGE_SIZE, "%u\n",
228 data->query.HostTestEn);
229}
230
231static ssize_t rmi_f09_HostTestEn_store(struct device *dev,
232 struct device_attribute *attr,
233 char *buf, size_t count)
234{
235 struct rmi_function_container *fc;
236 struct rmi_fn_09_data *data;
237 unsigned int new_value;
238 int result;
239
240 fc = to_rmi_function_container(dev);
241 data = fc->data;
242 if (sscanf(buf, "%u", &new_value) != 1) {
243 dev_err(dev,
244 "%s: Error - HostTestEn_store has an "
245 "invalid len.\n",
246 __func__);
247 return -EINVAL;
248 }
249
250 if (new_value < 0 || new_value > 1) {
251 dev_err(dev, "%s: Invalid HostTestEn bit %s.", __func__, buf);
252 return -EINVAL;
253 }
254 data->query.HostTestEn = new_value;
255 result = rmi_write(fc->rmi_dev, fc->fd.query_base_addr,
256 data->query.HostTestEn);
257 if (result < 0) {
258 dev_err(dev, "%s : Could not write HostTestEn_store to 0x%x\n",
259 __func__, fc->fd.query_base_addr);
260 return result;
261 }
262
263 return count;
264
265}
266
267static ssize_t rmi_f09_InternalLimits_show(struct device *dev,
268 struct device_attribute *attr,
269 char *buf)
270{
271 struct rmi_function_container *fc;
272 struct rmi_fn_09_data *data;
273
274 fc = to_rmi_function_container(dev);
275 data = fc->data;
276 return snprintf(buf, PAGE_SIZE, "%u\n",
277 data->query.InternalLimits);
278}
279
280static ssize_t rmi_f09_Result_Register_Count_show(struct device *dev,
281 struct device_attribute *attr,
282 char *buf)
283{
284 struct rmi_function_container *fc;
285 struct rmi_fn_09_data *data;
286
287 fc = to_rmi_function_container(dev);
288 data = fc->data;
289 return snprintf(buf, PAGE_SIZE, "%u\n",
290 data->query.Result_Register_Count);
291}
292
293module_init(rmi_f09_module_init);
294module_exit(rmi_f09_module_exit);
295
296MODULE_AUTHOR("Allie Xiong <axiong@Synaptics.com>");
297MODULE_DESCRIPTION("RMI F09 module");
298MODULE_LICENSE("GPL");