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