Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: drivers/input/mouse/qci_touchpad.c

Issue 724001: add trackpad driver in st1.5 (Closed)
Patch Set: Correct format error Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « drivers/input/mouse/Makefile ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Quanta I2C Touchpad Driver
2 *
3 * Copyright (C) 2009 Quanta Computer Inc.
4 * Author: Hsin Wu <hsin.wu@quantatw.com>
5 * Author: Austin Lai <austin.lai@quantatw.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18 /*
19 *
20 * The Driver with I/O communications via the I2C Interface for ON2 of AP BU.
21 * And it is only working on the nuvoTon WPCE775x Embedded Controller.
22 *
23 */
24
25 #include <linux/kernel.h>
26 #include <linux/init.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/jiffies.h>
30 #include <linux/i2c.h>
31 #include <linux/mutex.h>
32 #include <linux/interrupt.h>
33 #include <linux/input.h>
34 #include <linux/keyboard.h>
35 #include <linux/gpio.h>
36 #include <linux/delay.h>
37
38 #define TOUCHPAD_ID_NAME "qci-i2cpad"
39 #define TOUCHPAD_NAME "PS2 Touchpad"
40 #define TOUCHPAD_DEVICE "/i2c/input1"
41 #define TOUCHPAD_CMD_ENABLE 0xF4
42
43 static int __devinit qcitp_probe(struct i2c_client *client,
44 const struct i2c_device_id *id);
45 static int __devexit qcitp_remove(struct i2c_client *kbd);
46
47 /* General structure to hold the driver data */
48 struct i2ctpad_drv_data {
49 struct i2c_client *ti2c_client;
50 struct work_struct work;
51 struct input_dev *qcitp_dev;
52 struct kobject *tp_kobj;
53 unsigned int qcitp_gpio;
54 unsigned int qcitp_irq;
55 char ecdata[8];
56 };
57
58 static int tp_sense_val = 10;
59 static ssize_t tp_sensitive_show(struct kobject *kobj,
60 struct kobj_attribute *attr, char * buf)
61 {
62 return sprintf(buf, "%d\n", tp_sense_val);
63 }
64
65 static ssize_t tp_sensitive_store(struct kobject *kobj,
66 struct kobj_attribute *attr, const char* buf, size_t n)
67 {
68 unsigned int val = 0;
69 sscanf(buf, "%d", &val);
70
71 if (val >= 1 && val <= 10)
72 tp_sense_val = val;
73 else
74 return -ENOSYS;
75
76 return sizeof(buf);
77 }
78
79 static struct kobj_attribute tp_sensitivity = __ATTR(tp_sensitivity ,
80 0644 ,
81 tp_sensitive_show ,
82 tp_sensitive_store);
83
84 static struct attribute *g_tp[] = {
85 &tp_sensitivity.attr,
86 NULL,
87 };
88
89 static struct attribute_group attr_group = {
90 .attrs = g_tp,
91 };
92
93 /*-----------------------------------------------------------------------------
94 * Driver functions
95 *---------------------------------------------------------------------------*/
96
97 #ifdef CONFIG_PM
98 static int qcitp_suspend(struct device *dev)
99 {
100 return 0;
101 }
102
103 static int qcitp_resume(struct device *dev)
104 {
105 return 0;
106 }
107 #endif
108
109 static const struct i2c_device_id qcitp_idtable[] = {
110 { TOUCHPAD_ID_NAME, 0 },
111 { }
112 };
113
114 MODULE_DEVICE_TABLE(i2c, qcitp_idtable);
115 #ifdef CONFIG_PM
116 static struct dev_pm_ops qcitp_pm_ops = {
117 .suspend = qcitp_suspend,
118 .resume = qcitp_resume,
119 };
120 #endif
121 static struct i2c_driver i2ctp_driver = {
122 .driver = {
123 .owner = THIS_MODULE,
124 .name = TOUCHPAD_ID_NAME,
125 #ifdef CONFIG_PM
126 .pm = &qcitp_pm_ops,
127 #endif
128 },
129 .probe = qcitp_probe,
130 .remove = __devexit_p(qcitp_remove),
131 .id_table = qcitp_idtable,
132 };
133
134 static void qcitp_fetch_data(struct i2c_client *tpad_client,
135 char *ec_data)
136 {
137 struct i2c_msg tp_msg;
138 int ret;
139 tp_msg.addr = tpad_client->addr;
140 tp_msg.flags = I2C_M_RD;
141 tp_msg.len = 3;
142 tp_msg.buf = (char *)&ec_data[0];
143 ret = i2c_transfer(tpad_client->adapter, &tp_msg, 1);
144 }
145
146 static void qcitp_report_key(struct input_dev *tpad_dev, char *ec_data)
147 {
148 int dx = 0;
149 int dy = 0;
150
151 if (ec_data[1])
152 dx = (int) ec_data[1] -
153 (int) ((ec_data[0] << 4) & 0x100);
154
155 if (ec_data[2])
156 dy = (int) ((ec_data[0] << 3) & 0x100) -
157 (int) ec_data[2];
158
159 dx = (dx * tp_sense_val)/10;
160 dy = (dy * tp_sense_val)/10;
161
162 input_report_key(tpad_dev, BTN_LEFT, ec_data[0] & 0x01);
163 input_report_key(tpad_dev, BTN_RIGHT, ec_data[0] & 0x02);
164 input_report_key(tpad_dev, BTN_MIDDLE, ec_data[0] & 0x04);
165 input_report_rel(tpad_dev, REL_X, dx);
166 input_report_rel(tpad_dev, REL_Y, dy);
167 input_sync(tpad_dev);
168 }
169
170 static void qcitp_work_handler(struct work_struct *_work)
171 {
172 struct i2ctpad_drv_data *itpad_drv_data =
173 container_of(_work, struct i2ctpad_drv_data, work);
174
175 struct i2c_client *itpad_client = itpad_drv_data->ti2c_client;
176 struct input_dev *itpad_dev = itpad_drv_data->qcitp_dev;
177
178 qcitp_fetch_data(itpad_client, itpad_drv_data->ecdata);
179 qcitp_report_key(itpad_dev, itpad_drv_data->ecdata);
180 }
181
182 static irqreturn_t qcitp_interrupt(int irq, void *dev_id)
183 {
184 struct i2ctpad_drv_data *itpad_drv_data = dev_id;
185 schedule_work(&itpad_drv_data->work);
186 return IRQ_HANDLED;
187 }
188
189 static int __devinit qcitp_probe(struct i2c_client *client,
190 const struct i2c_device_id *id)
191 {
192 int err = -ENOMEM;
193 struct i2ctpad_drv_data *context = 0;
194
195 context = kzalloc(sizeof(struct i2ctpad_drv_data), GFP_KERNEL);
196 if (!context)
197 return err;
198 i2c_set_clientdata(client, context);
199 context->ti2c_client = client;
200 context->qcitp_gpio = client->irq;
201
202 /* Enable mouse */
203 i2c_smbus_write_byte(client, TOUCHPAD_CMD_ENABLE);
204 mdelay(100);
205 i2c_smbus_read_byte(client);
206 /*allocate and register input device*/
207 context->qcitp_dev = input_allocate_device();
208 if (!context->qcitp_dev) {
209 pr_err("[TouchPad] allocting memory fail\n");
210 err = -ENOMEM;
211 goto allocate_fail;
212 }
213 context->qcitp_dev->name = TOUCHPAD_NAME;
214 context->qcitp_dev->phys = TOUCHPAD_DEVICE;
215 context->qcitp_dev->id.bustype = BUS_I2C;
216 context->qcitp_dev->id.vendor = 0x1050;
217 context->qcitp_dev->id.product = 0x1;
218 context->qcitp_dev->id.version = 0x1;
219 context->qcitp_dev->evbit[0] = BIT_MASK(EV_KEY) |
220 BIT_MASK(EV_REL);
221 context->qcitp_dev->relbit[0] = BIT_MASK(REL_X) |
222 BIT_MASK(REL_Y);
223 context->qcitp_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
224 BIT_MASK(BTN_MIDDLE) |
225 BIT_MASK(BTN_RIGHT);
226
227 input_set_drvdata(context->qcitp_dev, context);
228 err = input_register_device(context->qcitp_dev);
229 if (err) {
230 pr_err("[TouchPad] register device fail\n");
231 goto register_fail;
232 }
233
234 /*request intterrupt*/
Mandeep Singh Baines 2010/03/23 18:06:03 request interrupt
235 INIT_WORK(&context->work, qcitp_work_handler);
236
237 err = gpio_request(context->qcitp_gpio, "qci-pad");
238 if (err) {
239 pr_err("[TouchPad]err gpio request\n");
240 goto gpio_request_fail;
241 }
242
243 context->qcitp_irq = gpio_to_irq(context->qcitp_gpio);
244 err = request_irq(context->qcitp_irq,
245 qcitp_interrupt,
246 IRQF_TRIGGER_FALLING,
247 TOUCHPAD_ID_NAME,
248 context);
249 if (err) {
250 pr_err("[TouchPad] unable to get IRQ\n");
251 goto request_irq_fail;
252 }
253 /*create touchpad kobject*/
254 context->tp_kobj = kobject_create_and_add("touchpad", NULL);
255
256 err = sysfs_create_group(context->tp_kobj, &attr_group);
257 if (err)
258 pr_warning("[TouchPad] sysfs create fail\n");
259
260 tp_sense_val = 10;
261
262 return 0;
263
264 request_irq_fail:
265 gpio_free(context->qcitp_gpio);
266
267 gpio_request_fail:
268 input_unregister_device(context->qcitp_dev);
269
270 register_fail:
271 input_free_device(context->qcitp_dev);
272
273 allocate_fail:
274 i2c_set_clientdata(client, NULL);
275 kfree(context);
276 return err;
277 }
278
279 static int __devexit qcitp_remove(struct i2c_client *dev)
280 {
281 struct i2ctpad_drv_data *context = i2c_get_clientdata(dev);
282
283 free_irq(context->qcitp_irq, context);
284 gpio_free(context->qcitp_gpio);
285 input_free_device(context->qcitp_dev);
286 input_unregister_device(context->qcitp_dev);
287 kfree(context);
288
289 return 0;
290 }
291
292 static int __init qcitp_init(void)
293 {
294 return i2c_add_driver(&i2ctp_driver);
295 }
296
297
298 static void __exit qcitp_exit(void)
299 {
300 i2c_del_driver(&i2ctp_driver);
301 }
302
303 module_init(qcitp_init);
304 module_exit(qcitp_exit);
305
306 MODULE_AUTHOR("Quanta Computer Inc.");
307 MODULE_DESCRIPTION("Quanta Embedded Controller I2C Touch Pad Driver");
308 MODULE_LICENSE("GPL v2");
OLDNEW
« no previous file with comments | « drivers/input/mouse/Makefile ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698