diff options
Diffstat (limited to 'arch/arm/mach-exynos/kona-input.c')
-rw-r--r-- | arch/arm/mach-exynos/kona-input.c | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/kona-input.c b/arch/arm/mach-exynos/kona-input.c new file mode 100644 index 0000000..72ffb16 --- /dev/null +++ b/arch/arm/mach-exynos/kona-input.c @@ -0,0 +1,430 @@ +/* + * arch/arm/mach-exynos/p4-input.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/i2c.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <plat/gpio-cfg.h> +#include <plat/iic.h> +#include <linux/regulator/consumer.h> + +static u32 hw_rev; + +#ifdef CONFIG_SENSORS_HALL +int ts_powered_on; +EXPORT(ts_powered_on); +#endif + +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301) +#include <linux/synaptics_s7301.h> +static bool have_tsp_ldo; +static struct charger_callbacks *charger_callbacks; + +void synaptics_ts_charger_infom(bool en) +{ + if (charger_callbacks && charger_callbacks->inform_charger) + charger_callbacks->inform_charger(charger_callbacks, en); +} + +static void synaptics_ts_register_callback(struct charger_callbacks *cb) +{ + charger_callbacks = cb; + printk(KERN_DEBUG "[TSP] %s\n", __func__); +} + +static int synaptics_ts_set_power(bool en) +{ + struct regulator *regulator; + + if (!have_tsp_ldo) + return -1; + printk(KERN_DEBUG "[TSP] %s(%d)\n", __func__, en); + + ts_powered_on = en; + + regulator = regulator_get(NULL, "tsp_3.3v"); + if (IS_ERR(regulator)) + return PTR_ERR(regulator); + + if (en) { + s3c_gpio_cfgpin(GPIO_TSP_SDA_18V, S3C_GPIO_SFN(0x3)); + s3c_gpio_setpull(GPIO_TSP_SDA_18V, S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(GPIO_TSP_SCL_18V, S3C_GPIO_SFN(0x3)); + s3c_gpio_setpull(GPIO_TSP_SCL_18V, S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(GPIO_TSP_LDO_ON, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_LDO_ON, S3C_GPIO_PULL_NONE); + + if (regulator_is_enabled(regulator)) { + printk(KERN_DEBUG "[TSP] regulator force disabled before enabling\n"); + regulator_force_disable(regulator); + msleep(100); + } + + regulator_enable(regulator); + gpio_set_value(GPIO_TSP_LDO_ON, 1); + + s3c_gpio_setpull(GPIO_TSP_INT, S3C_GPIO_PULL_NONE); + s3c_gpio_cfgpin(GPIO_TSP_INT, S3C_GPIO_SFN(0xf)); + } else { + s3c_gpio_cfgpin(GPIO_TSP_SDA_18V, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_SDA_18V, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_SDA_18V, 0); + s3c_gpio_cfgpin(GPIO_TSP_SCL_18V, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_SCL_18V, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_SCL_18V, 0); + s3c_gpio_cfgpin(GPIO_TSP_INT, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_INT, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_INT, 0); + s3c_gpio_cfgpin(GPIO_TSP_LDO_ON, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_LDO_ON, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_LDO_ON, 0); + + if (regulator_is_enabled(regulator)) + regulator_disable(regulator); + } + + regulator_put(regulator); + return 0; +} + +static void synaptics_ts_reset(void) +{ + printk(KERN_DEBUG "[TSP] %s\n", __func__); + synaptics_ts_set_power(false); + msleep(100); + synaptics_ts_set_power(true); + msleep(200); +} + +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED) +static void synaptics_ts_led_control(int on_off) +{ + printk(KERN_DEBUG "[TSP] %s [%d]\n", __func__, on_off); + + if (hw_rev < 1) + return ; + + if (on_off == 1) + gpio_direction_output(GPIO_TSP_2TOUCH_EN, 1); + else + gpio_direction_output(GPIO_TSP_2TOUCH_EN, 0); +} +#endif + +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) +static u8 synaptics_button_codes[] = {KEY_MENU, KEY_BACK}; +static u8 synaptics_extend_button_codes[] = + {KEY_DUMMY_1, KEY_MENU, KEY_DUMMY_2, KEY_BACK, KEY_DUMMY_3}; + +static struct synaptics_button_map synpatics_button_map = { + .nbuttons = ARRAY_SIZE(synaptics_button_codes), + .map = synaptics_button_codes, +}; + +static struct synaptics_extend_button_map synptics_extend_button_map = { + .nbuttons = ARRAY_SIZE(synaptics_extend_button_codes), + .map = synaptics_extend_button_codes, + .button_mask = BUTTON_0_MASK | BUTTON_2_MASK | BUTTON_4_MASK, +}; +#endif + +static struct synaptics_platform_data synaptics_ts_pdata = { + .gpio_attn = GPIO_TSP_INT, + .max_x = 799, + .max_y = 1279, + .max_pressure = 255, + .max_width = 100, + .x_line = 26, + .y_line = 41, + .swap_xy = false, + .invert_x = false, + .invert_y = false, +#if defined(CONFIG_SEC_TOUCHSCREEN_SURFACE_TOUCH) + .palm_threshold = 28, +#endif + .set_power = synaptics_ts_set_power, + .hw_reset = synaptics_ts_reset, + .register_cb = synaptics_ts_register_callback, +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED) + .led_control = synaptics_ts_led_control, + .led_event = false, +#endif +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + .button_map = &synpatics_button_map, + .extend_button_map = &synptics_extend_button_map, + .support_extend_button = false, + .enable_extend_button_event = false, +#endif +}; + +static struct i2c_board_info i2c_synaptics[] __initdata = { + { + I2C_BOARD_INFO(SYNAPTICS_TS_NAME, + SYNAPTICS_TS_ADDR), + .platform_data = &synaptics_ts_pdata, + }, +}; +#elif defined(CONFIG_RMI4_I2C) +#include <linux/interrupt.h> +#include <linux/rmi4.h> +#include <linux/input.h> + +#define TOUCH_ON 1 +#define TOUCH_OFF 0 + +#define RMI4_DEFAULT_ATTN_GPIO GPIO_TSP_INT +#define RMI4_DEFAULT_ATTN_NAME "TSP_INT" + +struct syna_gpio_data { + u16 gpio_number; + char *gpio_name; +}; + +static bool have_tsp_ldo; + +static struct syna_gpio_data rmi4_default_gpio_data = { + .gpio_number = RMI4_DEFAULT_ATTN_GPIO, + .gpio_name = RMI4_DEFAULT_ATTN_NAME, +}; + +#define SYNA_ADDR 0x20 + +static unsigned char SYNA_f1a_button_codes[] = {KEY_MENU, KEY_BACK}; + +static struct rmi_button_map SYNA_f1a_button_map = { + .nbuttons = ARRAY_SIZE(SYNA_f1a_button_codes), + .map = SYNA_f1a_button_codes, +}; + +static int SYNA_ts_power(bool on_off) +{ + struct regulator *regulator; + + if (!have_tsp_ldo) + return -1; + printk(KERN_DEBUG "[TSP] %s(%d)\n", __func__, on_off); + + regulator = regulator_get(NULL, "tsp_3.3v"); + if (IS_ERR(regulator)) + return PTR_ERR(regulator); + + if (on_off) { + s3c_gpio_cfgpin(GPIO_TSP_SDA_18V, S3C_GPIO_SFN(0x3)); + s3c_gpio_setpull(GPIO_TSP_SDA_18V, S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(GPIO_TSP_SCL_18V, S3C_GPIO_SFN(0x3)); + s3c_gpio_setpull(GPIO_TSP_SCL_18V, S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(GPIO_TSP_LDO_ON, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_LDO_ON, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_LDO_ON, 1); + + regulator_enable(regulator); + + s3c_gpio_setpull(GPIO_TSP_INT, S3C_GPIO_PULL_NONE); + s3c_gpio_cfgpin(GPIO_TSP_INT, S3C_GPIO_SFN(0xf)); + } else { + s3c_gpio_cfgpin(GPIO_TSP_SDA_18V, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_SDA_18V, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_SDA_18V, 0); + s3c_gpio_cfgpin(GPIO_TSP_SCL_18V, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_SCL_18V, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_SCL_18V, 0); + s3c_gpio_cfgpin(GPIO_TSP_INT, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_INT, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_INT, 0); + s3c_gpio_cfgpin(GPIO_TSP_LDO_ON, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_LDO_ON, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_LDO_ON, 0); + + if (regulator_is_enabled(regulator)) + regulator_disable(regulator); + } + + regulator_put(regulator); + msleep(200); + return 0; +} + +static int synaptics_touchpad_gpio_setup(void *gpio_data, bool configure) +{ + return SYNA_ts_power(configure); +} + +int SYNA_post_suspend(void *pm_data) { + pr_info("%s: RMI4 callback.\n", __func__); + return SYNA_ts_power(TOUCH_OFF); +} + +int SYNA_pre_resume(void *pm_data) { + pr_info("%s: RMI4 callback.\n", __func__); + return SYNA_ts_power(TOUCH_ON); +} + +static struct rmi_device_platform_data SYNA_platformdata = { + .sensor_name = "s7301", + .attn_gpio = RMI4_DEFAULT_ATTN_GPIO, + .attn_polarity = RMI_ATTN_ACTIVE_LOW, + .gpio_data = &rmi4_default_gpio_data, + .gpio_config = synaptics_touchpad_gpio_setup, + .f1a_button_map = &SYNA_f1a_button_map, +// .reset_delay_ms = 200, +#ifdef CONFIG_PM + .post_suspend = SYNA_post_suspend, + .pre_resume = SYNA_pre_resume, +#endif +#ifdef CONFIG_RMI4_FWLIB + .firmware_name = "KONA-E036", +#endif +}; + +static struct i2c_board_info __initdata i2c_synaptics[] = { + { + I2C_BOARD_INFO("rmi_i2c", SYNA_ADDR), + .platform_data = &SYNA_platformdata, + }, +}; + +#endif /* CONFIG_RMI4_I2C */ + +void __init kona_tsp_init(u32 system_rev) +{ + int gpio = 0, irq = 0, err = 0; + hw_rev = system_rev; + + printk(KERN_DEBUG "[TSP] %s rev : %u\n", + __func__, hw_rev); + + gpio = GPIO_TSP_LDO_ON; + gpio_request(gpio, "TSP_LDO_ON"); + gpio_direction_output(gpio, 0); + gpio_export(gpio, 0); + + have_tsp_ldo = true; + + gpio = GPIO_TSP_INT; + gpio_request(gpio, "TSP_INT"); + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); + s5p_register_gpio_interrupt(gpio); + irq = gpio_to_irq(gpio); + +#ifdef CONFIG_S3C_DEV_I2C3 + s3c_i2c3_set_platdata(NULL); + i2c_synaptics[0].irq = irq; + i2c_register_board_info(3, i2c_synaptics, + ARRAY_SIZE(i2c_synaptics)); +#endif /* CONFIG_S3C_DEV_I2C3 */ + +#if defined(CONFIG_MACH_KONA_EUR_OPEN) +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYS) + /* rev01 touch button0 & button1 position change */ + if (system_rev == 1) { + synaptics_ts_pdata.button_map->map[0] = KEY_BACK; + synaptics_ts_pdata.button_map->map[1] = KEY_MENU; + } +#endif +#endif +#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_S7301_KEYLED) + if (system_rev > 0) { + synaptics_ts_pdata.led_event = true; + err = gpio_request(GPIO_TSP_2TOUCH_EN, "GPIO_TSP_2TOUCH_EN"); + if (err) + printk(KERN_DEBUG "%s gpio_request error\n", __func__); + else { + s3c_gpio_cfgpin(GPIO_TSP_2TOUCH_EN, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_TSP_2TOUCH_EN, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_TSP_2TOUCH_EN, 0); + } + } + + /* + * button changed 2button -> 5button + * KONA 3G, WIFI: gpio >= 3 + * KONA LTE : gpio >=2 + */ + +#if defined(CONFIG_MACH_KONA_EUR_LTE) || \ + defined(CONFIG_MACH_KONALTE_USA_ATT) + if (system_rev >= 2) { +#else + if (system_rev >= 3) { +#endif + synaptics_ts_pdata.support_extend_button = true; + synaptics_ts_pdata.enable_extend_button_event = true; + } +#endif +} + +#if defined(CONFIG_KEYBOARD_GPIO) +#include <mach/sec_debug.h> +#include <linux/gpio_keys.h> +#define GPIO_KEYS(_code, _gpio, _active_low, _iswake, _hook) \ +{ \ + .code = _code, \ + .gpio = _gpio, \ + .active_low = _active_low, \ + .type = EV_KEY, \ + .wakeup = _iswake, \ + .debounce_interval = 10, \ + .isr_hook = _hook, \ + .value = 1 \ +} + +struct gpio_keys_button kona_buttons[] = { + GPIO_KEYS(KEY_VOLUMEUP, GPIO_VOL_UP, + 1, 1, sec_debug_check_crash_key), + GPIO_KEYS(KEY_VOLUMEDOWN, GPIO_VOL_DOWN, + 1, 1, sec_debug_check_crash_key), + GPIO_KEYS(KEY_POWER, GPIO_nPOWER, + 1, 1, sec_debug_check_crash_key), + GPIO_KEYS(KEY_HOMEPAGE, GPIO_OK_KEY_ANDROID, + 1, 1, sec_debug_check_crash_key), +}; + +struct gpio_keys_platform_data kona_gpiokeys_platform_data = { + kona_buttons, + ARRAY_SIZE(kona_buttons), +#ifdef CONFIG_SENSORS_HALL + .gpio_flip_cover = GPIO_HALL_SENSOR_INT, +#endif +}; + +static struct platform_device kona_keypad = { + .name = "gpio-keys", + .dev = { + .platform_data = &kona_gpiokeys_platform_data, + }, +}; +#endif +void __init kona_key_init(void) +{ + int err; +#if defined(CONFIG_KEYBOARD_GPIO) + platform_device_register(&kona_keypad); +#ifdef CONFIG_SENSORS_HALL + /* INT GPX0[3] = WAKEUP_INT0[3] */ + err = gpio_request(GPIO_HALL_SENSOR_INT, "GPIO_HALL_SENSOR_INT"); + + if (err) + printk(KERN_DEBUG "%s gpio_request error\n", __func__); + else { + s3c_gpio_setpull(GPIO_HALL_SENSOR_INT, S3C_GPIO_PULL_DOWN); + s5p_register_gpio_interrupt(GPIO_HALL_SENSOR_INT); + gpio_direction_input(GPIO_HALL_SENSOR_INT); + s3c_gpio_cfgpin(GPIO_HALL_SENSOR_INT, S3C_GPIO_SFN(0xF)); /* EINT */ + gpio_free(GPIO_HALL_SENSOR_INT); + } +#endif +#endif + + + +} |