Ejemplo n.º 1
0
/*
 * 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 {