示例#1
0
void  touchkey_work_func(struct work_struct * p)
{
	u8 data;

	if(i2c_touchkey_read(KEYCODE_REG, &data, 1) < 0)
	{
		printk("%s %d i2c transfer error\n", __func__, __LINE__);
		return;
	}


#ifdef CONFIG_CPU_FREQ
	set_dvfs_target_level(LEV_400MHZ);
#endif


	if(data & UPDOWN_EVENT_BIT)
	{
		input_report_key(touchkey_driver->input_dev, touchkey_keycode[data & KEYCODE_BIT], 0);
		input_sync(touchkey_driver->input_dev);
	}
	else
	{
		input_report_key(touchkey_driver->input_dev, touchkey_keycode[data & KEYCODE_BIT],1);
		input_sync(touchkey_driver->input_dev);
	}

//	enable_irq(IRQ_TOUCH_INT);
	return ;
}
示例#2
0
static irqreturn_t s3c_keygpio_ok_isr(int irq, void *dev_id)
{
	unsigned int key_status;
	static unsigned int prev_key_status = (1 << 5);
	struct s3c_keypad *pdata = (struct s3c_keypad *)dev_id;
	struct input_dev *dev = pdata->dev;

#ifdef CONFIG_CPU_FREQ
	set_dvfs_target_level(LEV_800MHZ);
#endif
	// Beware that we may not obtain exact key up/down status at
	// this point.
	key_status = (readl(S5PV210_GPH3DAT)) & ((1 << 5));

	// If ISR is called and up/down status remains the same, we
	// must have lost one and should report that first with
	// upside/down.
	if (in_sleep) {
		if (key_status == prev_key_status) {
			INPUT_REPORT_KEY(dev, 50, key_status ? 1 : 0);
		}
		in_sleep = 0;
	}

	INPUT_REPORT_KEY(dev, 50, key_status ? 0 : 1);

	if (key_status)
		TSP_forced_release_forOKkey();

	prev_key_status = key_status;
	printk(KERN_DEBUG "s3c_keygpio_ok_isr key_status =%d\n", key_status);

	return IRQ_HANDLED;
}
示例#3
0
static void keypad_timer_handler(unsigned long data)
{
	u32 press_mask;
	u32 release_mask;
	u32 restart_timer = 0;
	int i, col;
	struct s3c_keypad *pdata = (struct s3c_keypad *)data;
	struct input_dev *dev = pdata->dev;

	keypad_scan();

	for (col = 0; col < KEYPAD_COLUMNS; col++) {
		press_mask = ((keymask[col] ^ prevmask[col]) & keymask[col]);
		release_mask = ((keymask[col] ^ prevmask[col]) & prevmask[col]);

#ifdef CONFIG_CPU_FREQ
#if USE_PERF_LEVEL_KEYPAD
		if (press_mask || release_mask)
			set_dvfs_target_level(LEV_400MHZ);
#endif
#endif
		i = col * KEYPAD_ROWS;

		while (press_mask) {
			if (press_mask & 1) {
				input_report_key(dev, pdata->keycodes[i], 1);
				DPRINTK("\nkey Pressed  : key %d map %d\n", i,
					pdata->keycodes[i]);
			}
			press_mask >>= 1;
			i++;
		}

		i = col * KEYPAD_ROWS;

		while (release_mask) {
			if (release_mask & 1) {
				input_report_key(dev, pdata->keycodes[i], 0);
				DPRINTK("\nkey Released : %d  map %d\n", i,
					pdata->keycodes[i]);

			}
			release_mask >>= 1;
			i++;
		}
		prevmask[col] = keymask[col];

		restart_timer |= keymask[col];
	}

	if (restart_timer) {
		mod_timer(&keypad_timer, jiffies + HZ / 10);
	} else {
		writel(KEYIFCON_INIT, key_base + S3C_KEYIFCON);
		is_timer_on = FALSE;
	}

}
示例#4
0
static irqreturn_t s3c_keygpio_ok_isr(int irq, void *dev_id)
{
	unsigned int key_status;
	static unsigned int prev_key_status = (1 << 5);
	struct s3c_keypad *pdata = (struct s3c_keypad *)dev_id;
	struct input_dev *dev = pdata->dev;

	#ifdef CONFIG_CPU_FREQ
	set_dvfs_target_level(LEV_800MHZ);
	#endif
	// Beware that we may not obtain exact key up/down status at
	// this point.
#if defined(CONFIG_HAWK_VER_B1_REAL_ADDED_FEATURE) //NAGSM_Android_HQ_KERNEL_CLEE_20100908 : Setup Hawk Real Board Rev 0.1
	key_status = (readl(S5PV210_GPH3DAT)) & ((1 << 0));
#else
	key_status = (readl(S5PV210_GPH3DAT)) & ((1 << 5));
#endif

	// If ISR is called and up/down status remains the same, we
	// must have lost one and should report that first with
	// upside/down.
	if(s3ckeypad_evt_enable_status)		//NAGSM_Android_SEL_Kernel_Aakash_20100319
	{	

	if(in_sleep)
	{
		if (key_status == prev_key_status)
		{
#ifdef CONFIG_S5PC110_FLEMING_BOARD
			INPUT_REPORT_KEY(dev, 28, key_status ? 1 : 0);
#else
			INPUT_REPORT_KEY(dev, 50, key_status ? 1 : 0);
#endif
		}
		in_sleep = 0;
	}
#ifdef CONFIG_S5PC110_FLEMING_BOARD
	INPUT_REPORT_KEY(dev, 28, key_status ? 0 : 1);
#else
	INPUT_REPORT_KEY(dev, 50, key_status ? 0 : 1);
#endif
}
	if(key_status)
		TSP_forced_release_forOKkey();
	
	prev_key_status = key_status;
        printk(KERN_DEBUG "s3c_keygpio_ok_isr key_status =%d\n", key_status);
        
        return IRQ_HANDLED;
}
示例#5
0
void  touchkey_work_func(struct work_struct * p)
{
	u8 data[3];
	//printk("touchkey workqueue %s\n",__func__);
if(!gpio_get_value(_3_GPIO_TOUCH_INT))
{
	if(i2c_touchkey_read(KEYCODE_REG, &data, 1) < 0)
	{
		printk("%s %d i2c transfer error\n", __func__, __LINE__);
		return;
	}


#ifdef CONFIG_CPU_FREQ
	set_dvfs_target_level(LEV_400MHZ);
#endif


	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]); 
	}
	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]);
               }
	}
}
       enable_irq(IRQ_TOUCH_INT);
	return ;
}
示例#6
0
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;
#ifndef CONFIG_S5PC110_DEMPSEY_BOARD
			gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
#endif
#if !(defined(CONFIG_ARIES_NTT) || defined(CONFIG_S5PC110_DEMPSEY_BOARD))
			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);
			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');
}
示例#7
0
static void keypad_timer_handler(unsigned long data)
{
	u32 press_mask;
	u32 release_mask;
	u32 restart_timer = 0;
	int i,col;
	struct s3c_keypad *pdata = (struct s3c_keypad *)data;
	struct input_dev *dev = pdata->dev;

	keypad_scan();


	for(col=0; col < KEYPAD_COLUMNS; col++) {
		press_mask = ((keymask[col] ^ prevmask[col]) & keymask[col]); 
		release_mask = ((keymask[col] ^ prevmask[col]) & prevmask[col]); 

#ifdef CONFIG_CPU_FREQ
#if USE_PERF_LEVEL_KEYPAD
		if (press_mask || release_mask)
			set_dvfs_target_level(LEV_400MHZ);
#endif
#endif
		i = col * KEYPAD_ROWS;

		while (press_mask) {
			if (press_mask & 1) {
				if(s3ckeypad_evt_enable_status){		//NAGSM_Android_SEL_Kernel_Aakash_20100319

					#if defined(CONFIG_KEPLER_VER_B2) || defined(CONFIG_KEPLER_VER_B4) || defined(CONFIG_T959_VER_B5)|| defined (CONFIG_S5PC110_VIBRANTPLUS_BOARD)
						if((i != 1) && (i !=2)){
							input_report_key(dev,pdata->keycodes[i],1);
							printk("\nkey Pressed  : key %d map %d\n",i, pdata->keycodes[i]);
						}
					#elif defined(CONFIG_HAWK_VER_B0)
						if((i != 0) && (i !=1) && (i != 2) && (i !=3) ){
							input_report_key(dev,pdata->keycodes[i],1);
							printk("\nkey Pressed  : key %d map %d\n",i, pdata->keycodes[i]);
						}
					#else					
				input_report_key(dev,pdata->keycodes[i],1);
				printk("\nkey Pressed  : key %d map %d\n",i, pdata->keycodes[i]);
					#endif
				}
						}
			press_mask >>= 1;
			i++;
		}

		i = col * KEYPAD_ROWS;

		while (release_mask) {
			if (release_mask & 1) {
				if(s3ckeypad_evt_enable_status){		//NAGSM_Android_SEL_Kernel_Aakash_20100319
					#if defined(CONFIG_KEPLER_VER_B2) || defined(CONFIG_KEPLER_VER_B4) || defined(CONFIG_T959_VER_B5) || defined(CONFIG_HAWK_VER_B0)|| defined (CONFIG_S5PC110_VIBRANTPLUS_BOARD)
						if((i != 1) && (i !=2)){
							input_report_key(dev,pdata->keycodes[i],0);
							printk("\nkey Released : %d  map %d\n",i,pdata->keycodes[i]);
						}
					#else					
				input_report_key(dev,pdata->keycodes[i],0);
				printk("\nkey Released : %d  map %d\n",i,pdata->keycodes[i]);
					#endif
				}
				
#ifdef CONFIG_KERNEL_DEBUG_SEC
#if defined(CONFIG_S5PC110_KEPLER_BOARD) || defined(CONFIG_S5PC110_FLEMING_BOARD) || defined(CONFIG_T959_VER_B5) || defined(CONFIG_HAWK_VER_B0) || defined (CONFIG_S5PC110_VIBRANTPLUS_BOARD)

	#if defined(CONFIG_KEPLER_VER_B2) || defined(CONFIG_KEPLER_VER_B4) || defined(CONFIG_T959_VER_B5) || defined(CONFIG_HAWK_VER_B0) || defined (CONFIG_S5PC110_VIBRANTPLUS_BOARD)
		if((i != 1) && (i !=2)){
			dump_mode_key_sequence[dump_mode_key_count%DUMP_SEQUENCE_COUNT] = i;
			dump_mode_key_count++;
		}
	#endif
	#if defined(CONFIG_KEPLER_VER_B0)
	dump_mode_key_sequence[dump_mode_key_count%DUMP_SEQUENCE_COUNT] = i;
	dump_mode_key_count++;
	#endif

       {
            // check time inverval between force upload key sequence input
		int this_cpu;
		this_cpu = smp_processor_id();
		unsigned long nanosec_rem;
						
		dump_mode_key_pressed = cpu_clock(this_cpu);
		nanosec_rem = do_div(dump_mode_key_pressed, 1000000000);

		if ((dump_mode_key_pressed-dump_mode_key_pressed_prev>=2) && dump_mode_key_pressed_prev!=0)
                {
			forced_dump_time_limit=1;
              printk("force upload long time : %ul\n ",
			dump_mode_key_pressed-dump_mode_key_pressed_prev);
                 }
	
		dump_mode_key_pressed_prev=dump_mode_key_pressed;
						
	}

	if(i == PRESSED_DOWN){	
		if(is_first_key_down == 1)
		{	// when down key is pressed twice, will check whether pressed keys are same as dump seqence 
			is_dump_sequence = 0;

			//for(dump_compare_count=0; dump_compare_count<DUMP_SEQUENCE_COUNT; dump_compare_count++)
				//printk("dump_mode_key_sequence[%d] : %d\n",(dump_mode_key_count + dump_compare_count)%DUMP_SEQUENCE_COUNT, dump_mode_key_sequence[(dump_mode_key_count + dump_compare_count)%DUMP_SEQUENCE_COUNT]);
			
			for(dump_compare_count=0; dump_compare_count<DUMP_SEQUENCE_COUNT; dump_compare_count++)
			{			
				//printk("forced_dump_sequence[%d] : %d, dump_mode_key_sequence[%d] : %d\n",dump_compare_count, forced_dump_sequence[dump_compare_count],(dump_mode_key_count + dump_compare_count)%DUMP_SEQUENCE_COUNT, dump_mode_key_sequence[(dump_mode_key_count + dump_compare_count)%DUMP_SEQUENCE_COUNT]);
				if(forced_dump_sequence[dump_compare_count] == dump_mode_key_sequence[((dump_mode_key_count + dump_compare_count) % DUMP_SEQUENCE_COUNT)]){
					is_dump_sequence++;
					continue;
				}else
				{	
					//printk("This is not dump sequence.\n");
					is_dump_sequence = 0;
					break;
				}
			}
			
			if(is_dump_sequence == DUMP_SEQUENCE_COUNT)
			{		
                  if (forced_dump_time_limit==1)
                                {
                                        // case of long time between force upload key sequence
                       forced_dump_time_limit=0;
                       is_dump_sequence=0;
                       dump_mode_key_pressed_prev=0;
                       printk("Dump Mode Fail\n");
                                }
                  else	
                                {	

						if( (KERNEL_SEC_DEBUG_LEVEL_MID == kernel_sec_get_debug_level()) || 
							  (KERNEL_SEC_DEBUG_LEVEL_HIGH == kernel_sec_get_debug_level()) )	
							{
								
					printk("Now going to Dump Mode\n");
					if (kernel_sec_viraddr_wdt_reset_reg)
					{
						kernel_sec_set_cp_upload();
						kernel_sec_save_final_context(); // Save theh final context.
						kernel_sec_set_upload_cause(UPLOAD_CAUSE_FORCED_UPLOAD);
						kernel_sec_hw_reset(FALSE); 	 // Reboot.
					}
							}

            }
			}
		}else{
			is_first_key_down = 1;
		}
	}else{
		#if defined(CONFIG_KEPLER_VER_B2) || defined(CONFIG_KEPLER_VER_B4) || defined(CONFIG_T959_VER_B5) || defined(CONFIG_HAWK_VER_B0)|| defined (CONFIG_S5PC110_VIBRANTPLUS_BOARD)
			if((i != 1) && (i !=2)){
				is_first_key_down = 0;
			}
		#endif
		#if defined(CONFIG_KEPLER_VER_B0)
		is_first_key_down = 0;
		#endif			
	}				
#endif
#endif
            }
			release_mask >>= 1;
			i++;
		}
		prevmask[col] = keymask[col];

		restart_timer |= keymask[col];
	}


	if (restart_timer) {
		mod_timer(&keypad_timer,jiffies + HZ/10);
	} else {
		writel(KEYIFCON_INIT, key_base+S3C_KEYIFCON);
		is_timer_on = FALSE;
	}

}
示例#8
0
static irqreturn_t s3c_keygpio_ok_isr(int irq, void *dev_id)
{
	unsigned int key_status;
	static unsigned int prev_key_status = (1 << 5);
	struct s3c_keypad *pdata = (struct s3c_keypad *)dev_id;
	struct input_dev *dev = pdata->dev;

	#ifdef CONFIG_CPU_FREQ
	set_dvfs_target_level(LEV_800MHZ);
	#endif
	// Beware that we may not obtain exact key up/down status at
	// this point.
#if defined(CONFIG_S5PC110_SIDEKICK_BOARD)

	key_status = (readl(S5PV210_GPH3DAT)) & ((1 << 7));
	// If ISR is called and up/down status remains the same, we
	// must have lost one and should report that first with
	// upside/down.
#if 0
	if(key_status == 0){
		if(prev_key_status != 0){
		last_okkey_jiffies = jiffies;
		}
		prev_key_status = key_status;
		is_ok_key_pressed = 1;
		//printk("s3c_keygpio_ok_isr key_status =%d, but not send it.\n", key_status);
		return IRQ_HANDLED;
	}

	if((jiffies - last_okkey_jiffies) < (HZ/100)){
		prev_key_status = key_status;
	        printk("s3c_keygpio_ok_isr key_status =%d, but ignored.\n", key_status);
	        
	        return IRQ_HANDLED;
	}else{
		input_report_key(dev,50,1);
		is_ok_key_pressed = 0;
		printk("s3c_keygpio_ok_isr key_status =%d\n", prev_key_status);
	}
#endif
	if(s3ckeypad_evt_enable_status)		//NAGSM_Android_SEL_Kernel_Aakash_20100319
	{	
		if(in_sleep)
		{
			if (key_status == prev_key_status)
			{
				if(key_status == ((1 << 7)))
					input_report_key(dev,50,0);
				else
					input_report_key(dev,50,1);	
			}
			in_sleep = 0;
		}
		if(key_status == ((1 << 7)))
			input_report_key(dev,50,0);
		else
			input_report_key(dev,50,1);	
	}

#else

	key_status = (readl(S5PV210_GPH3DAT)) & ((1 << 5));

	// If ISR is called and up/down status remains the same, we
	// must have lost one and should report that first with
	// upside/down.
	if(s3ckeypad_evt_enable_status)		//NAGSM_Android_SEL_Kernel_Aakash_20100319
	{	
	if(in_sleep)
	{
		if (key_status == prev_key_status)
		{
#ifdef CONFIG_S5PC110_FLEMING_BOARD
			INPUT_REPORT_KEY(dev, 28, key_status ? 1 : 0);
#else
			INPUT_REPORT_KEY(dev, 50, key_status ? 1 : 0);
#endif
		}
		in_sleep = 0;
	}
#ifdef CONFIG_S5PC110_FLEMING_BOARD
	INPUT_REPORT_KEY(dev, 28, key_status ? 0 : 1);
#else
	INPUT_REPORT_KEY(dev, 50, key_status ? 0 : 1);
#endif
}

#endif	

	if(key_status)
		TSP_forced_release_forOKkey();
	
	prev_key_status = key_status;
        printk("s3c_keygpio_ok_isr key_status =%d\n", key_status);
        
        return IRQ_HANDLED;
}
示例#9
0
static void keypad_timer_handler(unsigned long data)
{
	u32 press_mask;
	u32 release_mask;
	u32 restart_timer = 0;
	int i,col;
	struct s3c_keypad *pdata = (struct s3c_keypad *)data;
	struct input_dev *dev = pdata->dev;

	keypad_scan();

#if defined (CONFIG_S5PC110_SIDEKICK_BOARD)
	checking_ghostkey_pressing();
#endif

	for(col=0; col < KEYPAD_COLUMNS; col++) {
		press_mask = ((keymask[col] ^ prevmask[col]) & keymask[col]); 
		release_mask = ((keymask[col] ^ prevmask[col]) & prevmask[col]); 

#ifdef CONFIG_CPU_FREQ
#if USE_PERF_LEVEL_KEYPAD
		if (press_mask || release_mask)
			set_dvfs_target_level(LEV_400MHZ);
#endif
#endif
		i = col * KEYPAD_ROWS;

		while (press_mask) {
			if (press_mask & 1) {
				if(s3ckeypad_evt_enable_status){		//NAGSM_Android_SEL_Kernel_Aakash_20100319
					if(i == 41){
						abnomal_key_combination = 1;
					}

					if((abnomal_key_combination == 1) && (i == 51)){

					}else{						
							input_report_key(dev,pdata->keycodes[i],1);
							printk("\nkey Pressed  : key %d map %d\n",i, pdata->keycodes[i]);
				}
						}
			}
			press_mask >>= 1;
			i++;
		}

		i = col * KEYPAD_ROWS;

		while (release_mask) {
			if (release_mask & 1) {
				if(s3ckeypad_evt_enable_status){		//NAGSM_Android_SEL_Kernel_Aakash_20100319
					if(i == 41){
						abnomal_key_combination = 0;
					}

					if((abnomal_key_combination == 1) && (i == 51)){ 
						// for T839. if @ is pressed, p is also pressed, then lock up occurs(UI issue...). temporary, block p key when @ is pressed.
					}else{
							input_report_key(dev,pdata->keycodes[i],0);
							printk("\nkey Released : %d  map %d\n",i,pdata->keycodes[i]);
                                }
            }
            }
			release_mask >>= 1;
			i++;
		}
		prevmask[col] = keymask[col];

		restart_timer |= keymask[col];
	}


	if (restart_timer) {
		mod_timer(&keypad_timer,jiffies + HZ/100);
	} else {
		writel(KEYIFCON_INIT, key_base+S3C_KEYIFCON);
		is_timer_on = FALSE;
	}

}
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);
}