/* * Copyright (C) 2012 Samsung Electronics, Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/platform_device.h> #include <linux/errno.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/keyreset.h> #include <linux/gpio_event.h> #include <linux/gpio.h> #include <linux/i2c.h> #include <linux/platform_data/cypress_cyttsp4.h> #include <linux/platform_data/sec_ts.h> #include <linux/delay.h> #include <linux/regulator/consumer.h> #include <asm/mach-types.h> #include <plat/omap4-keypad.h> #include "board-gokey.h" #include "mux.h" #include "omap_muxtbl.h" #include "control.h" #include "sec_debug.h" #define CY_I2C_TCH_ADR 0x24 #define CY_I2C_LDR_ADR 0x24 enum { GPIO_EXT_WAKEUP = 0, }; static struct gpio keys_map_high_gpios[] __initdata = { [GPIO_EXT_WAKEUP] = { .label = "EXT_WAKEUP", }, }; enum { GPIO_VOL_UP = 0, GPIO_VOL_DOWN, GPIO_HOME_KEY, }; static struct gpio keys_map_low_gpios[] __initdata = { [GPIO_VOL_UP] = { .label = "VOL_UP", }, [GPIO_VOL_DOWN] = { .label = "VOL_DN", }, [GPIO_HOME_KEY] = { .label = "HOME_KEY", }, }; static struct gpio_event_direct_entry gokey_gpio_keypad_keys_map_high[] = { { .code = KEY_POWER, }, }; static struct gpio_event_input_info gokey_gpio_keypad_keys_info_high = { .info.func = gpio_event_input_func, .info.no_suspend = true, .type = EV_KEY, .keymap = gokey_gpio_keypad_keys_map_high, .keymap_size = ARRAY_SIZE(gokey_gpio_keypad_keys_map_high), .debounce_time.tv64 = 2 * NSEC_PER_MSEC, }; static struct gpio_event_direct_entry gokey_gpio_keypad_keys_map_low[] = { [GPIO_VOL_DOWN] = { .code = KEY_VOLUMEDOWN, }, [GPIO_VOL_UP] = { .code = KEY_VOLUMEUP, }, [GPIO_HOME_KEY] = { .code = KEY_HOMEPAGE, }, }; static struct gpio_event_input_info gokey_gpio_keypad_keys_info_low = { .info.func = gpio_event_input_func, .info.no_suspend = true, .type = EV_KEY, .keymap = gokey_gpio_keypad_keys_map_low, .keymap_size = ARRAY_SIZE(gokey_gpio_keypad_keys_map_low), .debounce_time.tv64 = 2 * NSEC_PER_MSEC, }; static struct gpio_event_info *gokey_gpio_keypad_info[] = { &gokey_gpio_keypad_keys_info_high.info, &gokey_gpio_keypad_keys_info_low.info, }; static struct gpio_event_platform_data gokey_gpio_keypad_data = { .name = "sec_key", .info = gokey_gpio_keypad_info, .info_count = ARRAY_SIZE(gokey_gpio_keypad_info) }; static struct platform_device gokey_gpio_keypad_device = { .name = GPIO_EVENT_DEV_NAME, .id = 0, .dev = { .platform_data = &gokey_gpio_keypad_data, }, }; static struct gpio tsp_gpios[] = { [GPIO_TOUCH_nINT] = { .flags = GPIOF_IN, .label = "TSP_INT", }, [GPIO_TOUCH_EN] = { .flags = GPIOF_OUT_INIT_LOW, .label = "TOUCH_EN", }, [GPIO_TOUCH_SCL] = { .label = "TSP_I2C_SCL_1.8V", }, [GPIO_TOUCH_SDA] = { .label = "TSP_I2C_SDA_1.8V", }, }; static struct touch_key gokey_touch_keys[] = { { .name = "menu", .code = KEY_MENU, }, { .name = "back", .code = KEY_BACK, }, }; static int cyttsp4_hw_reset(void) { int retval = 0; pr_info("%s: strobe RST(%d) pin\n", __func__, tsp_gpios[GPIO_TOUCH_EN].gpio); gpio_set_value(tsp_gpios[GPIO_TOUCH_EN].gpio, 1); msleep(20); gpio_set_value(tsp_gpios[GPIO_TOUCH_EN].gpio, 0); msleep(40); gpio_set_value(tsp_gpios[GPIO_TOUCH_EN].gpio, 1); msleep(20); return retval; } static void tsp_set_power_gpio(bool on) { if (on) { pr_info("%s: TSP LDO enable(%d)\n", __func__, tsp_gpios[GPIO_TOUCH_EN].gpio); gpio_set_value(tsp_gpios[GPIO_TOUCH_EN].gpio, 1); msleep(20); } else { pr_info("%s: TSP LDO disable(%d)\n", __func__, tsp_gpios[GPIO_TOUCH_EN].gpio); gpio_set_value(tsp_gpios[GPIO_TOUCH_EN].gpio, 0); msleep(40); } } static int key_led_power(bool on) { struct regulator *vreg_led; vreg_led = regulator_get(NULL, "KEYLED_3P3V"); if (IS_ERR(vreg_led)) { pr_err("tsp: Fail to register vreg_led(KEYLED_3P3V) in touch driver\n"); return PTR_ERR(vreg_led); } if (on) { if (!regulator_is_enabled(vreg_led)) regulator_enable(vreg_led); } else { if (regulator_is_enabled(vreg_led)) regulator_disable(vreg_led); } regulator_put(vreg_led); return 0; } #define CY_WAKE_DFLT 99 /* causes wake strobe on INT line * in sample board configuration * platform data->hw_recov() function */ static int cyttsp4_hw_recov(int on) { int retval = 0; switch (on) { case 0: cyttsp4_hw_reset(); retval = 0; break; case CY_WAKE_DFLT: retval = gpio_direction_output (tsp_gpios[GPIO_TOUCH_nINT].gpio, 0); if (retval < 0) { pr_err("%s: Fail switch IRQ pin to OUT r=%d\n", __func__, retval); } else { udelay(2000); retval = gpio_direction_input (tsp_gpios[GPIO_TOUCH_nINT].gpio); if (retval < 0) { pr_err("%s: Fail switch IRQ pin to IN" " r=%d\n", __func__, retval); } } break; default: retval = -ENOSYS; break; } return retval; }
static int cyttsp4_hw_recov(int on) { int retval = 0; pr_info("%s: on=%d\n", __func__, on); if (on == 0) { cyttsp4_hw_reset(); retval = 0; } else retval = -EINVAL; #if 0 // KEVKEV else {