blob: 3acbfc609b10267f075a856dca1b67894a31a038 [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
Chintan Pandya0d453192012-03-09 13:20:33 +05302 *
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
Shantanu Jain37a3b2e2012-10-10 13:13:20 +0530730static unsigned int kp_row_gpios_skud[] = {31, 32};
731static unsigned int kp_col_gpios_skud[] = {37};
732
733static const unsigned short keymap_skud[] = {
734 [KP_INDEX_SKU3(0, 0)] = KEY_VOLUMEUP,
735 [KP_INDEX_SKU3(0, 1)] = KEY_VOLUMEDOWN,
736};
737
738
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530739static struct gpio_event_matrix_info kp_matrix_info_sku3 = {
740 .info.func = gpio_event_matrix_func,
741 .keymap = keymap_sku3,
742 .output_gpios = kp_row_gpios_sku3,
743 .input_gpios = kp_col_gpios_sku3,
744 .noutputs = ARRAY_SIZE(kp_row_gpios_sku3),
745 .ninputs = ARRAY_SIZE(kp_col_gpios_sku3),
Steve Mucklef132c6c2012-06-06 18:30:57 -0700746 .settle_time.tv64 = 40 * NSEC_PER_USEC,
747 .poll_time.tv64 = 20 * NSEC_PER_MSEC,
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530748 .flags = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE |
749 GPIOKPF_PRINT_UNMAPPED_KEYS,
750};
751
752static struct gpio_event_info *kp_info_sku3[] = {
753 &kp_matrix_info_sku3.info,
754};
755static struct gpio_event_platform_data kp_pdata_sku3 = {
756 .name = "7x27a_kp",
757 .info = kp_info_sku3,
758 .info_count = ARRAY_SIZE(kp_info_sku3)
759};
760
761static struct platform_device kp_pdev_sku3 = {
762 .name = GPIO_EVENT_DEV_NAME,
763 .id = -1,
764 .dev = {
765 .platform_data = &kp_pdata_sku3,
766 },
767};
768
Mohan Pallaka6fbeb992012-04-18 15:37:28 +0530769static struct led_info ctp_backlight_info = {
770 .name = "button-backlight",
771 .flags = PM_MPP__I_SINK__LEVEL_40mA << 16 | PM_MPP_7,
772};
773
774static struct led_platform_data ctp_backlight_pdata = {
775 .leds = &ctp_backlight_info,
776 .num_leds = 1,
777};
778
779static struct platform_device pmic_mpp_leds_pdev = {
780 .name = "pmic-mpp-leds",
781 .id = -1,
782 .dev = {
783 .platform_data = &ctp_backlight_pdata,
784 },
785};
786
Mohan Pallaka0e9625d2012-05-29 13:52:49 +0530787static struct led_info tricolor_led_info[] = {
788 [0] = {
789 .name = "red",
790 .flags = LED_COLOR_RED,
791 },
792 [1] = {
793 .name = "green",
794 .flags = LED_COLOR_GREEN,
795 },
796};
797
798static struct led_platform_data tricolor_led_pdata = {
799 .leds = tricolor_led_info,
800 .num_leds = ARRAY_SIZE(tricolor_led_info),
801};
802
803static struct platform_device tricolor_leds_pdev = {
804 .name = "msm-tricolor-leds",
805 .id = -1,
806 .dev = {
807 .platform_data = &tricolor_led_pdata,
808 },
809};
810
Chintan Pandya0d453192012-03-09 13:20:33 +0530811void __init msm7627a_add_io_devices(void)
812{
813 /* touchscreen */
814 if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
815 atmel_ts_pdata.min_x = 0;
816 atmel_ts_pdata.max_x = 480;
817 atmel_ts_pdata.min_y = 0;
818 atmel_ts_pdata.max_y = 320;
819 }
820
821 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
822 atmel_ts_i2c_info,
823 ARRAY_SIZE(atmel_ts_i2c_info));
824 /* keypad */
825 platform_device_register(&kp_pdev);
826
827 /* headset */
828 platform_device_register(&hs_pdev);
829
830 /* LED: configure it as a pdm function */
831 if (gpio_tlmm_config(GPIO_CFG(LED_GPIO_PDM, 3,
832 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
833 GPIO_CFG_8MA), GPIO_CFG_ENABLE))
834 pr_err("%s: gpio_tlmm_config for %d failed\n",
835 __func__, LED_GPIO_PDM);
836 else
837 platform_device_register(&led_pdev);
838
839 /* Vibrator */
Aparna Mallavarapu9f000a72012-04-20 15:37:57 +0530840 if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
841 || machine_is_msm8625_ffa())
Chintan Pandya0d453192012-03-09 13:20:33 +0530842 msm_init_pmic_vibrator();
843}
844
845void __init qrd7627a_add_io_devices(void)
846{
847 int rc;
848
849 /* touchscreen */
850 if (machine_is_msm7627a_qrd1()) {
851 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
852 synaptic_i2c_clearpad3k,
853 ARRAY_SIZE(synaptic_i2c_clearpad3k));
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530854 } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
855 machine_is_msm8625_evt()) {
856 /* Use configuration data for EVT */
857 if (machine_is_msm8625_evt()) {
858 mxt_config_array[0].config = mxt_config_data_evt;
859 mxt_config_array[0].config_length =
860 ARRAY_SIZE(mxt_config_data_evt);
861 mxt_platform_data.panel_maxy = 875;
Mohan Pallaka98193f22012-09-24 14:48:33 +0530862 mxt_platform_data.need_calibration = true;
Mohan Pallaka8ea8f832012-05-10 18:33:24 +0530863 mxt_vkey_setup();
864 }
865
Chintan Pandya0d453192012-03-09 13:20:33 +0530866 rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_IRQ_GPIO, 0,
867 GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
868 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
869 if (rc) {
870 pr_err("%s: gpio_tlmm_config for %d failed\n",
871 __func__, MXT_TS_IRQ_GPIO);
872 }
873
874 rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_RESET_GPIO, 0,
875 GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
876 GPIO_CFG_8MA), GPIO_CFG_ENABLE);
877 if (rc) {
878 pr_err("%s: gpio_tlmm_config for %d failed\n",
879 __func__, MXT_TS_RESET_GPIO);
880 }
881
882 i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
883 mxt_device_info,
884 ARRAY_SIZE(mxt_device_info));
Shantanu Jainbeca47f2012-10-09 17:08:18 +0530885 } else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()
886 || machine_is_qrd_skud_prime()) {
Chintan Pandya0d453192012-03-09 13:20:33 +0530887 ft5x06_touchpad_setup();
888 }
889
Mohan Pallakaf8b6f572012-12-04 22:38:24 +0530890 /* headset and power key*/
891 /* ignore end key as this target doesn't need it */
892 hs_platform_data.ignore_end_key = true;
Chintan Pandya0d453192012-03-09 13:20:33 +0530893 platform_device_register(&hs_pdev);
894
895 /* vibrator */
896#ifdef CONFIG_MSM_RPC_VIBRATOR
897 msm_init_pmic_vibrator();
898#endif
899
900 /* keypad */
Shantanu Jain37a3b2e2012-10-10 13:13:20 +0530901
902 if (machine_is_qrd_skud_prime()) {
903 kp_matrix_info_sku3.keymap = keymap_skud;
904 kp_matrix_info_sku3.output_gpios = kp_row_gpios_skud;
905 kp_matrix_info_sku3.input_gpios = kp_col_gpios_skud;
906 kp_matrix_info_sku3.noutputs = ARRAY_SIZE(kp_row_gpios_skud);
907 kp_matrix_info_sku3.ninputs = ARRAY_SIZE(kp_col_gpios_skud);
908 }
909
Mohan Pallaka299edc92012-05-16 11:39:01 +0530910 if (machine_is_msm8625_evt())
911 kp_matrix_info_8625.keymap = keymap_8625_evt;
912
913 if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
914 machine_is_msm8625_evt())
Chintan Pandya0d453192012-03-09 13:20:33 +0530915 platform_device_register(&kp_pdev_8625);
Shantanu Jain37a3b2e2012-10-10 13:13:20 +0530916 else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()
917 || machine_is_qrd_skud_prime())
Mohan Pallaka719aaa92012-04-03 12:21:03 +0530918 platform_device_register(&kp_pdev_sku3);
Chintan Pandya0d453192012-03-09 13:20:33 +0530919
920 /* leds */
Mohan Pallaka0e9625d2012-05-29 13:52:49 +0530921 if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
922 machine_is_msm8625_evt()) {
Mohan Pallaka6fbeb992012-04-18 15:37:28 +0530923 platform_device_register(&pmic_mpp_leds_pdev);
Mohan Pallaka0e9625d2012-05-29 13:52:49 +0530924 platform_device_register(&tricolor_leds_pdev);
Chintan Pandya0d453192012-03-09 13:20:33 +0530925 }
926}