blob: ef93a7ea8727560a32949f9de9daa298d274efdc [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* 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#define TOUCHPAD_INIT_DELAY_MS 100
43
44static int __devinit qcitp_probe(struct i2c_client *client,
45 const struct i2c_device_id *id);
46static int __devexit qcitp_remove(struct i2c_client *kbd);
47
48/* General structure to hold the driver data */
49struct i2ctpad_drv_data {
50 struct i2c_client *ti2c_client;
51 struct work_struct work;
52 struct input_dev *qcitp_dev;
53 struct kobject *tp_kobj;
54 unsigned int qcitp_gpio;
55 unsigned int qcitp_irq;
56 char ecdata[8];
57};
58
59static int tp_sense_val = 10;
60static ssize_t tp_sensitive_show(struct kobject *kobj,
61 struct kobj_attribute *attr, char * buf)
62{
63 return sprintf(buf, "%d\n", tp_sense_val);
64}
65
66static ssize_t tp_sensitive_store(struct kobject *kobj,
67 struct kobj_attribute *attr, const char* buf, size_t n)
68{
69 unsigned int val = 0;
70 sscanf(buf, "%d", &val);
71
72 if (val >= 1 && val <= 10)
73 tp_sense_val = val;
74 else
75 return -ENOSYS;
76
77 return sizeof(buf);
78}
79
80static struct kobj_attribute tp_sensitivity = __ATTR(tp_sensitivity ,
81 0644 ,
82 tp_sensitive_show ,
83 tp_sensitive_store);
84
85static struct attribute *g_tp[] = {
86 &tp_sensitivity.attr,
87 NULL,
88};
89
90static struct attribute_group attr_group = {
91 .attrs = g_tp,
92};
93
94/*-----------------------------------------------------------------------------
95 * Driver functions
96 *---------------------------------------------------------------------------*/
97
98#ifdef CONFIG_PM
99static int qcitp_suspend(struct device *dev)
100{
101 return 0;
102}
103
104static int qcitp_resume(struct device *dev)
105{
106 return 0;
107}
108#endif
109
110static const struct i2c_device_id qcitp_idtable[] = {
111 { TOUCHPAD_ID_NAME, 0 },
112 { }
113};
114
115MODULE_DEVICE_TABLE(i2c, qcitp_idtable);
116#ifdef CONFIG_PM
117static const struct dev_pm_ops qcitp_pm_ops = {
118 .suspend = qcitp_suspend,
119 .resume = qcitp_resume,
120};
121#endif
122static struct i2c_driver i2ctp_driver = {
123 .driver = {
124 .owner = THIS_MODULE,
125 .name = TOUCHPAD_ID_NAME,
126#ifdef CONFIG_PM
127 .pm = &qcitp_pm_ops,
128#endif
129 },
130 .probe = qcitp_probe,
131 .remove = __devexit_p(qcitp_remove),
132 .id_table = qcitp_idtable,
133};
134
135static void qcitp_fetch_data(struct i2c_client *tpad_client,
136 char *ec_data)
137{
138 struct i2c_msg tp_msg;
139 int ret;
140 tp_msg.addr = tpad_client->addr;
141 tp_msg.flags = I2C_M_RD;
142 tp_msg.len = 3;
143 tp_msg.buf = (char *)&ec_data[0];
144 ret = i2c_transfer(tpad_client->adapter, &tp_msg, 1);
145}
146
147static void qcitp_report_key(struct input_dev *tpad_dev, char *ec_data)
148{
149 int dx = 0;
150 int dy = 0;
151
152 if (ec_data[1])
153 dx = (int) ec_data[1] -
154 (int) ((ec_data[0] << 4) & 0x100);
155
156 if (ec_data[2])
157 dy = (int) ((ec_data[0] << 3) & 0x100) -
158 (int) ec_data[2];
159
160 dx = (dx * tp_sense_val)/10;
161 dy = (dy * tp_sense_val)/10;
162
163 input_report_key(tpad_dev, BTN_LEFT, ec_data[0] & 0x01);
164 input_report_key(tpad_dev, BTN_RIGHT, ec_data[0] & 0x02);
165 input_report_key(tpad_dev, BTN_MIDDLE, ec_data[0] & 0x04);
166 input_report_rel(tpad_dev, REL_X, dx);
167 input_report_rel(tpad_dev, REL_Y, dy);
168 input_sync(tpad_dev);
169}
170
171static void qcitp_work_handler(struct work_struct *_work)
172{
173 struct i2ctpad_drv_data *itpad_drv_data =
174 container_of(_work, struct i2ctpad_drv_data, work);
175
176 struct i2c_client *itpad_client = itpad_drv_data->ti2c_client;
177 struct input_dev *itpad_dev = itpad_drv_data->qcitp_dev;
178
179 qcitp_fetch_data(itpad_client, itpad_drv_data->ecdata);
180 qcitp_report_key(itpad_dev, itpad_drv_data->ecdata);
181}
182
183static irqreturn_t qcitp_interrupt(int irq, void *dev_id)
184{
185 struct i2ctpad_drv_data *itpad_drv_data = dev_id;
186 schedule_work(&itpad_drv_data->work);
187 return IRQ_HANDLED;
188}
189
190static int __devinit qcitp_probe(struct i2c_client *client,
191 const struct i2c_device_id *id)
192{
193 int err = -ENOMEM;
194 struct i2ctpad_drv_data *context = 0;
195
196 context = kzalloc(sizeof(struct i2ctpad_drv_data), GFP_KERNEL);
197 if (!context)
198 return err;
199 i2c_set_clientdata(client, context);
200 context->ti2c_client = client;
201 context->qcitp_gpio = client->irq;
202
203 /* Enable mouse */
204 i2c_smbus_write_byte(client, TOUCHPAD_CMD_ENABLE);
205 msleep(TOUCHPAD_INIT_DELAY_MS);
206 i2c_smbus_read_byte(client);
207 /*allocate and register input device*/
208 context->qcitp_dev = input_allocate_device();
209 if (!context->qcitp_dev) {
210 pr_err("[TouchPad] allocting memory fail\n");
211 err = -ENOMEM;
212 goto allocate_fail;
213 }
214 context->qcitp_dev->name = TOUCHPAD_NAME;
215 context->qcitp_dev->phys = TOUCHPAD_DEVICE;
216 context->qcitp_dev->id.bustype = BUS_I2C;
217 context->qcitp_dev->id.vendor = 0x1050;
218 context->qcitp_dev->id.product = 0x1;
219 context->qcitp_dev->id.version = 0x1;
220 context->qcitp_dev->evbit[0] = BIT_MASK(EV_KEY) |
221 BIT_MASK(EV_REL);
222 context->qcitp_dev->relbit[0] = BIT_MASK(REL_X) |
223 BIT_MASK(REL_Y);
224 context->qcitp_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
225 BIT_MASK(BTN_MIDDLE) |
226 BIT_MASK(BTN_RIGHT);
227
228 input_set_drvdata(context->qcitp_dev, context);
229 err = input_register_device(context->qcitp_dev);
230 if (err) {
231 pr_err("[TouchPad] register device fail\n");
232 goto register_fail;
233 }
234
235 /*request intterrupt*/
236 INIT_WORK(&context->work, qcitp_work_handler);
237
238 err = gpio_request(context->qcitp_gpio, "qci-pad");
239 if (err) {
240 pr_err("[TouchPad]err gpio request\n");
241 goto gpio_request_fail;
242 }
243
244 context->qcitp_irq = gpio_to_irq(context->qcitp_gpio);
245 err = request_irq(context->qcitp_irq,
246 qcitp_interrupt,
247 IRQF_TRIGGER_FALLING,
248 TOUCHPAD_ID_NAME,
249 context);
250 if (err) {
251 pr_err("[TouchPad] unable to get IRQ\n");
252 goto request_irq_fail;
253 }
254 /*create touchpad kobject*/
255 context->tp_kobj = kobject_create_and_add("touchpad", NULL);
256
257 err = sysfs_create_group(context->tp_kobj, &attr_group);
258 if (err)
259 pr_warning("[TouchPad] sysfs create fail\n");
260
261 tp_sense_val = 10;
262
263 return 0;
264
265request_irq_fail:
266 gpio_free(context->qcitp_gpio);
267
268gpio_request_fail:
269 input_unregister_device(context->qcitp_dev);
270
271register_fail:
272 input_free_device(context->qcitp_dev);
273
274allocate_fail:
275 i2c_set_clientdata(client, NULL);
276 kfree(context);
277 return err;
278}
279
280static int __devexit qcitp_remove(struct i2c_client *dev)
281{
282 struct i2ctpad_drv_data *context = i2c_get_clientdata(dev);
283
284 free_irq(context->qcitp_irq, context);
285 gpio_free(context->qcitp_gpio);
286 input_free_device(context->qcitp_dev);
287 input_unregister_device(context->qcitp_dev);
288 kfree(context);
289
290 return 0;
291}
292
293static int __init qcitp_init(void)
294{
295 return i2c_add_driver(&i2ctp_driver);
296}
297
298
299static void __exit qcitp_exit(void)
300{
301 i2c_del_driver(&i2ctp_driver);
302}
303
304module_init(qcitp_init);
305module_exit(qcitp_exit);
306
307MODULE_AUTHOR("Quanta Computer Inc.");
308MODULE_DESCRIPTION("Quanta Embedded Controller I2C Touch Pad Driver");
309MODULE_LICENSE("GPL v2");