blob: 2be6ef6bc4109592374a37d0f3988b839ae33da8 [file] [log] [blame]
Taniya Das6f0884b2011-09-06 16:24:21 +05301/**
2 * Synaptics Register Mapped Interface (RMI4) - RMI Function Module.
3 * Copyright (C) 2007 - 2011, Synaptics Incorporated
4 *
5 */
6/*
7 * This file is licensed under the GPL2 license.
8 *
9 *#############################################################################
10 * GPL
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published
14 * by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
20 *
21 *#############################################################################
22 */
23
24static const char functionname[10] = "fn";
25
26#include <linux/kernel.h>
27#include <linux/device.h>
28#include <linux/hrtimer.h>
29#include <linux/miscdevice.h>
30#include <linux/fs.h>
31#include <linux/delay.h>
32#include <linux/uaccess.h>
33#include <linux/slab.h>
34#include <linux/kthread.h>
35#include <linux/freezer.h>
36#include <linux/input.h>
37#include <linux/interrupt.h>
38
39#include "rmi_drvr.h"
40#include "rmi_function.h"
41#include "rmi_bus.h"
42#include "rmi_sensor.h"
43#include "rmi_f01.h"
44#include "rmi_f05.h"
45#include "rmi_f11.h"
46#include "rmi_f19.h"
47#include "rmi_f34.h"
48
49/* Each time a new RMI4 function support is added the developer needs to
50bump the number of supported functions and add the info for
51that RMI4 function to the array along with pointers to the report,
52config, init and detect functions that they coded in rmi_fxx.c
53and rmi_fxx.h - where xx is the RMI4 function number in hex for the new
54RMI4 data source function. The information for the RMI4 functions is
55obtained from the RMI4 specification document.
56 */
57#define rmi4_num_supported_data_src_fns 5
58
59/* supported RMI4 functions list - controls what we
60 * will provide support for - if it's not in the list then
61 * the developer needs to add support functions for it.*/
62static LIST_HEAD(fns_list);
63static DEFINE_MUTEX(fns_mutex);
64
65/* NOTE: Developer - add in any new RMI4 fn data info - function number
66 * and ptrs to report, config, init and detect functions. This data is
67 * used to point to the functions that need to be called to config, init,
68 * detect and report data for the new RMI4 function. Refer to the RMI4
69 * specification for information on RMI4 functions.
70 */
71/* TODO: This will eventually go away, and each function will be an independent
72 * module. */
73static struct rmi_functions_data
74 rmi4_supported_data_src_functions[rmi4_num_supported_data_src_fns] = {
75 /* Fn $11 - 2D sensing */
76 {.functionNumber = 0x11, .inthandlerFn = FN_11_inthandler, .configFn = FN_11_config, .initFn = FN_11_init, .detectFn = FN_11_detect, .attnFn = NULL},
77 /* Fn $01 - device control */
78 {.functionNumber = 0x01, .inthandlerFn = FN_01_inthandler, .configFn = FN_01_config, .initFn = FN_01_init, .detectFn = FN_01_detect, .attnFn = FN_01_attention},
79 /* Fn $05 - analog report */
80 {.functionNumber = 0x05, .inthandlerFn = FN_05_inthandler, .configFn = FN_05_config, .initFn = FN_05_init, .detectFn = FN_05_detect, .attnFn = NULL},
81 /* Fn $19 - buttons */
82 {.functionNumber = 0x19, .inthandlerFn = FN_19_inthandler, .configFn = FN_19_config, .initFn = FN_19_init, .detectFn = FN_19_detect, .attnFn = NULL},
83 /* Fn $34 - firmware reflash */
84 {.functionNumber = 0x34, .inthandlerFn = FN_34_inthandler, .configFn = FN_34_config, .initFn = FN_34_init, .detectFn = FN_34_detect, .attnFn = FN_34_attention},
85};
86
87
88/* This function is here to provide a way for external modules to access the
89 * functions list. It will try to find a matching function base on the passed
90 * in RMI4 function number and return the pointer to the struct rmi_functions
91 * if a match is found or NULL if not found.
92 */
93struct rmi_functions *rmi_find_function(int functionNum)
94{
95 struct rmi_functions *fn;
96 bool found = false;
97
98 list_for_each_entry(fn, &fns_list, link) {
99 if (functionNum == fn->functionNum) {
100 found = true;
101 break;
102 }
103 }
104
105 if (!found)
106 return NULL;
107 else
108 return fn;
109}
110EXPORT_SYMBOL(rmi_find_function);
111
112
113static void rmi_function_config(struct rmi_function_device *function)
114{
115 printk(KERN_DEBUG "%s: rmi_function_config", __func__);
116
117}
118
119#if 0 /* This may not be needed anymore. */
120/**
121 * This is the probe function passed to the RMI4 subsystem that gives us a
122 * chance to recognize an RMI4 function.
123 */
124static int rmi_function_probe(struct rmi_function_driver *function)
125{
126 struct rmi_phys_driver *rpd;
127
128 rpd = function->rpd;
129
130 if (!rpd) {
131 printk(KERN_ERR "%s: Invalid rmi physical driver - null ptr.", __func__);
132 return 0;
133 }
134
135 return 1;
136}
137#endif
138
139/** Just a stub for now.
140 */
141static int rmi_function_suspend(struct device *dev, pm_message_t state)
142{
143 printk(KERN_INFO "%s: function suspend called.", __func__);
144 return 0;
145}
146
147/** Just a stub for now.
148 */
149static int rmi_function_resume(struct device *dev)
150{
151 printk(KERN_INFO "%s: function resume called.", __func__);
152 return 0;
153}
154
155int rmi_function_register_driver(struct rmi_function_driver *drv, int fnNumber)
156{
157 int retval;
158 char *drvrname;
159
160 printk(KERN_INFO "%s: Registering function driver for F%02x.\n", __func__, fnNumber);
161
162 retval = 0;
163
164 /* Create a function device and function driver for this Fn */
165 drvrname = kzalloc(sizeof(functionname) + 4, GFP_KERNEL);
166 if (!drvrname) {
167 printk(KERN_ERR "%s: Error allocating memeory for rmi_function_driver name.\n", __func__);
168 return -ENOMEM;
169 }
170 sprintf(drvrname, "fn%02x", fnNumber);
171
172 drv->drv.name = drvrname;
173 drv->module = drv->drv.owner;
174
175 drv->drv.suspend = rmi_function_suspend;
176 drv->drv.resume = rmi_function_resume;
177
178 /* register the sensor driver */
179 retval = driver_register(&drv->drv);
180 if (retval) {
181 printk(KERN_ERR "%s: Failed driver_register %d\n",
182 __func__, retval);
183 }
184
185 return retval;
186}
187EXPORT_SYMBOL(rmi_function_register_driver);
188
189void rmi_function_unregister_driver(struct rmi_function_driver *drv)
190{
191 printk(KERN_INFO "%s: Unregistering function driver.\n", __func__);
192
193 driver_unregister(&drv->drv);
194}
195EXPORT_SYMBOL(rmi_function_unregister_driver);
196
197int rmi_function_register_device(struct rmi_function_device *function_device, int fnNumber)
198{
199 struct input_dev *input;
200 int retval;
201
202 printk(KERN_INFO "%s: Registering function device for F%02x.\n", __func__, fnNumber);
203
204 retval = 0;
205
206 /* make name - fn11, fn19, etc. */
207 dev_set_name(&function_device->dev, "%sfn%02x", function_device->sensor->drv.name, fnNumber);
208 dev_set_drvdata(&function_device->dev, function_device);
209 retval = device_register(&function_device->dev);
210 if (retval) {
211 printk(KERN_ERR "%s: Failed device_register for function device.\n",
212 __func__);
213 return retval;
214 }
215
216 input = input_allocate_device();
217 if (input == NULL) {
218 printk(KERN_ERR "%s: Failed to allocate memory for a "
219 "new input device.\n",
220 __func__);
221 return -ENOMEM;
222 }
223
224 input->name = dev_name(&function_device->dev);
225 input->phys = "rmi_function";
226 function_device->input = input;
227
228
229 /* init any input specific params for this function */
230 function_device->rmi_funcs->init(function_device);
231
232 retval = input_register_device(input);
233
234 if (retval) {
235 printk(KERN_ERR "%s: Failed input_register_device.\n",
236 __func__);
237 return retval;
238 }
239
240
241 rmi_function_config(function_device);
242
243 return retval;
244}
245EXPORT_SYMBOL(rmi_function_register_device);
246
247void rmi_function_unregister_device(struct rmi_function_device *dev)
248{
249 printk(KERN_INFO "%s: Unregistering function device.n", __func__);
250
251 input_unregister_device(dev->input);
252 device_unregister(&dev->dev);
253}
254EXPORT_SYMBOL(rmi_function_unregister_device);
255
256static int __init rmi_function_init(void)
257{
258 struct rmi_functions_data *rmi4_fn;
259 int i;
260
261 printk(KERN_DEBUG "%s: RMI Function Init\n", __func__);
262
263 /* Initialize global list of RMI4 Functions.
264 We need to add the supported RMI4 funcions so that we will have
265 pointers to the associated functions for init, config, report and
266 detect. See rmi.h for more details. The developer will add a new
267 RMI4 function number in the array in rmi_drvr.h, then add a new file to
268 the build (called rmi_fXX.c where XX is the hex number for
269 the added RMI4 function). The rest should be automatic.
270 */
271
272 /* for each function number defined in rmi.h creat a new rmi_function
273 struct and initialize the pointers to the servicing functions and then
274 add it into the global list for function support.
275 */
276 for (i = 0; i < rmi4_num_supported_data_src_fns; i++) {
277 /* Add new rmi4 function struct to list */
278 struct rmi_functions *fn = kzalloc(sizeof(*fn), GFP_KERNEL);
279 if (!fn) {
280 printk(KERN_ERR "%s: could not allocate memory "
281 "for rmi_function struct for function 0x%x\n",
282 __func__,
283 rmi4_supported_data_src_functions[i].functionNumber);
284 return -ENOMEM;
285 } else {
286
287 rmi4_fn = &rmi4_supported_data_src_functions[i];
288 fn->functionNum = rmi4_fn->functionNumber;
289 /* Fill in ptrs to functions. The functions are
290 linked in from a file called rmi_fxx.c
291 where xx is the hex number of the RMI4 function
292 from the RMI4 spec. Also, the function prototypes
293 need to be added to rmi_fxx.h - also where
294 xx is the hex number of the RMI4 function. So
295 that you don't get compile errors and that new
296 header needs to be included in the rmi_function.h
297 */
298 fn->inthandler = rmi4_fn->inthandlerFn;
299 fn->config = rmi4_fn->configFn;
300 fn->init = rmi4_fn->initFn;
301 fn->detect = rmi4_fn->detectFn;
302 fn->attention = rmi4_fn->attnFn;
303
304 /* Add the new fn to the global list */
305 mutex_lock(&fns_mutex);
306 list_add_tail(&fn->link, &fns_list);
307 mutex_unlock(&fns_mutex);
308 }
309 }
310
311 return 0;
312}
313
314static void __exit rmi_function_exit(void)
315{
316 printk(KERN_DEBUG "%s: RMI Function Exit\n", __func__);
317}
318
319
320module_init(rmi_function_init);
321module_exit(rmi_function_exit);
322
323MODULE_AUTHOR("Synaptics, Inc.");
324MODULE_DESCRIPTION("RMI4 Function Driver");
325MODULE_LICENSE("GPL");