blob: 47e83817a3ae9f770531ef8025b70be8f681dd28 [file] [log] [blame]
Chintan Pandya0d453192012-03-09 13:20:33 +05301/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/platform_device.h>
15#include <linux/regulator/consumer.h>
16#include <linux/gpio_event.h>
17#include <linux/leds.h>
18#include <linux/i2c/atmel_mxt_ts.h>
19#include <linux/i2c.h>
20#include <linux/input/rmi_platformdata.h>
21#include <linux/input/rmi_i2c.h>
22#include <linux/delay.h>
23#include <linux/atmel_maxtouch.h>
24#include <linux/input/ft5x06_ts.h>
Mohan Pallaka0e9625d2012-05-29 13:52:49 +053025#include <linux/leds-msm-tricolor.h>
Chintan Pandya0d453192012-03-09 13:20:33 +053026#include <asm/gpio.h>
27#include <asm/mach-types.h>
28#include <mach/rpc_server_handset.h>
Mohan Pallaka6fbeb992012-04-18 15:37:28 +053029#include <mach/pmic.h>
Chintan Pandya0d453192012-03-09 13:20:33 +053030
31#include "devices.h"
32#include "board-msm7627a.h"
33#include "devices-msm7x2xa.h"
34
35#define ATMEL_TS_I2C_NAME "maXTouch"
36#define ATMEL_X_OFFSET 13
37#define ATMEL_Y_OFFSET 0
38
39#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C) || \
40defined(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C_MODULE)
41
42#ifndef CLEARPAD3000_ATTEN_GPIO
43#define CLEARPAD3000_ATTEN_GPIO (48)
44#endif
45
46#ifndef CLEARPAD3000_RESET_GPIO
47#define CLEARPAD3000_RESET_GPIO (26)
48#endif
49
50#define KP_INDEX(row, col) ((row)*ARRAY_SIZE(kp_col_gpios) + (col))
51
52static unsigned int kp_row_gpios[] = {31, 32, 33, 34, 35};
53static unsigned int kp_col_gpios[] = {36, 37, 38, 39, 40};
54
55static const unsigned short keymap[ARRAY_SIZE(kp_col_gpios) *
56 ARRAY_SIZE(kp_row_gpios)] = {
57 [KP_INDEX(0, 0)] = KEY_7,
58 [KP_INDEX(0, 1)] = KEY_DOWN,
59 [KP_INDEX(0, 2)] = KEY_UP,
60 [KP_INDEX(0, 3)] = KEY_RIGHT,
61 [KP_INDEX(0, 4)] = KEY_ENTER,
62
63 [KP_INDEX(1, 0)] = KEY_LEFT,
64 [KP_INDEX(1, 1)] = KEY_SEND,
65 [KP_INDEX(1, 2)] = KEY_1,
66 [KP_INDEX(1, 3)] = KEY_4,
67 [KP_INDEX(1, 4)] = KEY_CLEAR,
68
69 [KP_INDEX(2, 0)] = KEY_6,
70 [KP_INDEX(2, 1)] = KEY_5,
71 [KP_INDEX(2, 2)] = KEY_8,
72 [KP_INDEX(2, 3)] = KEY_3,
73 [KP_INDEX(2, 4)] = KEY_NUMERIC_STAR,
74
75 [KP_INDEX(3, 0)] = KEY_9,
76 [KP_INDEX(3, 1)] = KEY_NUMERIC_POUND,
77 [KP_INDEX(3, 2)] = KEY_0,
78 [KP_INDEX(3, 3)] = KEY_2,
79 [KP_INDEX(3, 4)] = KEY_SLEEP,
80
81 [KP_INDEX(4, 0)] = KEY_BACK,
82 [KP_INDEX(4, 1)] = KEY_HOME,
83 [KP_INDEX(4, 2)] = KEY_MENU,
84 [KP_INDEX(4, 3)] = KEY_VOLUMEUP,
85 [KP_INDEX(4, 4)] = KEY_VOLUMEDOWN,
86};
87
88/* SURF keypad platform device information */
89static struct gpio_event_matrix_info kp_matrix_info = {
90 .info.func = gpio_event_matrix_func,
91 .keymap = keymap,
92 .output_gpios = kp_row_gpios,
93 .input_gpios = kp_col_gpios,
94 .noutputs = ARRAY_SIZE(kp_row_gpios),
95 .ninputs = ARRAY_SIZE(kp_col_gpios),
Steve Mucklef132c6c2012-06-06 18:30:57 -070096 .settle_time.tv64 = 40 * NSEC_PER_USEC,
97 .poll_time.tv64 = 20 * NSEC_PER_MSEC,
Chintan Pandya0d453192012-03-09 13:20:33 +053098 .flags = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE |
99 GPIOKPF_PRINT_UNMAPPED_KEYS,
100};
101
102static struct gpio_event_info *kp_info[] = {
103 &kp_matrix_info.info
104};
105
106static struct gpio_event_platform_data kp_pdata = {
107 .name = "7x27a_kp",
108 .info = kp_info,
109 .info_count = ARRAY_SIZE(kp_info)
110};
111
112static struct platform_device kp_pdev = {
113 .name = GPIO_EVENT_DEV_NAME,
114 .id = -1,
115 .dev = {
116 .platform_data = &kp_pdata,
117 },
118};
119
120/* 8625 keypad device information */
121static unsigned int kp_row_gpios_8625[] = {31};
122static unsigned int kp_col_gpios_8625[] = {36, 37};
123
124static const unsigned short keymap_8625[] = {
125 KEY_VOLUMEUP,
126 KEY_VOLUMEDOWN,
127};
128
Mohan Pallaka299edc92012-05-16 11:39:01 +0530129static const unsigned short keymap_8625_evt[] = {
130 KEY_VOLUMEDOWN,
131 KEY_VOLUMEUP,
132};
133
Chintan Pandya0d453192012-03-09 13:20:33 +0530134static struct gpio_event_matrix_info kp_matrix_info_8625 = {
135 .info.func = gpio_event_matrix_func,
136 .keymap = keymap_8625,
137 .output_gpios = kp_row_gpios_8625,
138 .input_gpios = kp_col_gpios_8625,
139 .noutputs = ARRAY_SIZE(kp_row_gpios_8625),
140 .ninputs = ARRAY_SIZE(kp_col_gpios_8625),
Steve Mucklef132c6c2012-06-06 18:30:57 -0700141 .settle_time.tv64 = 40 * NSEC_PER_USEC,
142 .poll_time.tv64 = 20 * NSEC_PER_MSEC,
Chintan Pandya0d453192012-03-09 13:20:33 +0530143 .flags = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE |
144 GPIOKPF_PRINT_UNMAPPED_KEYS,
145};
146
147static struct gpio_event_info *kp_info_8625[] = {
148 &kp_matrix_info_8625.info,
149};
150
151static struct gpio_event_platform_data kp_pdata_8625 = {
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530152 .name = "7x27a_kp",
Chintan Pandya0d453192012-03-09 13:20:33 +0530153 .info = kp_info_8625,
154 .info_count = ARRAY_SIZE(kp_info_8625)
155};
156
157static struct platform_device kp_pdev_8625 = {
158 .name = GPIO_EVENT_DEV_NAME,
159 .id = -1,
160 .dev = {
161 .platform_data = &kp_pdata_8625,
162 },
163};
164
165#define LED_GPIO_PDM 96
Chintan Pandya0d453192012-03-09 13:20:33 +0530166
167#define MXT_TS_IRQ_GPIO 48
168#define MXT_TS_RESET_GPIO 26
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530169#define MAX_VKEY_LEN 100
170
171static ssize_t mxt_virtual_keys_register(struct kobject *kobj,
172 struct kobj_attribute *attr, char *buf)
173{
174 char *virtual_keys = __stringify(EV_KEY) ":" __stringify(KEY_MENU) \
175 ":60:840:120:80" ":" __stringify(EV_KEY) \
176 ":" __stringify(KEY_HOME) ":180:840:120:80" \
177 ":" __stringify(EV_KEY) ":" \
178 __stringify(KEY_BACK) ":300:840:120:80" \
179 ":" __stringify(EV_KEY) ":" \
180 __stringify(KEY_SEARCH) ":420:840:120:80" "\n";
181
182 return snprintf(buf, strnlen(virtual_keys, MAX_VKEY_LEN) + 1 , "%s",
183 virtual_keys);
184}
185
186static struct kobj_attribute mxt_virtual_keys_attr = {
187 .attr = {
188 .name = "virtualkeys.atmel_mxt_ts",
189 .mode = S_IRUGO,
190 },
191 .show = &mxt_virtual_keys_register,
192};
193
194static struct attribute *mxt_virtual_key_properties_attrs[] = {
195 &mxt_virtual_keys_attr.attr,
196 NULL,
197};
198
199static struct attribute_group mxt_virtual_key_properties_attr_group = {
200 .attrs = mxt_virtual_key_properties_attrs,
201};
202
203struct kobject *mxt_virtual_key_properties_kobj;
204
205static int mxt_vkey_setup(void)
206{
Steve Muckle6dff9572012-06-25 17:37:50 -0700207 int retval = 0;
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530208
209 mxt_virtual_key_properties_kobj =
210 kobject_create_and_add("board_properties", NULL);
211 if (mxt_virtual_key_properties_kobj)
212 retval = sysfs_create_group(mxt_virtual_key_properties_kobj,
213 &mxt_virtual_key_properties_attr_group);
214 if (!mxt_virtual_key_properties_kobj || retval)
215 pr_err("failed to create mxt board_properties\n");
216
217 return retval;
218}
Chintan Pandya0d453192012-03-09 13:20:33 +0530219
220static const u8 mxt_config_data[] = {
221 /* T6 Object */
222 0, 0, 0, 0, 0, 0,
223 /* T38 Object */
Mohan Pallaka33287122012-05-14 14:02:56 +0530224 16, 1, 0, 0, 0, 0, 0, 0,
Chintan Pandya0d453192012-03-09 13:20:33 +0530225 /* T7 Object */
226 32, 16, 50,
227 /* T8 Object */
228 30, 0, 20, 20, 0, 0, 20, 0, 50, 0,
229 /* T9 Object */
230 3, 0, 0, 18, 11, 0, 32, 75, 3, 3,
231 0, 1, 1, 0, 10, 10, 10, 10, 31, 3,
232 223, 1, 11, 11, 15, 15, 151, 43, 145, 80,
233 100, 15, 0, 0, 0,
234 /* T15 Object */
235 131, 0, 11, 11, 1, 1, 0, 45, 3, 0,
236 0,
237 /* T18 Object */
238 0, 0,
239 /* T19 Object */
240 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
241 0, 0, 0, 0, 0, 0,
242 /* T23 Object */
243 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
244 0, 0, 0, 0, 0,
245 /* T25 Object */
246 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
247 0, 0, 0, 0,
248 /* T40 Object */
249 0, 0, 0, 0, 0,
250 /* T42 Object */
251 0, 0, 0, 0, 0, 0, 0, 0,
252 /* T46 Object */
253 0, 2, 32, 48, 0, 0, 0, 0, 0,
254 /* T47 Object */
255 1, 20, 60, 5, 2, 50, 40, 0, 0, 40,
256 /* T48 Object */
257 1, 12, 80, 0, 0, 0, 0, 0, 0, 0,
258 0, 0, 0, 6, 6, 0, 0, 100, 4, 64,
259 10, 0, 20, 5, 0, 38, 0, 20, 0, 0,
260 0, 0, 0, 0, 16, 65, 3, 1, 1, 0,
261 10, 10, 10, 0, 0, 15, 15, 154, 58, 145,
262 80, 100, 15, 3,
263};
264
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530265static const u8 mxt_config_data_evt[] = {
266 /* T6 Object */
267 0, 0, 0, 0, 0, 0,
268 /* T38 Object */
269 20, 0, 0, 0, 0, 0, 0, 0,
270 /* T7 Object */
271 24, 12, 10,
272 /* T8 Object */
273 30, 0, 20, 20, 0, 0, 9, 45, 10, 192,
274 /* T9 Object */
275 3, 0, 0, 18, 11, 0, 16, 60, 3, 1,
276 0, 1, 1, 0, 10, 10, 10, 10, 107, 3,
277 223, 1, 0, 0, 0, 0, 0, 0, 0, 0,
278 20, 15, 0, 0, 2,
279 /* T15 Object */
280 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
281 0,
282 /* T18 Object */
283 0, 0,
284 /* T19 Object */
285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
286 0, 0, 0, 0, 0, 0,
287 /* T23 Object */
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
289 0, 0, 0, 0, 0,
290 /* T25 Object */
291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
292 0, 0, 0, 0,
293 /* T40 Object */
294 17, 0, 0, 30, 30,
295 /* T42 Object */
296 3, 20, 45, 40, 128, 0, 0, 0,
297 /* T46 Object */
298 0, 2, 16, 16, 0, 0, 0, 0, 0,
299 /* T47 Object */
300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
301 /* T48 Object */
302 1, 128, 96, 0, 0, 0, 0, 0, 0, 0,
303 0, 0, 0, 6, 6, 0, 0, 63, 4, 64,
304 10, 0, 32, 5, 0, 38, 0, 8, 0, 0,
305 0, 0, 0, 0, 16, 65, 3, 1, 1, 0,
306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
307 0, 0, 0, 0,
308};
309
Chintan Pandya0d453192012-03-09 13:20:33 +0530310static struct mxt_config_info mxt_config_array[] = {
311 {
312 .config = mxt_config_data,
313 .config_length = ARRAY_SIZE(mxt_config_data),
314 .family_id = 0x81,
315 .variant_id = 0x01,
316 .version = 0x10,
317 .build = 0xAA,
318 },
319};
320
321static int mxt_key_codes[MXT_KEYARRAY_MAX_KEYS] = {
322 [0] = KEY_HOME,
323 [1] = KEY_MENU,
324 [9] = KEY_BACK,
325 [10] = KEY_SEARCH,
326};
327
328static struct mxt_platform_data mxt_platform_data = {
329 .config_array = mxt_config_array,
330 .config_array_size = ARRAY_SIZE(mxt_config_array),
331 .panel_minx = 0,
332 .panel_maxx = 479,
333 .panel_miny = 0,
334 .panel_maxy = 799,
335 .disp_minx = 0,
336 .disp_maxx = 479,
337 .disp_miny = 0,
338 .disp_maxy = 799,
339 .irqflags = IRQF_TRIGGER_FALLING,
340 .i2c_pull_up = true,
341 .reset_gpio = MXT_TS_RESET_GPIO,
342 .irq_gpio = MXT_TS_IRQ_GPIO,
343 .key_codes = mxt_key_codes,
344};
345
346static struct i2c_board_info mxt_device_info[] __initdata = {
347 {
348 I2C_BOARD_INFO("atmel_mxt_ts", 0x4a),
349 .platform_data = &mxt_platform_data,
350 .irq = MSM_GPIO_TO_INT(MXT_TS_IRQ_GPIO),
351 },
352};
353
354static int synaptics_touchpad_setup(void);
355
356static struct msm_gpio clearpad3000_cfg_data[] = {
357 {GPIO_CFG(CLEARPAD3000_ATTEN_GPIO, 0, GPIO_CFG_INPUT,
358 GPIO_CFG_NO_PULL, GPIO_CFG_6MA), "rmi4_attn"},
359 {GPIO_CFG(CLEARPAD3000_RESET_GPIO, 0, GPIO_CFG_OUTPUT,
360 GPIO_CFG_PULL_DOWN, GPIO_CFG_8MA), "rmi4_reset"},
361};
362
363static struct rmi_XY_pair rmi_offset = {.x = 0, .y = 0};
364static struct rmi_range rmi_clipx = {.min = 48, .max = 980};
365static struct rmi_range rmi_clipy = {.min = 7, .max = 1647};
366static struct rmi_f11_functiondata synaptics_f11_data = {
367 .swap_axes = false,
368 .flipX = false,
369 .flipY = false,
370 .offset = &rmi_offset,
371 .button_height = 113,
372 .clipX = &rmi_clipx,
373 .clipY = &rmi_clipy,
374};
375
376#define MAX_LEN 100
377
378static ssize_t clearpad3000_virtual_keys_register(struct kobject *kobj,
379 struct kobj_attribute *attr, char *buf)
380{
381 char *virtual_keys = __stringify(EV_KEY) ":" __stringify(KEY_MENU) \
382 ":60:830:120:60" ":" __stringify(EV_KEY) \
383 ":" __stringify(KEY_HOME) ":180:830:120:60" \
384 ":" __stringify(EV_KEY) ":" \
385 __stringify(KEY_SEARCH) ":300:830:120:60" \
386 ":" __stringify(EV_KEY) ":" \
387 __stringify(KEY_BACK) ":420:830:120:60" "\n";
388
389 return snprintf(buf, strnlen(virtual_keys, MAX_LEN) + 1 , "%s",
390 virtual_keys);
391}
392
393static struct kobj_attribute clearpad3000_virtual_keys_attr = {
394 .attr = {
395 .name = "virtualkeys.sensor00fn11",
396 .mode = S_IRUGO,
397 },
398 .show = &clearpad3000_virtual_keys_register,
399};
400
401static struct attribute *virtual_key_properties_attrs[] = {
402 &clearpad3000_virtual_keys_attr.attr,
403 NULL
404};
405
406static struct attribute_group virtual_key_properties_attr_group = {
407 .attrs = virtual_key_properties_attrs,
408};
409
410struct kobject *virtual_key_properties_kobj;
411
412static struct rmi_functiondata synaptics_functiondata[] = {
413 {
414 .function_index = RMI_F11_INDEX,
415 .data = &synaptics_f11_data,
416 },
417};
418
419static struct rmi_functiondata_list synaptics_perfunctiondata = {
420 .count = ARRAY_SIZE(synaptics_functiondata),
421 .functiondata = synaptics_functiondata,
422};
423
424static struct rmi_sensordata synaptics_sensordata = {
425 .perfunctiondata = &synaptics_perfunctiondata,
426 .rmi_sensor_setup = synaptics_touchpad_setup,
427};
428
429static struct rmi_i2c_platformdata synaptics_platformdata = {
430 .i2c_address = 0x2c,
431 .irq_type = IORESOURCE_IRQ_LOWLEVEL,
432 .sensordata = &synaptics_sensordata,
433};
434
435static struct i2c_board_info synaptic_i2c_clearpad3k[] = {
436 {
437 I2C_BOARD_INFO("rmi4_ts", 0x2c),
438 .platform_data = &synaptics_platformdata,
439 },
440};
441
442static int synaptics_touchpad_setup(void)
443{
444 int retval = 0;
445
446 virtual_key_properties_kobj =
447 kobject_create_and_add("board_properties", NULL);
448 if (virtual_key_properties_kobj)
449 retval = sysfs_create_group(virtual_key_properties_kobj,
450 &virtual_key_properties_attr_group);
451 if (!virtual_key_properties_kobj || retval)
452 pr_err("failed to create ft5202 board_properties\n");
453
454 retval = msm_gpios_request_enable(clearpad3000_cfg_data,
455 sizeof(clearpad3000_cfg_data)/sizeof(struct msm_gpio));
456 if (retval) {
457 pr_err("%s:Failed to obtain touchpad GPIO %d. Code: %d.",
458 __func__, CLEARPAD3000_ATTEN_GPIO, retval);
459 retval = 0; /* ignore the err */
460 }
461 synaptics_platformdata.irq = gpio_to_irq(CLEARPAD3000_ATTEN_GPIO);
462
463 gpio_set_value(CLEARPAD3000_RESET_GPIO, 0);
464 usleep(10000);
465 gpio_set_value(CLEARPAD3000_RESET_GPIO, 1);
466 usleep(50000);
467
468 return retval;
469}
470#endif
471
472static struct regulator_bulk_data regs_atmel[] = {
Mohan Pallakaaf51bb12012-04-26 15:51:30 +0530473 { .supply = "ldo12", .min_uV = 2700000, .max_uV = 3300000 },
Chintan Pandya0d453192012-03-09 13:20:33 +0530474 { .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
475};
476
477#define ATMEL_TS_GPIO_IRQ 82
478
479static int atmel_ts_power_on(bool on)
480{
481 int rc = on ?
482 regulator_bulk_enable(ARRAY_SIZE(regs_atmel), regs_atmel) :
483 regulator_bulk_disable(ARRAY_SIZE(regs_atmel), regs_atmel);
484
485 if (rc)
486 pr_err("%s: could not %sable regulators: %d\n",
487 __func__, on ? "en" : "dis", rc);
488 else
489 msleep(50);
490
491 return rc;
492}
493
494static int atmel_ts_platform_init(struct i2c_client *client)
495{
496 int rc;
497 struct device *dev = &client->dev;
498
499 rc = regulator_bulk_get(dev, ARRAY_SIZE(regs_atmel), regs_atmel);
500 if (rc) {
501 dev_err(dev, "%s: could not get regulators: %d\n",
502 __func__, rc);
503 goto out;
504 }
505
506 rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_atmel), regs_atmel);
507 if (rc) {
508 dev_err(dev, "%s: could not set voltages: %d\n",
509 __func__, rc);
510 goto reg_free;
511 }
512
513 rc = gpio_tlmm_config(GPIO_CFG(ATMEL_TS_GPIO_IRQ, 0,
514 GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
515 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
516 if (rc) {
517 dev_err(dev, "%s: gpio_tlmm_config for %d failed\n",
518 __func__, ATMEL_TS_GPIO_IRQ);
519 goto reg_free;
520 }
521
522 /* configure touchscreen interrupt gpio */
523 rc = gpio_request(ATMEL_TS_GPIO_IRQ, "atmel_maxtouch_gpio");
524 if (rc) {
525 dev_err(dev, "%s: unable to request gpio %d\n",
526 __func__, ATMEL_TS_GPIO_IRQ);
527 goto ts_gpio_tlmm_unconfig;
528 }
529
530 rc = gpio_direction_input(ATMEL_TS_GPIO_IRQ);
531 if (rc < 0) {
532 dev_err(dev, "%s: unable to set the direction of gpio %d\n",
533 __func__, ATMEL_TS_GPIO_IRQ);
534 goto free_ts_gpio;
535 }
536 return 0;
537
538free_ts_gpio:
539 gpio_free(ATMEL_TS_GPIO_IRQ);
540ts_gpio_tlmm_unconfig:
541 gpio_tlmm_config(GPIO_CFG(ATMEL_TS_GPIO_IRQ, 0,
542 GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
543 GPIO_CFG_2MA), GPIO_CFG_DISABLE);
544reg_free:
545 regulator_bulk_free(ARRAY_SIZE(regs_atmel), regs_atmel);
546out:
547 return rc;
548}
549
550static int atmel_ts_platform_exit(struct i2c_client *client)
551{
552 gpio_free(ATMEL_TS_GPIO_IRQ);
553 gpio_tlmm_config(GPIO_CFG(ATMEL_TS_GPIO_IRQ, 0,
554 GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
555 GPIO_CFG_2MA), GPIO_CFG_DISABLE);
556 regulator_bulk_free(ARRAY_SIZE(regs_atmel), regs_atmel);
557 return 0;
558}
559
560static u8 atmel_ts_read_chg(void)
561{
562 return gpio_get_value(ATMEL_TS_GPIO_IRQ);
563}
564
565static u8 atmel_ts_valid_interrupt(void)
566{
567 return !atmel_ts_read_chg();
568}
569
570
571static struct maxtouch_platform_data atmel_ts_pdata = {
572 .numtouch = 4,
573 .init_platform_hw = atmel_ts_platform_init,
574 .exit_platform_hw = atmel_ts_platform_exit,
575 .power_on = atmel_ts_power_on,
576 .display_res_x = 480,
577 .display_res_y = 864,
578 .min_x = ATMEL_X_OFFSET,
579 .max_x = (505 - ATMEL_X_OFFSET),
580 .min_y = ATMEL_Y_OFFSET,
581 .max_y = (863 - ATMEL_Y_OFFSET),
582 .valid_interrupt = atmel_ts_valid_interrupt,
583 .read_chg = atmel_ts_read_chg,
584};
585
586static struct i2c_board_info atmel_ts_i2c_info[] __initdata = {
587 {
588 I2C_BOARD_INFO(ATMEL_TS_I2C_NAME, 0x4a),
589 .platform_data = &atmel_ts_pdata,
590 .irq = MSM_GPIO_TO_INT(ATMEL_TS_GPIO_IRQ),
591 },
592};
593
594static struct msm_handset_platform_data hs_platform_data = {
595 .hs_name = "7k_handset",
596 .pwr_key_delay_ms = 500, /* 0 will disable end key */
597};
598
599static struct platform_device hs_pdev = {
600 .name = "msm-handset",
601 .id = -1,
602 .dev = {
603 .platform_data = &hs_platform_data,
604 },
605};
606
607#define FT5X06_IRQ_GPIO 48
608#define FT5X06_RESET_GPIO 26
609
610static ssize_t
611ft5x06_virtual_keys_register(struct kobject *kobj,
612 struct kobj_attribute *attr,
613 char *buf)
614{
615 return snprintf(buf, 200,
616 __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":40:510:80:60"
617 ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":120:510:80:60"
618 ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":200:510:80:60"
619 ":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":280:510:80:60"
620 "\n");
621}
622
623static struct kobj_attribute ft5x06_virtual_keys_attr = {
624 .attr = {
625 .name = "virtualkeys.ft5x06_ts",
626 .mode = S_IRUGO,
627 },
628 .show = &ft5x06_virtual_keys_register,
629};
630
631static struct attribute *ft5x06_virtual_key_properties_attrs[] = {
632 &ft5x06_virtual_keys_attr.attr,
633 NULL,
634};
635
636static struct attribute_group ft5x06_virtual_key_properties_attr_group = {
637 .attrs = ft5x06_virtual_key_properties_attrs,
638};
639
640struct kobject *ft5x06_virtual_key_properties_kobj;
641
642static struct ft5x06_ts_platform_data ft5x06_platformdata = {
643 .x_max = 320,
644 .y_max = 480,
645 .reset_gpio = FT5X06_RESET_GPIO,
646 .irq_gpio = FT5X06_IRQ_GPIO,
647 .irqflags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
648};
649
650static struct i2c_board_info ft5x06_device_info[] __initdata = {
651 {
652 I2C_BOARD_INFO("ft5x06_ts", 0x38),
653 .platform_data = &ft5x06_platformdata,
654 .irq = MSM_GPIO_TO_INT(FT5X06_IRQ_GPIO),
655 },
656};
657
Stephen Boyd668d7652012-04-25 11:31:01 -0700658static void __init ft5x06_touchpad_setup(void)
Chintan Pandya0d453192012-03-09 13:20:33 +0530659{
660 int rc;
661
662 rc = gpio_tlmm_config(GPIO_CFG(FT5X06_IRQ_GPIO, 0,
663 GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
664 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
665 if (rc)
666 pr_err("%s: gpio_tlmm_config for %d failed\n",
667 __func__, FT5X06_IRQ_GPIO);
668
669 rc = gpio_tlmm_config(GPIO_CFG(FT5X06_RESET_GPIO, 0,
670 GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
671 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
672 if (rc)
673 pr_err("%s: gpio_tlmm_config for %d failed\n",
674 __func__, FT5X06_RESET_GPIO);
675
676 ft5x06_virtual_key_properties_kobj =
677 kobject_create_and_add("board_properties", NULL);
678
679 if (ft5x06_virtual_key_properties_kobj)
680 rc = sysfs_create_group(ft5x06_virtual_key_properties_kobj,
681 &ft5x06_virtual_key_properties_attr_group);
682
683 if (!ft5x06_virtual_key_properties_kobj || rc)
684 pr_err("%s: failed to create board_properties\n", __func__);
685
686 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
687 ft5x06_device_info,
688 ARRAY_SIZE(ft5x06_device_info));
689}
690
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530691/* SKU3/SKU7 keypad device information */
692#define KP_INDEX_SKU3(row, col) ((row)*ARRAY_SIZE(kp_col_gpios_sku3) + (col))
693static unsigned int kp_row_gpios_sku3[] = {31, 32};
694static unsigned int kp_col_gpios_sku3[] = {36, 37};
695
696static const unsigned short keymap_sku3[] = {
697 [KP_INDEX_SKU3(0, 0)] = KEY_VOLUMEUP,
698 [KP_INDEX_SKU3(0, 1)] = KEY_VOLUMEDOWN,
699 [KP_INDEX_SKU3(1, 1)] = KEY_CAMERA,
700};
701
702static struct gpio_event_matrix_info kp_matrix_info_sku3 = {
703 .info.func = gpio_event_matrix_func,
704 .keymap = keymap_sku3,
705 .output_gpios = kp_row_gpios_sku3,
706 .input_gpios = kp_col_gpios_sku3,
707 .noutputs = ARRAY_SIZE(kp_row_gpios_sku3),
708 .ninputs = ARRAY_SIZE(kp_col_gpios_sku3),
Steve Mucklef132c6c2012-06-06 18:30:57 -0700709 .settle_time.tv64 = 40 * NSEC_PER_USEC,
710 .poll_time.tv64 = 20 * NSEC_PER_MSEC,
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530711 .flags = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE |
712 GPIOKPF_PRINT_UNMAPPED_KEYS,
713};
714
715static struct gpio_event_info *kp_info_sku3[] = {
716 &kp_matrix_info_sku3.info,
717};
718static struct gpio_event_platform_data kp_pdata_sku3 = {
719 .name = "7x27a_kp",
720 .info = kp_info_sku3,
721 .info_count = ARRAY_SIZE(kp_info_sku3)
722};
723
724static struct platform_device kp_pdev_sku3 = {
725 .name = GPIO_EVENT_DEV_NAME,
726 .id = -1,
727 .dev = {
728 .platform_data = &kp_pdata_sku3,
729 },
730};
731
Mohan Pallaka6fbeb992012-04-18 15:37:28 +0530732static struct led_info ctp_backlight_info = {
733 .name = "button-backlight",
734 .flags = PM_MPP__I_SINK__LEVEL_40mA << 16 | PM_MPP_7,
735};
736
737static struct led_platform_data ctp_backlight_pdata = {
738 .leds = &ctp_backlight_info,
739 .num_leds = 1,
740};
741
742static struct platform_device pmic_mpp_leds_pdev = {
743 .name = "pmic-mpp-leds",
744 .id = -1,
745 .dev = {
746 .platform_data = &ctp_backlight_pdata,
747 },
748};
749
Mohan Pallaka0e9625d2012-05-29 13:52:49 +0530750static struct led_info tricolor_led_info[] = {
751 [0] = {
752 .name = "red",
753 .flags = LED_COLOR_RED,
754 },
755 [1] = {
756 .name = "green",
757 .flags = LED_COLOR_GREEN,
758 },
759};
760
761static struct led_platform_data tricolor_led_pdata = {
762 .leds = tricolor_led_info,
763 .num_leds = ARRAY_SIZE(tricolor_led_info),
764};
765
766static struct platform_device tricolor_leds_pdev = {
767 .name = "msm-tricolor-leds",
768 .id = -1,
769 .dev = {
770 .platform_data = &tricolor_led_pdata,
771 },
772};
773
Chintan Pandya0d453192012-03-09 13:20:33 +0530774void __init msm7627a_add_io_devices(void)
775{
776 /* touchscreen */
777 if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
778 atmel_ts_pdata.min_x = 0;
779 atmel_ts_pdata.max_x = 480;
780 atmel_ts_pdata.min_y = 0;
781 atmel_ts_pdata.max_y = 320;
782 }
783
784 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
785 atmel_ts_i2c_info,
786 ARRAY_SIZE(atmel_ts_i2c_info));
787 /* keypad */
788 platform_device_register(&kp_pdev);
789
790 /* headset */
791 platform_device_register(&hs_pdev);
792
793 /* LED: configure it as a pdm function */
794 if (gpio_tlmm_config(GPIO_CFG(LED_GPIO_PDM, 3,
795 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
796 GPIO_CFG_8MA), GPIO_CFG_ENABLE))
797 pr_err("%s: gpio_tlmm_config for %d failed\n",
798 __func__, LED_GPIO_PDM);
799 else
800 platform_device_register(&led_pdev);
801
802 /* Vibrator */
Aparna Mallavarapu9f000a72012-04-20 15:37:57 +0530803 if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
804 || machine_is_msm8625_ffa())
Chintan Pandya0d453192012-03-09 13:20:33 +0530805 msm_init_pmic_vibrator();
806}
807
808void __init qrd7627a_add_io_devices(void)
809{
810 int rc;
811
812 /* touchscreen */
813 if (machine_is_msm7627a_qrd1()) {
814 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
815 synaptic_i2c_clearpad3k,
816 ARRAY_SIZE(synaptic_i2c_clearpad3k));
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530817 } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
818 machine_is_msm8625_evt()) {
819 /* Use configuration data for EVT */
820 if (machine_is_msm8625_evt()) {
821 mxt_config_array[0].config = mxt_config_data_evt;
822 mxt_config_array[0].config_length =
823 ARRAY_SIZE(mxt_config_data_evt);
824 mxt_platform_data.panel_maxy = 875;
825 mxt_vkey_setup();
826 }
827
Chintan Pandya0d453192012-03-09 13:20:33 +0530828 rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_IRQ_GPIO, 0,
829 GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
830 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
831 if (rc) {
832 pr_err("%s: gpio_tlmm_config for %d failed\n",
833 __func__, MXT_TS_IRQ_GPIO);
834 }
835
836 rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_RESET_GPIO, 0,
837 GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
838 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
839 if (rc) {
840 pr_err("%s: gpio_tlmm_config for %d failed\n",
841 __func__, MXT_TS_RESET_GPIO);
842 }
843
844 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
845 mxt_device_info,
846 ARRAY_SIZE(mxt_device_info));
Mohan Pallaka4e5964b2012-04-03 12:22:19 +0530847 } else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
Chintan Pandya0d453192012-03-09 13:20:33 +0530848 ft5x06_touchpad_setup();
849 }
850
851 /* headset */
852 platform_device_register(&hs_pdev);
853
854 /* vibrator */
855#ifdef CONFIG_MSM_RPC_VIBRATOR
856 msm_init_pmic_vibrator();
857#endif
858
859 /* keypad */
Mohan Pallaka299edc92012-05-16 11:39:01 +0530860 if (machine_is_msm8625_evt())
861 kp_matrix_info_8625.keymap = keymap_8625_evt;
862
863 if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
864 machine_is_msm8625_evt())
Chintan Pandya0d453192012-03-09 13:20:33 +0530865 platform_device_register(&kp_pdev_8625);
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530866 else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())
867 platform_device_register(&kp_pdev_sku3);
Chintan Pandya0d453192012-03-09 13:20:33 +0530868
869 /* leds */
Mohan Pallaka0e9625d2012-05-29 13:52:49 +0530870 if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
871 machine_is_msm8625_evt()) {
Mohan Pallaka6fbeb992012-04-18 15:37:28 +0530872 platform_device_register(&pmic_mpp_leds_pdev);
Mohan Pallaka0e9625d2012-05-29 13:52:49 +0530873 platform_device_register(&tricolor_leds_pdev);
Chintan Pandya0d453192012-03-09 13:20:33 +0530874 }
875}