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