static void melfas_touchkey_early_suspend(struct early_suspend *h)
{
#ifdef CONFIG_GENERIC_BLN
    if(0) {
#else
    if(1) {
#endif
	    touchkey_enable = 0;
    }
	    set_touchkey_debug('S');
	    printk(KERN_DEBUG "melfas_touchkey_early_suspend\n");
	    if (touchkey_enable < 0) {
		    printk("---%s---touchkey_enable: %d\n", __FUNCTION__,
		           touchkey_enable);
		    return;
	    }

	   disable_irq(IRQ_TOUCH_INT);
       touchkey_power_off();
}

static void melfas_touchkey_early_resume(struct early_suspend *h)
{
	set_touchkey_debug('R');
	printk(KERN_DEBUG "melfas_touchkey_early_resume\n");
	if (touchkey_enable < 0) {
		printk("---%s---touchkey_enable: %d\n", __FUNCTION__,
		       touchkey_enable);
		return;
	}
#ifndef CONFIG_S5PC110_DEMPSEY_BOARD
	gpio_direction_output(_3_GPIO_TOUCH_EN, 1);
#endif
#if !(defined(CONFIG_ARIES_NTT) || defined(CONFIG_S5PC110_DEMPSEY_BOARD))
	gpio_direction_output(_3_GPIO_TOUCH_CE, 1);
#endif
	init_hw();
	msleep(50);

	//clear interrupt
	if (readl(gpio_pend_mask_mem) & (0x1 << 1))
		writel(readl(gpio_pend_mask_mem) | (0x1 << 1),
		       gpio_pend_mask_mem);

	enable_irq(IRQ_TOUCH_INT);
	touchkey_enable = 1;

}
static ssize_t touchkey_enable_disable(struct device *dev,
				       struct device_attribute *attr,
				       const char *buf, size_t size)
{
#if 0
	printk("touchkey_enable_disable %c \n", *buf);
	if (*buf == '0') {
		set_touchkey_debug('d');
		disable_irq(IRQ_TOUCH_INT);
#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_USE_BLN
		touchkey_power_off();
#else
		gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
#if !defined(CONFIG_ARIES_NTT)
		gpio_direction_output(_3_GPIO_TOUCH_CE, 0);
#endif
#endif
		touchkey_enable = -2;
	} else if (*buf == '1') {
		if (touchkey_enable == -2) {
			set_touchkey_debug('e');
#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_USE_BLN
			touchkey_power_on();
#else
			gpio_direction_output(_3_GPIO_TOUCH_EN, 1);
#if !defined(CONFIG_ARIES_NTT)
			gpio_direction_output(_3_GPIO_TOUCH_CE, 1);
#endif
#endif
			touchkey_enable = 1;
			enable_irq(IRQ_TOUCH_INT);
		}
	} else {
		printk("touchkey_enable_disable: unknown command %c \n", *buf);
	}
#endif
	return size;
}
void touchkey_work_func(struct work_struct *p)
{
	u8 data[3];
	int ret;
	int retry = 10;

	set_touchkey_debug('a');
	if (!gpio_get_value(_3_GPIO_TOUCH_INT)) {
		#ifdef CONFIG_CPU_FREQ
		set_dvfs_target_level(LEV_800MHZ);
		#endif
		ret = i2c_touchkey_read(KEYCODE_REG, data, 1);
		set_touchkey_debug(data[0]);
		if ((data[0] & ESD_STATE_BIT) || (ret != 0)) {
			printk
			    ("ESD_STATE_BIT set or I2C fail: data: %d, retry: %d\n",
			     data[0], retry);
			//releae key 
			input_report_key(touchkey_driver->input_dev,
					 touchkey_keycode[1], 0);
			input_report_key(touchkey_driver->input_dev,
					 touchkey_keycode[2], 0);
			retry = 10;
			while (retry--) {
#ifndef CONFIG_S5PC110_DEMPSEY_BOARD
				gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
#endif
				mdelay(300);
				init_hw();
				if (i2c_touchkey_read(KEYCODE_REG, data, 3) >=
				    0) {
					printk("%s touchkey init success\n",
					       __func__);
					set_touchkey_debug('O');
#ifndef CONFIG_S5PC110_DEMPSEY_BOARD
					enable_irq(IRQ_TOUCH_INT);
#endif 
					return;
				}
				printk("%s %d i2c transfer error retry = %d\n",
				       __func__, __LINE__, retry);
			}
			//touchkey die , do not enable touchkey
			//enable_irq(IRQ_TOUCH_INT);
			touchkey_enable = -1;
            touchkey_power_off();
			printk("%s touchkey died\n", __func__);
			set_touchkey_debug('D');
			return;
		}

		if (data[0] & UPDOWN_EVENT_BIT) {
			input_report_key(touchkey_driver->input_dev,
					 touchkey_keycode[data[0] &
							  KEYCODE_BIT], 0);
			input_sync(touchkey_driver->input_dev);
			//printk(" touchkey release keycode: %d\n", touchkey_keycode[data[0] & KEYCODE_BIT]);
			printk(KERN_DEBUG "touchkey release keycode:%d \n",
			       touchkey_keycode[data[0] & KEYCODE_BIT]);

		} else {
			if (touch_state_val == 1) {
				printk(KERN_DEBUG
				       "touchkey pressed but don't send event because touch is pressed. \n");
				set_touchkey_debug('P');
			} else {
				if ((data[0] & KEYCODE_BIT) == 2) {	// if back key is pressed, release multitouch
					//printk("touchkey release tsp input. \n");
					TSP_forced_release();
				}

				input_report_key(touchkey_driver->input_dev,
						 touchkey_keycode[data[0] &
								  KEYCODE_BIT],
						 1);
				input_sync(touchkey_driver->input_dev);
				//printk(" touchkey press keycode: %d\n", touchkey_keycode[data[0] & KEYCODE_BIT]);
				printk(KERN_DEBUG
				       "touchkey press keycode:%d \n",
				       touchkey_keycode[data[0] & KEYCODE_BIT]);
			}
		}
	}
	//clear interrupt
#ifndef CONFIG_S5PC110_DEMPSEY_BOARD
	if (readl(gpio_pend_mask_mem) & (0x1 << 1))
		writel(readl(gpio_pend_mask_mem) | (0x1 << 1),
		       gpio_pend_mask_mem);

	set_touchkey_debug('A');
	enable_irq(IRQ_TOUCH_INT);
#endif 
	set_touchkey_debug('A');
}
static int __init touchkey_init(void)
{
	int ret = 0;
	int retry = 10;
	char data[3] = { 0, };


		touchkey_keycode[2] = KEY_ENTER;

#if !defined(CONFIG_ARIES_NTT)
	if (ret = gpio_request(_3_GPIO_TOUCH_CE, "_3_GPIO_TOUCH_CE"))
		printk(KERN_ERR "Failed to request gpio %s:%d\n", __func__, __LINE__);
#endif
	if (ret = gpio_request(_3_GPIO_TOUCH_EN, "_3_GPIO_TOUCH_EN"))
		printk(KERN_ERR "Failed to request gpio %s:%d\n", __func__, __LINE__);
	if (ret = gpio_request(_3_TOUCH_SDA_28V, "_3_TOUCH_SDA_28V"))
		printk(KERN_ERR "Failed to request gpio %s:%d\n", __func__, __LINE__);
	if (ret = gpio_request(_3_TOUCH_SCL_28V, "_3_TOUCH_SCL_28V"))
		printk(KERN_ERR "Failed to request gpio %s:%d\n", __func__, __LINE__);

	ret = misc_register(&touchkey_update_device);
	if (ret) {
		printk("%s misc_register fail\n", __FUNCTION__);
	}

	if (device_create_file
	    (touchkey_update_device.this_device, &dev_attr_touch_version) < 0) {
		printk("%s device_create_file fail dev_attr_touch_version\n",
		       __FUNCTION__);
		pr_err("Failed to create device file(%s)!\n",
		       dev_attr_touch_version.attr.name);
	}

	if (device_create_file
	    (touchkey_update_device.this_device, &dev_attr_touch_update) < 0) {
		printk("%s device_create_file fail dev_attr_touch_update\n",
		       __FUNCTION__);
		pr_err("Failed to create device file(%s)!\n",
		       dev_attr_touch_update.attr.name);
	}

	if (device_create_file
	    (touchkey_update_device.this_device, &dev_attr_brightness) < 0) {
		printk("%s device_create_file fail dev_attr_touch_update\n",
		       __FUNCTION__);
		pr_err("Failed to create device file(%s)!\n",
		       dev_attr_brightness.attr.name);
	}

	if (device_create_file
	    (touchkey_update_device.this_device,
	     &dev_attr_enable_disable) < 0) {
		printk("%s device_create_file fail dev_attr_touch_update\n",
		       __FUNCTION__);
		pr_err("Failed to create device file(%s)!\n",
		       dev_attr_enable_disable.attr.name);
	}
#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_USE_BLN
	ret = 0;
	ret = misc_register(&backlightnotification_device);
	if (ret) {
		printk("%s misc_register fail\n", __FUNCTION__, backlightnotification_device.name);
	}
	//add the backlightnotification attributes
	if (device_create_file(backlightnotification_device.this_device, &dev_attr_enabled) < 0)
	{
		printk("%s device_create_file fail dev_attr_touch_update\n", __FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_enabled.attr.name);
	}
	if (device_create_file(backlightnotification_device.this_device, &dev_attr_notification_led) < 0)
	{
		printk("%s device_create_file fail dev_attr_touch_update\n", __FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_notification_led.attr.name);
	}
	if (device_create_file(backlightnotification_device.this_device, &dev_attr_version) < 0)
	{
		printk("%s device_create_file fail dev_attr_touch_update\n", __FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_version.attr.name);
	}
#endif

	touchkey_wq = create_singlethread_workqueue("melfas_touchkey_wq");
	if (!touchkey_wq)
		return -ENOMEM;

	INIT_WORK(&touchkey_work, touchkey_work_func);

	init_hw();

	while (retry--) {
		if (get_touchkey_firmware(data) == 0)	//melfas need delay for multiple read
			break;
	}
	printk("%s F/W version: 0x%x, Module version:0x%x\n", __FUNCTION__,
	       data[1], data[2]);
	touch_version = data[1];
	retry = 3;
#if 0
	//update version "eclair/vendor/samsung/apps/Lcdtest/src/com/sec/android/app/lcdtest/touch_firmware.java"
	if ((data[1] >= 0xa1) && (data[1] < 0xa9)) {
		set_touchkey_debug('U');
		while (retry--) {
			if (ISSP_main() == 0) {
				printk("touchkey_update succeeded\n");
				set_touchkey_debug('C');
				break;
			}
			printk("touchkey_update failed... retry...\n");
			set_touchkey_debug('f');
		}
		if (retry <= 0) {
#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_USE_BLN
			touchkey_power_off();
#else
			gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
#if !defined(CONFIG_ARIES_NTT)
			gpio_direction_output(_3_GPIO_TOUCH_CE, 0);
#endif
#endif
			msleep(300);
		}
		init_hw();	//after update, re initalize.
	}
#endif
	ret = i2c_add_driver(&touchkey_i2c_driver);

	if (ret) {
		printk
		    ("melfas touch keypad registration failed, module not inserted.ret= %d\n",
		     ret);
	}
	return ret;
}
static int i2c_touchkey_write(u8 * val, unsigned int len)
{
	int err;
	struct i2c_msg msg[1];
	unsigned char data[2];
	int retry = 2;

#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_USE_BLN
	if (touchkey_driver == NULL) {
#else
	if ((touchkey_driver == NULL) || !(touchkey_enable == 1)) {
#endif
		printk(KERN_DEBUG "touchkey is not enabled.W\n");
		return -ENODEV;
	}

	while (retry--) {
		data[0] = *val;
		msg->addr = touchkey_driver->client->addr;
		msg->flags = I2C_M_WR;
		msg->len = len;
		msg->buf = data;
		err = i2c_transfer(touchkey_driver->client->adapter, msg, 1);
		if (err >= 0)
			return 0;
		printk(KERN_DEBUG "%s %d i2c transfer error\n", __func__,
		       __LINE__);
		mdelay(10);
	}
	return err;
}

extern unsigned int touch_state_val;
extern void TSP_forced_release(void);
void touchkey_work_func(struct work_struct *p)
{
	u8 data[3];
	int ret;
	int retry = 10;

	set_touchkey_debug('a');
	if (!gpio_get_value(_3_GPIO_TOUCH_INT)) {
		#ifdef CONFIG_CPU_FREQ
		set_dvfs_target_level(LEV_800MHZ);
		#endif
		ret = i2c_touchkey_read(KEYCODE_REG, data, 1);
		set_touchkey_debug(data[0]);
		if ((data[0] & ESD_STATE_BIT) || (ret != 0)) {
			printk
			    ("ESD_STATE_BIT set or I2C fail: data: %d, retry: %d\n",
			     data[0], retry);
			//releae key 
			input_report_key(touchkey_driver->input_dev,
					 touchkey_keycode[1], 0);
			input_report_key(touchkey_driver->input_dev,
					 touchkey_keycode[2], 0);
			retry = 10;
			while (retry--) {
#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_USE_BLN
				touchkey_power_off();
#else
				gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
#endif
				mdelay(300);
				init_hw();
				if (i2c_touchkey_read(KEYCODE_REG, data, 3) >=
				    0) {
					printk("%s touchkey init success\n",
					       __func__);
					set_touchkey_debug('O');
					enable_irq(IRQ_TOUCH_INT);
					return;
				}
				printk("%s %d i2c transfer error retry = %d\n",
				       __func__, __LINE__, retry);
			}
			//touchkey die , do not enable touchkey
			//enable_irq(IRQ_TOUCH_INT);
			touchkey_enable = -1;
#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_USE_BLN
			touchkey_power_off_with_i2c();
#else
			gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
#if !defined(CONFIG_ARIES_NTT)
			gpio_direction_output(_3_GPIO_TOUCH_CE, 0);
#endif
			gpio_direction_output(_3_TOUCH_SDA_28V, 0);
			gpio_direction_output(_3_TOUCH_SCL_28V, 0);
#endif
			printk("%s touchkey died\n", __func__);
			set_touchkey_debug('D');
			return;
		}

		if (data[0] & UPDOWN_EVENT_BIT) {
			input_report_key(touchkey_driver->input_dev,
					 touchkey_keycode[data[0] &
							  KEYCODE_BIT], 0);
			input_sync(touchkey_driver->input_dev);
			//printk(" touchkey release keycode: %d\n", touchkey_keycode[data[0] & KEYCODE_BIT]);
			printk(KERN_DEBUG "touchkey release keycode:%d \n",
			       touchkey_keycode[data[0] & KEYCODE_BIT]);

		} else {
			if (touch_state_val == 1) {
				printk(KERN_DEBUG
				       "touchkey pressed but don't send event because touch is pressed. \n");
				set_touchkey_debug('P');
			} else {
				if ((data[0] & KEYCODE_BIT) == 2) {	// if back key is pressed, release multitouch
					//printk("touchkey release tsp input. \n");
					TSP_forced_release();
				}

				input_report_key(touchkey_driver->input_dev,
						 touchkey_keycode[data[0] &
								  KEYCODE_BIT],
						 1);
				input_sync(touchkey_driver->input_dev);
				//printk(" touchkey press keycode: %d\n", touchkey_keycode[data[0] & KEYCODE_BIT]);
				printk(KERN_DEBUG
				       "touchkey press keycode:%d \n",
				       touchkey_keycode[data[0] & KEYCODE_BIT]);
			}
		}
	}
	//clear interrupt
	if (readl(gpio_pend_mask_mem) & (0x1 << 1))
		writel(readl(gpio_pend_mask_mem) | (0x1 << 1),
		       gpio_pend_mask_mem);

	set_touchkey_debug('A');
	enable_irq(IRQ_TOUCH_INT);
}
static void touchkey_power_off_with_i2c(void){
    touchkey_power_off();
    gpio_direction_output(_3_TOUCH_SDA_28V, 0);
    gpio_direction_output(_3_TOUCH_SCL_28V, 0);
}