1/*
2 * qt2160.c - Atmel AT42QT2160 Touch Sense Controller
3 *
4 * Copyright (C) 2009 Raphael Derosso Pereira <raphaelpereira@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/leds.h>
23#include <linux/module.h>
24#include <linux/slab.h>
25#include <linux/jiffies.h>
26#include <linux/i2c.h>
27#include <linux/irq.h>
28#include <linux/interrupt.h>
29#include <linux/input.h>
30
31#define QT2160_VALID_CHIPID 0x11
32
33#define QT2160_CMD_CHIPID 0
34#define QT2160_CMD_CODEVER 1
35#define QT2160_CMD_GSTAT 2
36#define QT2160_CMD_KEYS3 3
37#define QT2160_CMD_KEYS4 4
38#define QT2160_CMD_SLIDE 5
39#define QT2160_CMD_GPIOS 6
40#define QT2160_CMD_SUBVER 7
41#define QT2160_CMD_CALIBRATE 10
42#define QT2160_CMD_DRIVE_X 70
43#define QT2160_CMD_PWMEN_X 74
44#define QT2160_CMD_PWM_DUTY 76
45
46#define QT2160_NUM_LEDS_X 8
47
48#define QT2160_CYCLE_INTERVAL (2*HZ)
49
50static unsigned char qt2160_key2code[] = {
51 KEY_0, KEY_1, KEY_2, KEY_3,
52 KEY_4, KEY_5, KEY_6, KEY_7,
53 KEY_8, KEY_9, KEY_A, KEY_B,
54 KEY_C, KEY_D, KEY_E, KEY_F,
55};
56
57#ifdef CONFIG_LEDS_CLASS
58struct qt2160_led {
59 struct qt2160_data *qt2160;
60 struct led_classdev cdev;
61 char name[32];
62 int id;
63 enum led_brightness brightness;
64};
65#endif
66
67struct qt2160_data {
68 struct i2c_client *client;
69 struct input_dev *input;
70 struct delayed_work dwork;
71 unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)];
72 u16 key_matrix;
73#ifdef CONFIG_LEDS_CLASS
74 struct qt2160_led leds[QT2160_NUM_LEDS_X];
75#endif
76};
77
78static int qt2160_read(struct i2c_client *client, u8 reg);
79static int qt2160_write(struct i2c_client *client, u8 reg, u8 data);
80
81#ifdef CONFIG_LEDS_CLASS
82
83static int qt2160_led_set(struct led_classdev *cdev,
84 enum led_brightness value)
85{
86 struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
87 struct qt2160_data *qt2160 = led->qt2160;
88 struct i2c_client *client = qt2160->client;
89 u32 drive, pwmen;
90
91 if (value != led->brightness) {
92 drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
93 pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
94 if (value != LED_OFF) {
95 drive |= BIT(led->id);
96 pwmen |= BIT(led->id);
97
98 } else {
99 drive &= ~BIT(led->id);
100 pwmen &= ~BIT(led->id);
101 }
102 qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
103 qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
104
105 /*
106 * Changing this register will change the brightness
107 * of every LED in the qt2160. It's a HW limitation.
108 */
109 if (value != LED_OFF)
110 qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
111
112 led->brightness = value;
113 }
114
115 return 0;
116}
117
118#endif /* CONFIG_LEDS_CLASS */
119
120static int qt2160_read_block(struct i2c_client *client,
121 u8 inireg, u8 *buffer, unsigned int count)
122{
123 int error, idx = 0;
124
125 /*
126 * Can't use SMBus block data read. Check for I2C functionality to speed
127 * things up whenever possible. Otherwise we will be forced to read
128 * sequentially.
129 */
130 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
131
132 error = i2c_smbus_write_byte(client, inireg + idx);
133 if (error) {
134 dev_err(&client->dev,
135 "couldn't send request. Returned %d\n", error);
136 return error;
137 }
138
139 error = i2c_master_recv(client, buffer, count);
140 if (error != count) {
141 dev_err(&client->dev,
142 "couldn't read registers. Returned %d bytes\n", error);
143 return error;
144 }
145 } else {
146
147 while (count--) {
148 int data;
149
150 error = i2c_smbus_write_byte(client, inireg + idx);
151 if (error) {
152 dev_err(&client->dev,
153 "couldn't send request. Returned %d\n", error);
154 return error;
155 }
156
157 data = i2c_smbus_read_byte(client);
158 if (data < 0) {
159 dev_err(&client->dev,
160 "couldn't read register. Returned %d\n", data);
161 return data;
162 }
163
164 buffer[idx++] = data;
165 }
166 }
167
168 return 0;
169}
170
171static int qt2160_get_key_matrix(struct qt2160_data *qt2160)
172{
173 struct i2c_client *client = qt2160->client;
174 struct input_dev *input = qt2160->input;
175 u8 regs[6];
176 u16 old_matrix, new_matrix;
177 int ret, i, mask;
178
179 dev_dbg(&client->dev, "requesting keys...\n");
180
181 /*
182 * Read all registers from General Status Register
183 * to GPIOs register
184 */
185 ret = qt2160_read_block(client, QT2160_CMD_GSTAT, regs, 6);
186 if (ret) {
187 dev_err(&client->dev,
188 "could not perform chip read.\n");
189 return ret;
190 }
191
192 old_matrix = qt2160->key_matrix;
193 qt2160->key_matrix = new_matrix = (regs[2] << 8) | regs[1];
194
195 mask = 0x01;
196 for (i = 0; i < 16; ++i, mask <<= 1) {
197 int keyval = new_matrix & mask;
198
199 if ((old_matrix & mask) != keyval) {
200 input_report_key(input, qt2160->keycodes[i], keyval);
201 dev_dbg(&client->dev, "key %d %s\n",
202 i, keyval ? "pressed" : "released");
203 }
204 }
205
206 input_sync(input);
207
208 return 0;
209}
210
211static irqreturn_t qt2160_irq(int irq, void *_qt2160)
212{
213 struct qt2160_data *qt2160 = _qt2160;
214
215 mod_delayed_work(system_wq, &qt2160->dwork, 0);
216
217 return IRQ_HANDLED;
218}
219
220static void qt2160_schedule_read(struct qt2160_data *qt2160)
221{
222 schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL);
223}
224
225static void qt2160_worker(struct work_struct *work)
226{
227 struct qt2160_data *qt2160 =
228 container_of(work, struct qt2160_data, dwork.work);
229
230 dev_dbg(&qt2160->client->dev, "worker\n");
231
232 qt2160_get_key_matrix(qt2160);
233
234 /* Avoid device lock up by checking every so often */
235 qt2160_schedule_read(qt2160);
236}
237
238static int qt2160_read(struct i2c_client *client, u8 reg)
239{
240 int ret;
241
242 ret = i2c_smbus_write_byte(client, reg);
243 if (ret) {
244 dev_err(&client->dev,
245 "couldn't send request. Returned %d\n", ret);
246 return ret;
247 }
248
249 ret = i2c_smbus_read_byte(client);
250 if (ret < 0) {
251 dev_err(&client->dev,
252 "couldn't read register. Returned %d\n", ret);
253 return ret;
254 }
255
256 return ret;
257}
258
259static int qt2160_write(struct i2c_client *client, u8 reg, u8 data)
260{
261 int ret;
262
263 ret = i2c_smbus_write_byte_data(client, reg, data);
264 if (ret < 0)
265 dev_err(&client->dev,
266 "couldn't write data. Returned %d\n", ret);
267
268 return ret;
269}
270
271#ifdef CONFIG_LEDS_CLASS
272
273static int qt2160_register_leds(struct qt2160_data *qt2160)
274{
275 struct i2c_client *client = qt2160->client;
276 int ret;
277 int i;
278
279 for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
280 struct qt2160_led *led = &qt2160->leds[i];
281
282 snprintf(led->name, sizeof(led->name), "qt2160:x%d", i);
283 led->cdev.name = led->name;
284 led->cdev.brightness_set_blocking = qt2160_led_set;
285 led->cdev.brightness = LED_OFF;
286 led->id = i;
287 led->qt2160 = qt2160;
288
289 ret = led_classdev_register(&client->dev, &led->cdev);
290 if (ret < 0)
291 return ret;
292 }
293
294 /* Tur off LEDs */
295 qt2160_write(client, QT2160_CMD_DRIVE_X, 0);
296 qt2160_write(client, QT2160_CMD_PWMEN_X, 0);
297 qt2160_write(client, QT2160_CMD_PWM_DUTY, 0);
298
299 return 0;
300}
301
302static void qt2160_unregister_leds(struct qt2160_data *qt2160)
303{
304 int i;
305
306 for (i = 0; i < QT2160_NUM_LEDS_X; i++)
307 led_classdev_unregister(&qt2160->leds[i].cdev);
308}
309
310#else
311
312static inline int qt2160_register_leds(struct qt2160_data *qt2160)
313{
314 return 0;
315}
316
317static inline void qt2160_unregister_leds(struct qt2160_data *qt2160)
318{
319}
320
321#endif
322
323static bool qt2160_identify(struct i2c_client *client)
324{
325 int id, ver, rev;
326
327 /* Read Chid ID to check if chip is valid */
328 id = qt2160_read(client, QT2160_CMD_CHIPID);
329 if (id != QT2160_VALID_CHIPID) {
330 dev_err(&client->dev, "ID %d not supported\n", id);
331 return false;
332 }
333
334 /* Read chip firmware version */
335 ver = qt2160_read(client, QT2160_CMD_CODEVER);
336 if (ver < 0) {
337 dev_err(&client->dev, "could not get firmware version\n");
338 return false;
339 }
340
341 /* Read chip firmware revision */
342 rev = qt2160_read(client, QT2160_CMD_SUBVER);
343 if (rev < 0) {
344 dev_err(&client->dev, "could not get firmware revision\n");
345 return false;
346 }
347
348 dev_info(&client->dev, "AT42QT2160 firmware version %d.%d.%d\n",
349 ver >> 4, ver & 0xf, rev);
350
351 return true;
352}
353
354static int qt2160_probe(struct i2c_client *client,
355 const struct i2c_device_id *id)
356{
357 struct qt2160_data *qt2160;
358 struct input_dev *input;
359 int i;
360 int error;
361
362 /* Check functionality */
363 error = i2c_check_functionality(client->adapter,
364 I2C_FUNC_SMBUS_BYTE);
365 if (!error) {
366 dev_err(&client->dev, "%s adapter not supported\n",
367 dev_driver_string(&client->adapter->dev));
368 return -ENODEV;
369 }
370
371 if (!qt2160_identify(client))
372 return -ENODEV;
373
374 /* Chip is valid and active. Allocate structure */
375 qt2160 = kzalloc(sizeof(struct qt2160_data), GFP_KERNEL);
376 input = input_allocate_device();
377 if (!qt2160 || !input) {
378 dev_err(&client->dev, "insufficient memory\n");
379 error = -ENOMEM;
380 goto err_free_mem;
381 }
382
383 qt2160->client = client;
384 qt2160->input = input;
385 INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker);
386
387 input->name = "AT42QT2160 Touch Sense Keyboard";
388 input->id.bustype = BUS_I2C;
389
390 input->keycode = qt2160->keycodes;
391 input->keycodesize = sizeof(qt2160->keycodes[0]);
392 input->keycodemax = ARRAY_SIZE(qt2160_key2code);
393
394 __set_bit(EV_KEY, input->evbit);
395 __clear_bit(EV_REP, input->evbit);
396 for (i = 0; i < ARRAY_SIZE(qt2160_key2code); i++) {
397 qt2160->keycodes[i] = qt2160_key2code[i];
398 __set_bit(qt2160_key2code[i], input->keybit);
399 }
400 __clear_bit(KEY_RESERVED, input->keybit);
401
402 /* Calibrate device */
403 error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1);
404 if (error) {
405 dev_err(&client->dev, "failed to calibrate device\n");
406 goto err_free_mem;
407 }
408
409 if (client->irq) {
410 error = request_irq(client->irq, qt2160_irq,
411 IRQF_TRIGGER_FALLING, "qt2160", qt2160);
412 if (error) {
413 dev_err(&client->dev,
414 "failed to allocate irq %d\n", client->irq);
415 goto err_free_mem;
416 }
417 }
418
419 error = qt2160_register_leds(qt2160);
420 if (error) {
421 dev_err(&client->dev, "Failed to register leds\n");
422 goto err_free_irq;
423 }
424
425 error = input_register_device(qt2160->input);
426 if (error) {
427 dev_err(&client->dev,
428 "Failed to register input device\n");
429 goto err_unregister_leds;
430 }
431
432 i2c_set_clientdata(client, qt2160);
433 qt2160_schedule_read(qt2160);
434
435 return 0;
436
437err_unregister_leds:
438 qt2160_unregister_leds(qt2160);
439err_free_irq:
440 if (client->irq)
441 free_irq(client->irq, qt2160);
442err_free_mem:
443 input_free_device(input);
444 kfree(qt2160);
445 return error;
446}
447
448static int qt2160_remove(struct i2c_client *client)
449{
450 struct qt2160_data *qt2160 = i2c_get_clientdata(client);
451
452 qt2160_unregister_leds(qt2160);
453
454 /* Release IRQ so no queue will be scheduled */
455 if (client->irq)
456 free_irq(client->irq, qt2160);
457
458 cancel_delayed_work_sync(&qt2160->dwork);
459
460 input_unregister_device(qt2160->input);
461 kfree(qt2160);
462
463 return 0;
464}
465
466static const struct i2c_device_id qt2160_idtable[] = {
467 { "qt2160", 0, },
468 { }
469};
470
471MODULE_DEVICE_TABLE(i2c, qt2160_idtable);
472
473static struct i2c_driver qt2160_driver = {
474 .driver = {
475 .name = "qt2160",
476 },
477
478 .id_table = qt2160_idtable,
479 .probe = qt2160_probe,
480 .remove = qt2160_remove,
481};
482
483module_i2c_driver(qt2160_driver);
484
485MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>");
486MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor");
487MODULE_LICENSE("GPL");
488