2 * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * You should have received a copy of the GNU General Public License along
9 * with this program; if not, write to the Free Software Foundation, Inc.,
10 * 675 Mass Ave, Cambridge, MA 02139, USA.
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/i2c.h>
17 #include <linux/input.h>
18 #include <linux/irq.h>
19 #include <linux/interrupt.h>
21 #include <linux/workqueue.h>
23 #include <asm/mach-jz4740/irq.h>
24 #include <asm/mach-jz4740/gpio.h>
27 struct i2c_client *client;
28 struct input_dev *input;
30 struct work_struct work;
33 static const unsigned int n526_lpc_keymap[] = {
35 [0x02] = KEY_PAGEDOWN,
36 [0x03] = KEY_VOLUMEUP,
37 [0x04] = KEY_VOLUMEDOWN,
42 [0x0a] = KEY_LEFTSHIFT,
52 [0x14] = KEY_DOCUMENTS,
72 /* [0x28] = KEY_SYM, */
85 [0x35] = KEY_BACKSPACE,
90 static void n526_lpc_irq_work(struct work_struct *work)
93 struct n526_lpc *n526_lpc = container_of(work, struct n526_lpc, work);
94 struct i2c_client *client = n526_lpc->client;
95 unsigned char raw_msg;
96 struct i2c_msg msg = {client->addr, client->flags | I2C_M_RD, 1, &raw_msg};
97 unsigned char keycode;
100 ret = i2c_transfer(client->adapter, &msg, 1);
103 dev_err(&client->dev, "Failed to read lpc status\n");
106 keycode = raw_msg & 0x7f;
108 if (keycode < ARRAY_SIZE(n526_lpc_keymap)) {
109 input_report_key(n526_lpc->input, n526_lpc_keymap[keycode],
111 input_sync(n526_lpc->input);
115 static irqreturn_t n526_lpc_irq(int irq, void *dev_id)
117 struct n526_lpc *n526_lpc = dev_id;
119 schedule_work(&n526_lpc->work);
123 static int __devinit n526_lpc_probe(struct i2c_client *client,
124 const struct i2c_device_id *id)
128 struct n526_lpc *n526_lpc;
129 struct input_dev *input;
131 n526_lpc = kmalloc(sizeof(*n526_lpc), GFP_KERNEL);
134 dev_err(&client->dev, "Failed to allocate device structure\n");
138 input = input_allocate_device();
140 dev_err(&client->dev, "Failed to allocate input device\n");
145 input->name = "n526-keys";
146 input->phys = "n526-keys/input0";
147 input->dev.parent = &client->dev;
148 input->id.bustype = BUS_I2C;
149 input->id.vendor = 0x0001;
150 input->id.product = 0x0001;
151 input->id.version = 0x0001;
153 __set_bit(EV_KEY, input->evbit);
155 for (i = 0; i < ARRAY_SIZE(n526_lpc_keymap); ++i) {
156 if (n526_lpc_keymap[i] != 0)
157 __set_bit(n526_lpc_keymap[i], input->keybit);
160 ret = input_register_device(input);
163 dev_err(&client->dev, "Failed to register input device: %d\n", ret);
167 n526_lpc->client = client;
168 n526_lpc->input = input;
169 INIT_WORK(&n526_lpc->work, n526_lpc_irq_work);
171 ret = request_irq(client->irq, n526_lpc_irq, IRQF_TRIGGER_FALLING,
172 "n526-lpc", n526_lpc);
174 dev_err(&client->dev, "Failed to request irq: %d\n", ret);
175 goto err_unregister_input;
178 i2c_set_clientdata(client, n526_lpc);
182 err_unregister_input:
183 input_unregister_device(input);
185 input_free_device(input);
192 static int n526_lpc_remove(struct i2c_client *client)
194 struct n526_lpc *n526_lpc = i2c_get_clientdata(client);
196 free_irq(client->irq, n526_lpc);
198 i2c_set_clientdata(client, NULL);
199 input_unregister_device(n526_lpc->input);
200 input_free_device(n526_lpc->input);
206 static const struct i2c_device_id n526_lpc_id[] = {
210 MODULE_DEVICE_TABLE(i2c, n526_lpc_id);
212 static struct i2c_driver n526_lpc_driver = {
215 .owner = THIS_MODULE,
217 .probe = n526_lpc_probe,
218 .remove = n526_lpc_remove,
219 .id_table = n526_lpc_id,
222 static int __init n526_lpc_init(void)
224 return i2c_add_driver(&n526_lpc_driver);
226 module_init(n526_lpc_init);
228 static void __exit n526_lpc_exit(void)
230 i2c_del_driver(&n526_lpc_driver);
232 module_exit(n526_lpc_exit);
234 MODULE_LICENSE("GPL");
235 MODULE_AUTHOR("Lars-Peter Clausen");
236 MODULE_DESCRIPTION("n526 keypad driver");
237 MODULE_ALIAS("i2c:n526-keys");