blob: 2983dc0ccad85ea0e8cf4c018354684c5ddc760e [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 */
Mohan Pallaka98193f22012-09-24 14:48:33 +0530269 20, 1, 0, 25, 9, 12, 0, 0,
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530270 /* T7 Object */
271 24, 12, 10,
272 /* T8 Object */
Mohan Pallaka98193f22012-09-24 14:48:33 +0530273 30, 0, 20, 20, 0, 0, 0, 0, 10, 192,
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530274 /* T9 Object */
Mohan Pallaka98193f22012-09-24 14:48:33 +0530275 131, 0, 0, 18, 11, 0, 16, 70, 2, 1,
276 0, 2, 1, 62, 10, 10, 10, 10, 107, 3,
277 223, 1, 2, 2, 20, 20, 172, 40, 139, 110,
278 10, 15, 0, 0, 0,
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530279 /* 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 */
Mohan Pallaka98193f22012-09-24 14:48:33 +0530294 0, 0, 0, 0, 0,
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530295 /* 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 */
Mohan Pallaka98193f22012-09-24 14:48:33 +0530302 1, 12, 64, 0, 0, 0, 0, 0, 0, 0,
303 0, 0, 0, 6, 6, 0, 0, 100, 4, 64,
304 10, 0, 20, 5, 0, 38, 0, 20, 0, 0,
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530305 0, 0, 0, 0, 16, 65, 3, 1, 1, 0,
Mohan Pallaka98193f22012-09-24 14:48:33 +0530306 10, 10, 10, 0, 0, 15, 15, 154, 58, 145,
307 80, 100, 15, 3,
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530308};
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
Shantanu Jainbeca47f2012-10-09 17:08:18 +0530610#define FT5X16_IRQ_GPIO 122
611
Chintan Pandya0d453192012-03-09 13:20:33 +0530612static ssize_t
613ft5x06_virtual_keys_register(struct kobject *kobj,
614 struct kobj_attribute *attr,
615 char *buf)
616{
617 return snprintf(buf, 200,
618 __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":40:510:80:60"
619 ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":120:510:80:60"
620 ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":200:510:80:60"
621 ":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":280:510:80:60"
622 "\n");
623}
624
Shantanu Jainbeca47f2012-10-09 17:08:18 +0530625static ssize_t ft5x16_virtual_keys_register(struct kobject *kobj,
626 struct kobj_attribute *attr, char *buf)
627{
628 return snprintf(buf, 200, \
629 __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":68:984:135:50" \
630 ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":203:984:135:50" \
631 ":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":338:984:135:50" \
632 ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":473:984:135:50" \
633 "\n");
634}
635
Chintan Pandya0d453192012-03-09 13:20:33 +0530636static struct kobj_attribute ft5x06_virtual_keys_attr = {
637 .attr = {
638 .name = "virtualkeys.ft5x06_ts",
639 .mode = S_IRUGO,
640 },
641 .show = &ft5x06_virtual_keys_register,
642};
643
644static struct attribute *ft5x06_virtual_key_properties_attrs[] = {
645 &ft5x06_virtual_keys_attr.attr,
646 NULL,
647};
648
649static struct attribute_group ft5x06_virtual_key_properties_attr_group = {
650 .attrs = ft5x06_virtual_key_properties_attrs,
651};
652
653struct kobject *ft5x06_virtual_key_properties_kobj;
654
655static struct ft5x06_ts_platform_data ft5x06_platformdata = {
656 .x_max = 320,
657 .y_max = 480,
658 .reset_gpio = FT5X06_RESET_GPIO,
659 .irq_gpio = FT5X06_IRQ_GPIO,
660 .irqflags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
661};
662
663static struct i2c_board_info ft5x06_device_info[] __initdata = {
664 {
665 I2C_BOARD_INFO("ft5x06_ts", 0x38),
666 .platform_data = &ft5x06_platformdata,
667 .irq = MSM_GPIO_TO_INT(FT5X06_IRQ_GPIO),
668 },
669};
670
Stephen Boyd668d7652012-04-25 11:31:01 -0700671static void __init ft5x06_touchpad_setup(void)
Chintan Pandya0d453192012-03-09 13:20:33 +0530672{
673 int rc;
Shantanu Jainbeca47f2012-10-09 17:08:18 +0530674 int irq_gpio;
Chintan Pandya0d453192012-03-09 13:20:33 +0530675
Shantanu Jainbeca47f2012-10-09 17:08:18 +0530676 if (machine_is_qrd_skud_prime()) {
677 irq_gpio = FT5X16_IRQ_GPIO;
678
679 ft5x06_platformdata.x_max = 540;
680 ft5x06_platformdata.y_max = 960;
681 ft5x06_platformdata.irq_gpio = FT5X16_IRQ_GPIO;
682
683 ft5x06_device_info[0].irq = MSM_GPIO_TO_INT(FT5X16_IRQ_GPIO);
684
685 ft5x06_virtual_keys_attr.show = &ft5x16_virtual_keys_register;
686 } else {
687 irq_gpio = FT5X06_IRQ_GPIO;
688 }
689
690 rc = gpio_tlmm_config(GPIO_CFG(irq_gpio, 0,
Chintan Pandya0d453192012-03-09 13:20:33 +0530691 GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
692 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
693 if (rc)
694 pr_err("%s: gpio_tlmm_config for %d failed\n",
Shantanu Jainbeca47f2012-10-09 17:08:18 +0530695 __func__, irq_gpio);
Chintan Pandya0d453192012-03-09 13:20:33 +0530696
697 rc = gpio_tlmm_config(GPIO_CFG(FT5X06_RESET_GPIO, 0,
698 GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
699 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
700 if (rc)
701 pr_err("%s: gpio_tlmm_config for %d failed\n",
702 __func__, FT5X06_RESET_GPIO);
703
704 ft5x06_virtual_key_properties_kobj =
705 kobject_create_and_add("board_properties", NULL);
706
707 if (ft5x06_virtual_key_properties_kobj)
708 rc = sysfs_create_group(ft5x06_virtual_key_properties_kobj,
709 &ft5x06_virtual_key_properties_attr_group);
710
711 if (!ft5x06_virtual_key_properties_kobj || rc)
712 pr_err("%s: failed to create board_properties\n", __func__);
713
714 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
715 ft5x06_device_info,
716 ARRAY_SIZE(ft5x06_device_info));
717}
718
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530719/* SKU3/SKU7 keypad device information */
720#define KP_INDEX_SKU3(row, col) ((row)*ARRAY_SIZE(kp_col_gpios_sku3) + (col))
721static unsigned int kp_row_gpios_sku3[] = {31, 32};
722static unsigned int kp_col_gpios_sku3[] = {36, 37};
723
724static const unsigned short keymap_sku3[] = {
725 [KP_INDEX_SKU3(0, 0)] = KEY_VOLUMEUP,
726 [KP_INDEX_SKU3(0, 1)] = KEY_VOLUMEDOWN,
727 [KP_INDEX_SKU3(1, 1)] = KEY_CAMERA,
728};
729
730static struct gpio_event_matrix_info kp_matrix_info_sku3 = {
731 .info.func = gpio_event_matrix_func,
732 .keymap = keymap_sku3,
733 .output_gpios = kp_row_gpios_sku3,
734 .input_gpios = kp_col_gpios_sku3,
735 .noutputs = ARRAY_SIZE(kp_row_gpios_sku3),
736 .ninputs = ARRAY_SIZE(kp_col_gpios_sku3),
Steve Mucklef132c6c2012-06-06 18:30:57 -0700737 .settle_time.tv64 = 40 * NSEC_PER_USEC,
738 .poll_time.tv64 = 20 * NSEC_PER_MSEC,
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530739 .flags = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE |
740 GPIOKPF_PRINT_UNMAPPED_KEYS,
741};
742
743static struct gpio_event_info *kp_info_sku3[] = {
744 &kp_matrix_info_sku3.info,
745};
746static struct gpio_event_platform_data kp_pdata_sku3 = {
747 .name = "7x27a_kp",
748 .info = kp_info_sku3,
749 .info_count = ARRAY_SIZE(kp_info_sku3)
750};
751
752static struct platform_device kp_pdev_sku3 = {
753 .name = GPIO_EVENT_DEV_NAME,
754 .id = -1,
755 .dev = {
756 .platform_data = &kp_pdata_sku3,
757 },
758};
759
Mohan Pallaka6fbeb992012-04-18 15:37:28 +0530760static struct led_info ctp_backlight_info = {
761 .name = "button-backlight",
762 .flags = PM_MPP__I_SINK__LEVEL_40mA << 16 | PM_MPP_7,
763};
764
765static struct led_platform_data ctp_backlight_pdata = {
766 .leds = &ctp_backlight_info,
767 .num_leds = 1,
768};
769
770static struct platform_device pmic_mpp_leds_pdev = {
771 .name = "pmic-mpp-leds",
772 .id = -1,
773 .dev = {
774 .platform_data = &ctp_backlight_pdata,
775 },
776};
777
Mohan Pallaka0e9625d2012-05-29 13:52:49 +0530778static struct led_info tricolor_led_info[] = {
779 [0] = {
780 .name = "red",
781 .flags = LED_COLOR_RED,
782 },
783 [1] = {
784 .name = "green",
785 .flags = LED_COLOR_GREEN,
786 },
787};
788
789static struct led_platform_data tricolor_led_pdata = {
790 .leds = tricolor_led_info,
791 .num_leds = ARRAY_SIZE(tricolor_led_info),
792};
793
794static struct platform_device tricolor_leds_pdev = {
795 .name = "msm-tricolor-leds",
796 .id = -1,
797 .dev = {
798 .platform_data = &tricolor_led_pdata,
799 },
800};
801
Chintan Pandya0d453192012-03-09 13:20:33 +0530802void __init msm7627a_add_io_devices(void)
803{
804 /* touchscreen */
805 if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
806 atmel_ts_pdata.min_x = 0;
807 atmel_ts_pdata.max_x = 480;
808 atmel_ts_pdata.min_y = 0;
809 atmel_ts_pdata.max_y = 320;
810 }
811
812 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
813 atmel_ts_i2c_info,
814 ARRAY_SIZE(atmel_ts_i2c_info));
815 /* keypad */
816 platform_device_register(&kp_pdev);
817
818 /* headset */
819 platform_device_register(&hs_pdev);
820
821 /* LED: configure it as a pdm function */
822 if (gpio_tlmm_config(GPIO_CFG(LED_GPIO_PDM, 3,
823 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
824 GPIO_CFG_8MA), GPIO_CFG_ENABLE))
825 pr_err("%s: gpio_tlmm_config for %d failed\n",
826 __func__, LED_GPIO_PDM);
827 else
828 platform_device_register(&led_pdev);
829
830 /* Vibrator */
Aparna Mallavarapu9f000a72012-04-20 15:37:57 +0530831 if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
832 || machine_is_msm8625_ffa())
Chintan Pandya0d453192012-03-09 13:20:33 +0530833 msm_init_pmic_vibrator();
834}
835
836void __init qrd7627a_add_io_devices(void)
837{
838 int rc;
839
840 /* touchscreen */
841 if (machine_is_msm7627a_qrd1()) {
842 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
843 synaptic_i2c_clearpad3k,
844 ARRAY_SIZE(synaptic_i2c_clearpad3k));
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530845 } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
846 machine_is_msm8625_evt()) {
847 /* Use configuration data for EVT */
848 if (machine_is_msm8625_evt()) {
849 mxt_config_array[0].config = mxt_config_data_evt;
850 mxt_config_array[0].config_length =
851 ARRAY_SIZE(mxt_config_data_evt);
852 mxt_platform_data.panel_maxy = 875;
Mohan Pallaka98193f22012-09-24 14:48:33 +0530853 mxt_platform_data.need_calibration = true;
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530854 mxt_vkey_setup();
855 }
856
Chintan Pandya0d453192012-03-09 13:20:33 +0530857 rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_IRQ_GPIO, 0,
858 GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
859 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
860 if (rc) {
861 pr_err("%s: gpio_tlmm_config for %d failed\n",
862 __func__, MXT_TS_IRQ_GPIO);
863 }
864
865 rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_RESET_GPIO, 0,
866 GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
867 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
868 if (rc) {
869 pr_err("%s: gpio_tlmm_config for %d failed\n",
870 __func__, MXT_TS_RESET_GPIO);
871 }
872
873 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
874 mxt_device_info,
875 ARRAY_SIZE(mxt_device_info));
Shantanu Jainbeca47f2012-10-09 17:08:18 +0530876 } else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()
877 || machine_is_qrd_skud_prime()) {
Chintan Pandya0d453192012-03-09 13:20:33 +0530878 ft5x06_touchpad_setup();
879 }
880
881 /* headset */
882 platform_device_register(&hs_pdev);
883
884 /* vibrator */
885#ifdef CONFIG_MSM_RPC_VIBRATOR
886 msm_init_pmic_vibrator();
887#endif
888
889 /* keypad */
Mohan Pallaka299edc92012-05-16 11:39:01 +0530890 if (machine_is_msm8625_evt())
891 kp_matrix_info_8625.keymap = keymap_8625_evt;
892
893 if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
894 machine_is_msm8625_evt())
Chintan Pandya0d453192012-03-09 13:20:33 +0530895 platform_device_register(&kp_pdev_8625);
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530896 else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())
897 platform_device_register(&kp_pdev_sku3);
Chintan Pandya0d453192012-03-09 13:20:33 +0530898
899 /* leds */
Mohan Pallaka0e9625d2012-05-29 13:52:49 +0530900 if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
901 machine_is_msm8625_evt()) {
Mohan Pallaka6fbeb992012-04-18 15:37:28 +0530902 platform_device_register(&pmic_mpp_leds_pdev);
Mohan Pallaka0e9625d2012-05-29 13:52:49 +0530903 platform_device_register(&tricolor_leds_pdev);
Chintan Pandya0d453192012-03-09 13:20:33 +0530904 }
905}