cyb4_linux/drivers/input/keyboard/s3c-keypad-qisda.c

1428 lines
48 KiB
C

/* Qisda Tony 090324, add keypad [
* drivers/input/keyboard/s3c-keypad-qisda.c
* KeyPad Interface on S3C in Qisda eBook
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/irq.h>
#include <asm/arch/regs-irq.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
/*Qisda , wenny cheng , 20091224 , board id info {*/
#include <../include/asm-arm/plat-s3c24xx/common-smdk.h>
/*Qisda , wenny cheng , 20091224 , board id info }*/
/* Qisda, ShiYong Lin, 2009/08/18, Detect insertion source {*/
#include <asm/arch/regs-udc-hs.h>
#include <asm/arch/regs-s3c2416-clock.h>
/* } Qisda, ShiYong Lin, 2009/08/18, Detect insertion source */
#define DPRINTK(x...) printk("S3C-Keypad-qisda " x)
//#define DPRINTK(x...) /* !!!! */
#define DEVICE_NAME "s3c-keypad-qisda"
#define TRUE 1
#define FALSE 0
//#define IN_2416_EMU_BOARD
/* Qisda, ShiYong Lin, 2009/07/18, Set Power key as EINT for sys shutdown{*/
//#define POWER_KEY_FOR_SYS_SHUTDOWN
/* Qisda, ShiYong Lin, 2009/07/18, Set Power key as EINT for sys shutdown}*/
#define QISDA_TILT_0 0
#define QISDA_TILT_90 1
#define QISDA_TILT_180 3
#define QISDA_TILT_270 2
/*Qisda , wenny cheng , 20091224 , board id info {*/
//static int hw_version_for_keypad = 0;
extern int board_id;
/*Qisda , wenny cheng , 20091224 , board id info }*/
extern int average_adc_value_keep1; /*joey add to keep ADC will always return lower one 2009/12/28*/
extern int average_adc_value_keep2; /*joey add to keep ADC will always return lower one 2009/12/28*/
// Qisda, 2010/02/18, TN Wei, sleep mode wakes up for usb event {
int sleeping_cha_event = 0;
// Qisda, 2010/02/18, TN Wei, sleep mode wakes up for usb event }
/*Qisda , howard hsu, 20100116 , op_mode-delay key event {*/
#define OP_MODE_DELAY_REQUEST KEY_F9
/*} Qisda , howard hsu, 20100116 , op_mode-delay key event*/
#if defined(CONFIG_QISDA_AS090B00_EVT1) || defined(CONFIG_QISDA_AS090B00_EVT1_1)
#define MAX_KEYPAD_QISDA 23 /*shiyong joey for asus 2009/12/15*/
static int keypad_keycode_qisda[] = {
KEY_PAGEDOWN, KEY_PAGEUP, KEY_VOLUMEDOWN, KEY_VOLUMEUP,
KEY_F1, KEY_F2, KEY_F3, KEY_INSERT, KEY_ESC,
/* Qisda, ShiYong Lin, 2009/09/08, Implement for message for AP {*/
KEY_CHA_STA_WALL_CHARGER, KEY_CHA_STA_UNPLUG,
KEY_CHA_STA_USB, KEY_BATTERY_FAIL,
KEY_SLEEP, KEY_TIMER_TICK,
KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_SOUND,
KEY_SD_INSERT, KEY_BATTERY /*shiyong joey for asus 2009/12/15*/
};
#endif
#ifdef CONFIG_QISDA_QD060B00
#define QISDA_E600
//#define QISDA_L600
//#define QISDA_BQ060B00_DVT
#define MAX_KEYPAD_QISDA 29
static int keypad_keycode_qisda[] = {
KEY_MENU, KEY_SEARCH, KEY_PAGEDOWN, KEY_PAGEUP,
KEY_BACK, KEY_VOLUMEDOWN, KEY_VOLUMEUP, KEY_WAKEUP,
KEY_REFRESH, KEY_ENTER, KEY_UP, KEY_DOWN,
KEY_LEFT, KEY_RIGHT,
KEY_F1, KEY_F2, KEY_F3, KEY_F4,
KEY_F5, KEY_F6,
/* Qisda, ShiYong Lin, 2009/09/08, Implement for message for AP {*/
KEY_CLOSE, KEY_CHA_STA_WALL_CHARGER, KEY_CHA_STA_UNPLUG,
KEY_CHA_STA_USB, KEY_BATTERY_FAIL,
KEY_SLEEP, KEY_TIMER_TICK, KEY_BATTERY,
/* } Qisda, ShiYong Lin, 2009/09/08, Implement for message for AP */
/*Qisda , howard hsu, 20100116 , op_mode-delay key event {*/
KEY_F9
/*} Qisda , howard hsu, 20100116 , op_mode-delay key event*/
};
#endif
#ifdef CONFIG_QISDA_QD090B00
#define MAX_KEYPAD_QISDA 27
static int keypad_keycode_qisda[] = {
KEY_MENU, KEY_SEARCH, KEY_PAGEDOWN, KEY_PAGEUP,
KEY_BACK, KEY_VOLUMEDOWN, KEY_VOLUMEUP, KEY_WAKEUP,
KEY_REFRESH, KEY_ENTER, KEY_UP, KEY_DOWN,
KEY_F1, KEY_F2, KEY_F3, KEY_F4,
KEY_F5, KEY_F6,
/* Qisda, ShiYong Lin, 2009/09/08, Implement for message for AP {*/
KEY_CLOSE, KEY_CHA_STA_WALL_CHARGER, KEY_CHA_STA_UNPLUG,
KEY_CHA_STA_USB, KEY_BATTERY_FAIL,
KEY_SLEEP, KEY_TIMER_TICK, KEY_BATTERY,
/* } Qisda, ShiYong Lin, 2009/09/08, Implement for message for AP */
/*Qisda , howard hsu, 20100116 , op_mode-delay key event {*/
KEY_F9
/*} Qisda , howard hsu, 20100116 , op_mode-delay key event*/
};
#endif
struct s3c_keypad_qisda {
struct input_dev *dev;
int keycodes[MAX_KEYPAD_QISDA];
int pressed[MAX_KEYPAD_QISDA];
};
//static struct work_struct wqReadData;
static struct timer_list keypad_timer_qisda;
static int is_timer_on_qisda = FALSE;
static int keypad_set_irq = FALSE;
/* Qisda, ShiYong Lin, 2009/11/11, Fix the trembling voice issue when plugging usb {*/
static struct timer_list charger_source_timer;
/* } Qisda, ShiYong Lin, 2009/11/11, Fix the trembling voice issue when plugging usb */
/*joey add timer to avoid bouncing with usb in/out 20100127*/
static struct timer_list battery_status_timer;
/* Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading {*/
static struct timer_list power_fail_timer;
static struct work_struct power_fail_workq;
u32 is_pwr_fail_timer_on = 0;
/* } Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading */
int charging_source = 3;
struct input_dev *Message_dev = NULL;
//static unsigned prevmask = 1;
static void keypad_port_initialize(void)
{
#ifdef CONFIG_QISDA_AS090B00
//Set gpio as input and pull-up enable
s3c2410_gpio_cfgpin(S3C2410_GPD10, S3C2410_GPD10_INP); //T_SENSOR2
s3c2410_gpio_cfgpin(S3C2410_GPD11, S3C2410_GPD11_INP); //T_SENSOR1
s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0); // power
s3c2410_gpio_pullup(S3C2410_GPF0, 2);
s3c2410_gpio_cfgpin(S3C2410_GPD14, S3C2410_GPD14_INP); // Menu
s3c2410_gpio_pullup(S3C2410_GPD14, 2);
s3c2410_gpio_cfgpin(S3C2410_GPD15, S3C2410_GPD15_INP); // Return
s3c2410_gpio_pullup(S3C2410_GPD15, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG6, S3C2410_GPG6_INP); // Function
s3c2410_gpio_pullup(S3C2410_GPG6, 2);
s3c2410_gpio_cfgpin(S3C2410_GPH4, S3C2410_GPH4_INP); // VOL+
s3c2410_gpio_pullup(S3C2410_GPH4, 2);
s3c2410_gpio_cfgpin(S3C2410_GPH5, S3C2410_GPH5_INP); // VOL-
s3c2410_gpio_pullup(S3C2410_GPH5, 2);
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_INP); // page up
s3c2410_gpio_pullup(S3C2410_GPF7, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG7, S3C2410_GPG7_INP); // Page down
s3c2410_gpio_pullup(S3C2410_GPG7, 2);
#endif
#ifdef CONFIG_QISDA_QD090B00
/*Qisda , wenny cheng , 20091224 , board id info {*/
// hw_version_for_keypad = readl(S3C2416_GPKDAT) & (0x3<<3);
printk("\nhw_version_for_keypad: %d\n", board_id);
//if(hw_version_for_keypad){
if(board_id != QD090B00_S02){
s3c2410_gpio_cfgpin(S3C2410_GPC3, S3C2410_GPC3_OUTP); // Tilt_EN
s3c2410_gpio_setpin(S3C2410_GPC3, 1);
s3c2410_gpio_cfgpin(S3C2410_GPG2, S3C2410_GPG2_EINT10); // Search
s3c2410_gpio_pullup(S3C2410_GPG2, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_EINT11); // Return
s3c2410_gpio_pullup(S3C2410_GPG3, 2);
}
else{
//old
s3c2410_gpio_cfgpin(S3C2410_GPD14, S3C2410_GPD14_INP); // Search
s3c2410_gpio_pullup(S3C2410_GPD14, 2);
s3c2410_gpio_cfgpin(S3C2410_GPD15, S3C2410_GPD15_INP); // Return
s3c2410_gpio_pullup(S3C2410_GPD15, 2);
}
/*Qisda , wenny cheng , 20091224 , board id info }*/
//Set gpio as input and pull-up enable
s3c2410_gpio_cfgpin(S3C2410_GPD10, S3C2410_GPD10_INP); //T_SENSOR2
s3c2410_gpio_cfgpin(S3C2410_GPD11, S3C2410_GPD11_INP); //T_SENSOR1
s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0); // power
s3c2410_gpio_pullup(S3C2410_GPF0, 2);
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_INP); // page down
s3c2410_gpio_pullup(S3C2410_GPF7, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_INP); // Refresh
s3c2410_gpio_pullup(S3C2410_GPG4, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG6, S3C2410_GPG6_INP); // Menu
s3c2410_gpio_pullup(S3C2410_GPG6, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG7, S3C2410_GPG7_INP); // Page up
s3c2410_gpio_pullup(S3C2410_GPG7, 2);
s3c2410_gpio_cfgpin(S3C2410_GPH4, S3C2410_GPH4_INP); // VOL+
s3c2410_gpio_pullup(S3C2410_GPH4, 2);
s3c2410_gpio_cfgpin(S3C2410_GPH5, S3C2410_GPH5_INP); // VOL-
s3c2410_gpio_pullup(S3C2410_GPH5, 2);
#endif
#ifdef CONFIG_QISDA_QD060B00
s3c2410_gpio_cfgpin(S3C2410_GPC3, S3C2410_GPC3_OUTP); // Tilt_EN
s3c2410_gpio_setpin(S3C2410_GPC3, 1);
#ifdef CONFIG_QISDA_BK060B00
s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_INP); //T_SENSOR2
s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_INP); //T_SENSOR1
s3c2410_gpio_cfgpin(S3C2410_GPG6, S3C2410_GPG6_INP); // Menu / Plato: Menu
s3c2410_gpio_pullup(S3C2410_GPG6, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG0, S3C2410_GPG0_INP); // VOL-/LEFT
s3c2410_gpio_pullup(S3C2410_GPG0, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG2, S3C2410_GPG2_INP); // VOL+/RIGHT
s3c2410_gpio_pullup(S3C2410_GPG2, 2);
s3c2410_gpio_cfgpin(S3C2410_GPH5, S3C2410_GPH5_OUTP); // USB_SEL: DEVICE ONLY
s3c2410_gpio_setpin(S3C2410_GPH5, 0);
#else
s3c2410_gpio_cfgpin(S3C2410_GPD10, S3C2410_GPD10_INP); //T_SENSOR2
s3c2410_gpio_cfgpin(S3C2410_GPD11, S3C2410_GPD11_INP); //T_SENSOR1
//Set gpio as input and pull-up enable
// Qisda Jonas disable for keypad rework 20100104
s3c2410_gpio_cfgpin(S3C2410_GPD14, S3C2410_GPD14_INP); // Menu / Plato: Menu
s3c2410_gpio_pullup(S3C2410_GPD14, 2);
// Qisda Jonas disable for keypad rework
s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0); // power
s3c2410_gpio_pullup(S3C2410_GPF0, 2);
s3c2410_gpio_cfgpin(S3C2410_GPH5, S3C2410_GPH5_INP); // Search / UP / Plato: Vol up
s3c2410_gpio_pullup(S3C2410_GPH5, 2);
// Qisda Jonas modify for keypad rework 20100104
s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_EINT11); // Menu key
s3c2410_gpio_pullup(S3C2410_GPG3, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_EINT12); // Page up, Plato: Back
s3c2410_gpio_pullup(S3C2410_GPG4, 2);
// Qisda Jonas modify for keypad rework
#endif
s3c2410_gpio_cfgpin(S3C2410_GPD15, S3C2410_GPD15_INP); // Page down / Back / Plato: Back
s3c2410_gpio_pullup(S3C2410_GPD15, 2);
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_EINT7); // Back / Right / Plato: Page down
s3c2410_gpio_pullup(S3C2410_GPF7, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG6, S3C2410_GPG6_EINT14); // VOL / Down / Plato: Search
s3c2410_gpio_pullup(S3C2410_GPG6, 2);
s3c2410_gpio_cfgpin(S3C2410_GPG7, S3C2410_GPG7_EINT15); // Refresh / Left / Plato: Page up
s3c2410_gpio_pullup(S3C2410_GPG7, 2);
#ifdef QISDA_L600
s3c2410_gpio_cfgpin(S3C2410_GPH4, S3C2410_GPH4_INP); // OK
s3c2410_gpio_pullup(S3C2410_GPH4, 2);
#endif
#ifdef CONFIG_QISDA_BQ060B00_DVT
s3c2410_gpio_cfgpin(S3C2410_GPH4, S3C2410_GPH4_INP); // Plato: Vol down
s3c2410_gpio_pullup(S3C2410_GPH4, 2);
#endif
#endif
// CHG_STA, GPF6, Both edge triggered /*shiyong joey for asus 2009/12/15*/
s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_EINT6);
s3c2410_gpio_pullup(S3C2410_GPF6, 0); /*joey modify 2->0 20100127*/
writel((readl(S3C2410_EXTINT0) & ~(1<<27)), S3C2410_EXTINT0);
writel(((readl(S3C2410_EXTINT0) & ~(7<<24))|(4<<24)), S3C2410_EXTINT0); /*joey modify (6<<24) to (4<<24)) 20100127*/ /*1:high 4:rise 6:both*/
// VBUS_IN_STA, GPG1, Both edge triggered /*shiyong joey for asus 2009/12/15*/
s3c2410_gpio_cfgpin(S3C2410_GPG1, S3C2410_GPG1_EINT9);
s3c2410_gpio_pullup(S3C2410_GPG1, 0);
writel((readl(S3C2410_EXTINT1) & ~(1<<7)), S3C2410_EXTINT1); /* EINT9 filter enable */
writel(((readl(S3C2410_EXTINT1) & ~(7<<4))|(6<<4)), S3C2410_EXTINT1);
// Power_Fail, GPG5, Both edge triggered /*shiyong joey for asus 2009/12/15*/
s3c2410_gpio_cfgpin(S3C2410_GPG5, S3C2410_GPG5_EINT13);
s3c2410_gpio_pullup(S3C2410_GPG5, 2);
writel((readl(S3C2410_EXTINT1) & ~(1<<23)), S3C2410_EXTINT1);
writel(((readl(S3C2410_EXTINT1) & ~(7<<20))|(6<<20)), S3C2410_EXTINT1);
}
struct s3c_keypad_qisda *pdata;
/*
static s3c_keypad_qisda_workqueue(struct work_struct *work)
{
struct input_dev *dev = pdata->dev;
DPRINTK("s3c_keypad_qisda_workqueue 1\n");
input_report_key(dev,pdata->keycodes[0],1);
input_sync(dev);
msleep(200);
input_report_key(dev,pdata->keycodes[0],0);
input_sync(dev);
}
*/
/* Qisda, ShiYong Lin, 2009/09/10, Detect insertion source {*/
/*Leo*/
int IsWallCharger(void)
{
u32 i=0;
u32 read_pin=99, test_pin = 99;
udelay(1000);
if((readl(S3C2410_GPGDAT)&0x2)==0x2){
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
s3c2410_gpio_setpin(S3C2443_GPH14, 1); /* usb power enbale */
// s3c2410_gpio_cfgpin(S3C2410_GPD13, S3C2410_GPD13_OUTP);
// s3c2410_gpio_setpin(S3C2410_GPD13,1); /* usb power enbale */
/* if reset by sleep wakeup, control the retention I/O cell */
if (__raw_readl(S3C_RSTSTAT) & 0x8)
__raw_writel(__raw_readl(S3C_RSTCON)|(1<<16), S3C_RSTCON);
__raw_writel(__raw_readl(S3C2410_MISCCR)&~(1<<12), S3C2410_MISCCR);
__raw_writel(__raw_readl(S3C_PWRCFG)|(1<<4), S3C_PWRCFG);
__raw_writel((0<<2)|(1<<0), S3C_URSTCON);
udelay(1000);
__raw_writel((1<<2)|(0<<0), S3C_URSTCON);
__raw_writel((0<<2)|(0<<0), S3C_URSTCON);
__raw_writel((0<<3)|(0<<2)|(1<<1)|(0<<0), S3C_PHYCTRL);
__raw_writel((1<<31)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0), S3C_PHYPWR);
__raw_writel((0<<31)|(1<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
__raw_writel((1<<31)|(1<<4)|(1<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
}
for(i=0;i<10;i++) {
read_pin = __raw_readl(S3C_UDC_SYS_STATUS_REG)&0x60;
udelay(1000);
}
//Benq,Andy modify for wall charger recognize bugfix
//if( (read_pin != 0x60) ){
if( (read_pin != 0x60) && (read_pin != 0x0)){ //Benq, Andy add (read_pin != 0x0)
printk("usb\n");
#if defined(CONFIG_QISDA_E600_EVT2)|| defined(CONFIG_QISDA_QD060N00_DVT1_1)
if((readl(S3C2410_GPGDAT) &(1<<1))==0)
{
if((readl(S3C2410_GPHDAT) &&(1<<11))==0)
{
printk("3G Module off\n");
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
s3c2410_gpio_setpin(S3C2443_GPH14, 0);
}
__raw_writel((0<<31)|(0<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
}
#endif
#if defined(CONFIG_QISDA_AS090B00_EVT1)||defined(CONFIG_QISDA_AS090B00_EVT1_1)||defined(CONFIG_QISDA_QD090B00_EVT1)
if((readl(S3C2410_GPGDAT) &(1<<1))==0)
{
if((readl(S3C2410_GPHDAT) &(1<<11))==0)
{
// printk("3G Module off\n");
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
s3c2410_gpio_setpin(S3C2443_GPH14, 0);
}
__raw_writel((0<<31)|(0<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
}
#endif
#ifdef CONFIG_PM_PLATFORM_POWER_SAVING
//{Benq,Andy add for USB power disable
printk("\nUSB_UDC_DEVICE_POWER_DOWN\n");
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
s3c2410_gpio_setpin(S3C2443_GPH14, 0); /* usb all power disable (USB_EN20)*/
//}Benq,Andy add for USB power disable
#endif
return 0;
}
else
{
printk("wall charger\n");
#if defined(CONFIG_QISDA_E600_EVT2)||defined(CONFIG_QISDA_QD060N00_DVT1_1)
if((readl(S3C2410_GPGDAT) &(1<<1))==0)
{
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
s3c2410_gpio_setpin(S3C2443_GPH14, 0);
__raw_writel((0<<31)|(0<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
}
#endif
#if defined(CONFIG_QISDA_AS090B00_EVT1)||defined(CONFIG_QISDA_AS090B00_EVT1_1)||defined(CONFIG_QISDA_QD090B00_EVT1)
if((readl(S3C2410_GPGDAT) &(1<<1))==0)
{
if((readl(S3C2410_GPHDAT) &(1<<11))==0)
{
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
s3c2410_gpio_setpin(S3C2443_GPH14, 0);
}
__raw_writel((0<<31)|(0<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
}
#endif
#ifdef CONFIG_PM_PLATFORM_POWER_SAVING
//{Benq,Andy add for USB power disable
printk("\nUSB_UDC_DEVICE_POWER_DOWN\n");
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
s3c2410_gpio_setpin(S3C2443_GPH14, 0); /* usb all power disable (USB_EN20)*/
//}Benq,Andy add for USB power disable
#endif
return 1;
}
}
/*Leo*/
/* } Qisda, ShiYong Lin, 2009/09/10, Detect insertion source */
static void s3c_keypad_deal(struct input_dev *dev, u32 read_pin, int key)
{
if(read_pin){ //should be released
if(pdata->pressed[key]){
input_report_key(dev, pdata->keycodes[key], 0);
input_sync(dev);
pdata->pressed[key] = 0;
printk(" release: %d\n", pdata->keycodes[key]);
}
}
else{ //should be pressed
if(!pdata->pressed[key]){
input_report_key(dev, pdata->keycodes[key], 1);
input_sync(dev);
pdata->pressed[key] = 1;
printk(" press: %d\n", pdata->keycodes[key]);
}
}
}
static irqreturn_t s3c_pwrbtn_close_irq(int irq, void *id)
{
/* Qisda, ShiYong Lin, 2009/08/27, Implementing power btn behavior {*/
struct input_dev *dev = id;
u32 read_pin;
read_pin = readl(S3C2410_GPFDAT) & (1<<0);
#if defined(CONFIG_QISDA_AS090B00_EVT1) || defined(CONFIG_QISDA_AS090B00_EVT1_1)
s3c_keypad_deal(dev, read_pin, 8);
#elif defined(CONFIG_QISDA_QD090B00) || defined(CONFIG_QISDA_QD060N00_DVT1_1)
s3c_keypad_deal(dev, read_pin, 7);
#else
s3c_keypad_deal(dev, read_pin, 7);
#endif
#ifdef POWER_KEY_FOR_SYS_SHUTDOWN
//close system by letting P_KEEP low
#ifdef CONFIG_QISDA_BK060B00
s3c2410_gpio_cfgpin(S3C2410_GPD14, S3C2410_GPD14_OUTP);
s3c2410_gpio_setpin(S3C2410_GPD14, 0);
#else
s3c2410_gpio_setpin(S3C2410_GPG0, 0);
s3c2410_gpio_cfgpin(S3C2410_GPG0, S3C2410_GPG0_OUTP);
#endif
#endif
/* } Qisda, ShiYong Lin, 2009/08/27, Implementing power btn behavior */
return IRQ_HANDLED;
}
static void battery_status_handler(unsigned long data)
{
//struct input_dev *dev = id;
u32 read_pin;
u32 i, j;
printk("battery_status_handler\n");
read_pin = readl(S3C2410_GPGDAT) & (1<<1); /*joey add condition with usb/charger 20100128*/
if(read_pin!=0)
{
read_pin = readl(S3C2410_GPFDAT) & (0x01<<6);
#ifdef CONFIG_QISDA_QD090B00
if(read_pin)
{
//s3c_keypad_deal(dev, 0 , 25);
input_report_key(Message_dev,KEY_BATTERY,1);
input_sync(Message_dev);
printk("s3c_battery_status_irq, keypad_message_to_ap\n");
}
else
{
//s3c_keypad_deal(dev, 1 , 25);
input_report_key(Message_dev,KEY_BATTERY,0);
input_sync(Message_dev);
}
#else
if(read_pin)
{
//s3c_keypad_deal(dev, 0 , 27);
input_report_key(Message_dev,KEY_BATTERY,1);
input_sync(Message_dev);
printk("s3c_battery_status_irq, keypad_message_to_ap\n");
}
else
{
//s3c_keypad_deal(dev, 1 , 27);
input_report_key(Message_dev,KEY_BATTERY,0);
input_sync(Message_dev);
}
#endif
}
enable_irq(IRQ_EINT6); /*joey add timer to avoid bouncing with usb in/out 20100127*/
}
static irqreturn_t s3c_battery_status_irq(int irq, void *id) /*joey add timer to avoid bouncing with usb in/out 20100127*/
{
printk("s3c_battery_status_irq, detecting\n");
disable_irq(IRQ_EINT6);
battery_status_timer.expires = jiffies + (HZ);
add_timer(&battery_status_timer);
return IRQ_HANDLED;
}
/* Qisda, ShiYong Lin, 2009/11/11, Fix the trembling voice issue when plugging usb {*/
static irqreturn_t s3c_cha_sta_irq(int irq, void *id)
{
/* Qisda , howard hsu, 2010/01/16 , op_mode-delay key event {*/
op_mode_delay_message_to_ap(0);//0:usb,1:sd
/* } Qisda , howard hsu, 2010/01/16 , op_mode-delay key event */
// Qisda, 2010/02/18, TN Wei, sleep mode wakes up for usb event {
sleeping_cha_event = 1;
// Qisda, 2010/02/18, TN Wei, sleep mode wakes up for usb event }
printk("s3c_cha_sta_irq\n");
disable_irq(IRQ_EINT9);
charger_source_timer.expires = jiffies + (HZ);
add_timer(&charger_source_timer);
return IRQ_HANDLED;
}
/* } Qisda, ShiYong Lin, 2009/11/11, Fix the trembling voice issue when plugging usb */
/* Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading {*/
static irqreturn_t s3c_pwr_fail_irq(int irq, void *id)
{
printk("s3c_pwr_fail_irq, detecting\n");
disable_irq(IRQ_EINT13);
power_fail_timer.expires = jiffies + (HZ*3);
if(is_pwr_fail_timer_on == 0){
// printk("add_timer, detected\n");
add_timer(&power_fail_timer);
is_pwr_fail_timer_on = 1;
}
else{
// printk("mod_timer, detected\n");
mod_timer(&power_fail_timer, keypad_timer_qisda.expires);
}
return IRQ_HANDLED;
}
/* } Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading */
/* Qisda, ShiYong Lin, 2009/07/22, Implement function for RTC tick service {*/
void rtc_tick_keypad_message_to_ap (void)
{
input_report_key(Message_dev,KEY_TIMER_TICK,1);
input_sync(Message_dev);
input_report_key(Message_dev,KEY_TIMER_TICK,0);
input_sync(Message_dev);
printk("rtc_tick_keypad_message_to_ap, keypad_message_to_ap\n");
}
/*} Qisda, ShiYong Lin, 2009/07/22, Implement function for RTC tick service */
/* Qisda, Leo SJ Yang, 2009/10/26*/
/*send key code F6 1 when USB plugin*/
/*send key code F6 0 when USB unplug*/
/*send key code F6 0 when safely remove usb{*/
void USB_SaftRemove_keypad_message_to_ap(uint uiSleep)
{
if(uiSleep==1)
{
input_report_key(Message_dev,KEY_F6,1);
input_sync(Message_dev);
printk("Key-USB_PlugIn\n");
}
else
{
input_report_key(Message_dev,KEY_F6,0);
input_sync(Message_dev);
printk("Key-USB_PlugOut\n");
//printk("USB_SaftRemove_keypad_message_to_ap, USB_SaftRemove_keypad_message_to_ap press\n");
}
}
/*} Qisda, Leo SJ Yang, 2009/10/26*/
/*Qisda , howard hsu, 20100116 , op_mode-delay key event {*/
/* OP_MODE_DELAY_REQUEST is KEY_F9 */
/* Qisda , howard hsu, 20100208 , add type, 0 for usb, 1 for sd */
void op_mode_delay_message_to_ap(uint type)
{
static uint last_type=0;
if (type == last_type)
{
if(pdata!=NULL)
{
change_bit(OP_MODE_DELAY_REQUEST,pdata->dev->key);
}
}
last_type = type;
input_report_key(Message_dev,OP_MODE_DELAY_REQUEST,type);
input_sync(Message_dev);
}
/*} Qisda , howard hsu, 20100116 , op_mode-delay key event*/
/* Qisda, howard hsu, 2010/01/21, SW_DEBOUNCE for sd card { */
// disable it first, wait integration test
#ifdef CONFIG_SD_SW_DEBOUNCE
void SD_Detect_keypad_message_to_ap(uint sd_on)
{
static uint last_sd_on=0;
if (last_sd_on == sd_on)
{
printk("\nCC--Repeat SDKey(%d)\n",sd_on);
if(pdata!=NULL)
{
change_bit(KEY_F5,pdata->dev->key);
}
}
last_sd_on = sd_on;
input_report_key(Message_dev,KEY_F5,sd_on);
input_sync(Message_dev);
printk("\nCC--SendSD Key(%d)\n",sd_on);
}
#endif /* CONFIG_SD_SW_DEBOUNCE */
/* } Qisda, howard hsu, 2010/01/21, SW_DEBOUNCE for sd card */
/* Qisda, ShiYong Lin, 2009/09/08, Implement sleep message to AP {*/
void s3c_keypad_pm_sleep_message_to_ap (uint uiSleep)
{
if(uiSleep){
input_report_key(Message_dev,KEY_SLEEP,1);
input_sync(Message_dev);
}
else{
input_report_key(Message_dev,KEY_SLEEP,0);
input_sync(Message_dev);
}
}
/* } Qisda, ShiYong Lin, 2009/09/08, Implement sleep message to AP */
static void s3c_keypad_set_irq(struct input_dev *dev)
{
set_irq_type(IRQ_EINT0, 0x3);
request_irq(IRQ_EINT0, s3c_pwrbtn_close_irq,
SA_INTERRUPT, DEVICE_NAME, dev);
set_irq_type(IRQ_EINT6, 0x3); /*shiyong joey for asus 2009/12/15*/
request_irq(IRQ_EINT6, s3c_battery_status_irq,
SA_INTERRUPT, "s3c2410-battery status", dev);
set_irq_type(IRQ_EINT9, 0x3);
request_irq(IRQ_EINT9, s3c_cha_sta_irq,
SA_INTERRUPT, "s3c2410-charging status", dev);
/* Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading {*/
if((readl(S3C2410_GPGDAT) & (1<<5)) == 0){
set_irq_type(IRQ_EINT13, IRQT_HIGH);
}
else{
set_irq_type(IRQ_EINT13, IRQT_LOW);
}
/* } Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading */
request_irq(IRQ_EINT13, s3c_pwr_fail_irq,
SA_INTERRUPT, "s3c2410-power fail status", dev);
}
/* Qisda, ShiYong Lin, 2009/11/11, Fix the trembling voice issue when plugging usb {*/
static void charger_source_handler(unsigned long data)
{
u32 read_pin = 99;
printk("charger_source_handler_qisda\n");
read_pin = readl(S3C2410_GPGDAT) & (1<<1);
printk("GPG1 = %d\n", read_pin);
if(read_pin != 0){
//s3c2410_gpio_pullup(S3C2410_GPF6, 0); /*joey add to put floating GPF6 with usb 20100201*/
average_adc_value_keep1=9999; /*joey add to keep ADC will always return lower one 2009/12/28*/
average_adc_value_keep2=9999; /*joey add to keep ADC will always return lower one 2009/12/28*/
input_report_key(Message_dev, KEY_CHA_STA_UNPLUG, 0);
input_sync(Message_dev);
printk("usb or wallchager\n");
if(IsWallCharger()==0){
charging_source = 0;
input_report_key(Message_dev, KEY_CHA_STA_USB, 1);
input_sync(Message_dev);
printk("USB, EN2 = 0, EN1 = 1\n");
//EN2
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB0, 0);
//EN1
s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB4, 1);
}
else
{
charging_source = 1;
input_report_key(Message_dev, KEY_CHA_STA_WALL_CHARGER, 1);
input_sync(Message_dev);
printk("Charger, EN2 = 1, EN1 = 0\n");
//EN2
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB0, 1);
//EN1
s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB4, 0);
}
}
else{
//s3c2410_gpio_pullup(S3C2410_GPF6, 1); /*joey add to pull low GPF6 without usb 20100201*/
printk("nothing\n");
input_report_key(Message_dev, KEY_CHA_STA_UNPLUG, 1);
input_sync(Message_dev);
if(charging_source==0){
input_report_key(Message_dev, KEY_CHA_STA_USB, 0);
input_sync(Message_dev);
}
else{
input_report_key(Message_dev, KEY_CHA_STA_WALL_CHARGER, 0);
input_sync(Message_dev);
}
charging_source = 2;
printk("EN2 = 0, EN1 = 1\n");
//EN2
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB0, 0);
//EN1
s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB4, 1);
#ifdef CONFIG_PM_PLATFORM_POWER_SAVING
//{Benq,Andy add for disable USB power
printk("\nUSB_UDC_DEVICE_POWER_DOWN\n");
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
s3c2410_gpio_setpin(S3C2443_GPH14, 0); /* usb all power disable (USB33 & USB12)*/
//}Benq,Andy add for disable USB power
#endif
}
enable_irq(IRQ_EINT9);
}
/* } Qisda, ShiYong Lin, 2009/11/11, Fix the trembling voice issue when plugging usb */
/* Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading {*/
static void power_fail_handler(unsigned long data)
{
// printk("power_fail_handler\n");
schedule_work(&power_fail_workq);
}
static void power_fail_workqueue(struct work_struct *work)
{
u32 test_pin, i;
u32 read_pin = readl(S3C2410_GPGDAT) & (1<<5);
msleep(1);
// printk("power_fail_workqueue, read_pin = %d\n",read_pin);
for(i = 0; i <100; i++){
test_pin = readl(S3C2410_GPGDAT) & (1<<5);
msleep(1);
if(read_pin != test_pin){
printk("read_pin != test_pin\n");
is_pwr_fail_timer_on = 0;
enable_irq(IRQ_EINT13);
return;
}
msleep(1);
}
// printk("power_fail_workqueue test_pin = %d\n", read_pin);
if(read_pin == 0){
// printk("send KEY_BATTERY_FAIL trigger, 0\n");
set_irq_type(IRQ_EINT13, IRQT_HIGH);
#if defined(CONFIG_QISDA_AS090B00_EVT1) || defined(CONFIG_QISDA_AS090B00_EVT1_1)
s3c_keypad_deal(Message_dev, 0, 12);
#elif defined(CONFIG_QISDA_QD090B00)
s3c_keypad_deal(Message_dev, 0, 22);
#elif CONFIG_QISDA_QD060N00_DVT1_1
s3c_keypad_deal(Message_dev, 0, 24);
#else
s3c_keypad_deal(Message_dev, 0, 12);
#endif
}
else{
// printk("send KEY_BATTERY_FAIL trigger, 1\n");
set_irq_type(IRQ_EINT13, IRQT_LOW);
#if defined(CONFIG_QISDA_AS090B00_EVT1) || defined(CONFIG_QISDA_AS090B00_EVT1_1)
s3c_keypad_deal(Message_dev, 1, 12);
#elif defined(CONFIG_QISDA_QD090B00)
s3c_keypad_deal(Message_dev, 1, 22);
#elif CONFIG_QISDA_QD060N00_DVT1_1
s3c_keypad_deal(Message_dev, 1, 24);
#else
s3c_keypad_deal(Message_dev, 1, 12);
#endif
}
is_pwr_fail_timer_on = 0;
enable_irq(IRQ_EINT13);
return;
}
/* } Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading */
static void keypad_timer_handler_qisda(unsigned long data)
{
u32 read_pin;
static u32 headphonr_insert;
static int headphonr_insert_counter=2;
u32 read_tilt;
static u32 tilt_status_previous;
static int tilt_counter=3;
static u32 mmc_status_previous = 0xF;
static int mmc_counter=16;
//struct s3c_keypad_qisda *pdata = (struct s3c_keypad_qisda *)data;
pdata = (struct s3c_keypad_qisda *)data;
struct input_dev *dev = pdata->dev;
#ifdef CONFIG_QISDA_AS090B00
read_pin = readl(S3C2410_GPFDAT);
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 0); // Page down
s3c_keypad_deal(dev, (read_pin & (0x1<<1)), 21); // SD card
if(headphonr_insert != (read_pin & (1<<4))){ // Headphone
if(headphonr_insert_counter != 0){
headphonr_insert_counter --;
}
else{
if(read_pin & (1<<4)){
//printk("Earphone insert!!!!!!!!!!!!!!!!\n");
input_report_switch(dev, SW_HEADPHONE_INSERT, 1);
input_sync(dev);
}
else {
//printk("Earphone remove!!!!!!!!!!!!!!!!!!!!!\n");
input_report_switch(dev, SW_HEADPHONE_INSERT, 0);
input_sync(dev);
}
headphonr_insert = read_pin & (1<<4);
headphonr_insert_counter = 2;
}
}
else{
headphonr_insert_counter = 2;
}
read_pin = readl(S3C2410_GPGDAT);
s3c_keypad_deal(dev, (read_pin & (0x1<<6)), 6); // Function
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 1); // Page up
read_pin = readl(S3C2410_GPHDAT);
s3c_keypad_deal(dev, read_pin & 1<<5, 2); // Volume down
s3c_keypad_deal(dev, read_pin & 1<<4, 3); // Volume up
read_pin = readl(S3C2410_GPDDAT);
s3c_keypad_deal(dev, read_pin & 1<<14, 5); // Menu
s3c_keypad_deal(dev, read_pin & 1<<15, 7); // Return
read_tilt = (readl(S3C2410_GPDDAT) & (0x3<<10)) >> 10;
if(tilt_status_previous != read_tilt){
if(tilt_counter != 0){
tilt_counter--;
}
else{
if(read_tilt == QISDA_TILT_270){
s3c_keypad_deal(dev, 1, 16);
s3c_keypad_deal(dev, 1, 17);
s3c_keypad_deal(dev, 1, 18);
s3c_keypad_deal(dev, 0, 19);
}
else if(read_tilt == QISDA_TILT_90){
s3c_keypad_deal(dev, 1, 16);
s3c_keypad_deal(dev, 1, 18);
s3c_keypad_deal(dev, 1, 19);
s3c_keypad_deal(dev, 0, 17);
}
else if(read_tilt == QISDA_TILT_180){
s3c_keypad_deal(dev, 1, 16);
s3c_keypad_deal(dev, 1, 17);
s3c_keypad_deal(dev, 1, 19);
s3c_keypad_deal(dev, 0, 18);
}
else{ //QISDA_TILT_0
s3c_keypad_deal(dev, 1, 17);
s3c_keypad_deal(dev, 1, 18);
s3c_keypad_deal(dev, 1, 19);
s3c_keypad_deal(dev, 0, 16);
}
tilt_status_previous = read_tilt;
tilt_counter = 3;
}
}
else{
tilt_counter = 3;
s3c_keypad_deal(dev, 1, 16);
s3c_keypad_deal(dev, 1, 17);
s3c_keypad_deal(dev, 1, 18);
s3c_keypad_deal(dev, 1, 19);
}
#endif
#ifdef CONFIG_QISDA_QD090B00
read_pin = readl(S3C2410_GPFDAT);
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 2); // Page down
/* Qisda, howard hsu, 2010/01/21, SW_DEBOUNCE for sd card { */
#ifndef CONFIG_SD_SW_DEBOUNCE
if(mmc_status_previous != (read_pin & (0x1<<1))){
if(mmc_counter != 0){
mmc_counter--;
}
else{
s3c_keypad_deal(dev, (read_pin & (0x1<<1)), 16); // SD card
mmc_status_previous = (read_pin & (0x1<<1));
mmc_counter=16;
}
}
else{
mmc_counter=16;
}
#endif /* CONFIG_SD_SW_DEBOUNCE */
/* } Qisda, howard hsu, 2010/01/21, SW_DEBOUNCE for sd card */
if(headphonr_insert != (read_pin & (1<<4))){ // Headphone
if(headphonr_insert_counter != 0){
headphonr_insert_counter --;
}
else{
if(read_pin & (1<<4)){
//printk("Earphone insert!!!!!!!!!!!!!!!!\n");
input_report_switch(dev, SW_HEADPHONE_INSERT, 1);
input_sync(dev);
}
else {
//printk("Earphone remove!!!!!!!!!!!!!!!!!!!!!\n");
input_report_switch(dev, SW_HEADPHONE_INSERT, 0);
input_sync(dev);
}
headphonr_insert = read_pin & (1<<4);
headphonr_insert_counter = 2;
}
}
else{
headphonr_insert_counter = 2;
}
read_pin = readl(S3C2410_GPGDAT);
s3c_keypad_deal(dev, (read_pin & (0x1<<4)), 8); // Refresh
s3c_keypad_deal(dev, (read_pin & (0x1<<6)), 0); // Menu
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 3); // Page up
/*Qisda , wenny cheng , 20091224 , board id info {*/
//if(hw_version_for_keypad){
if(board_id !=QD090B00_S02)
{
//new
s3c_keypad_deal(dev, read_pin & 1<<2, 1); // Search
s3c_keypad_deal(dev, read_pin & 1<<3, 4); // Return
}
/*Qisda , wenny cheng , 20091224 , board id info }*/
read_pin = readl(S3C2410_GPHDAT);
s3c_keypad_deal(dev, read_pin & 1<<5, 5); // Volume down
s3c_keypad_deal(dev, read_pin & 1<<4, 6); // Volume up
read_pin = readl(S3C2410_GPDDAT);
/*Qisda , wenny cheng , 20091224 , board id info {*/
//if(!hw_version_for_keypad){
if(board_id ==QD090B00_S02)
{
//old
s3c_keypad_deal(dev, read_pin & 1<<14, 1); // Search
s3c_keypad_deal(dev, read_pin & 1<<15, 4); // Return
}
/*Qisda , wenny cheng , 20091224 , board id info }*/
read_tilt = (read_pin & (0x3<<10)) >> 10;
if(tilt_status_previous != read_tilt){
if(tilt_counter != 0){
tilt_counter--;
}
else{
if(read_tilt == QISDA_TILT_270){
s3c_keypad_deal(dev, 1, 12);
s3c_keypad_deal(dev, 1, 13);
s3c_keypad_deal(dev, 1, 14);
s3c_keypad_deal(dev, 0, 15);
}
else if(read_tilt == QISDA_TILT_90){
s3c_keypad_deal(dev, 1, 12);
s3c_keypad_deal(dev, 1, 15);
s3c_keypad_deal(dev, 1, 14);
s3c_keypad_deal(dev, 0, 13);
}
else if(read_tilt == QISDA_TILT_180){
s3c_keypad_deal(dev, 1, 15);
s3c_keypad_deal(dev, 1, 12);
s3c_keypad_deal(dev, 1, 13);
s3c_keypad_deal(dev, 0, 14);
}
else{ //QISDA_TILT_0
s3c_keypad_deal(dev, 1, 15);
s3c_keypad_deal(dev, 1, 13);
s3c_keypad_deal(dev, 1, 14);
s3c_keypad_deal(dev, 0, 12);
}
tilt_status_previous = read_tilt;
tilt_counter = 3;
}
}
else{
tilt_counter = 3;
s3c_keypad_deal(dev, 1, 12);
s3c_keypad_deal(dev, 1, 13);
s3c_keypad_deal(dev, 1, 14);
s3c_keypad_deal(dev, 1, 15);
}
#endif
#ifdef CONFIG_QISDA_QD060B00
read_pin = readl(S3C2410_GPFDAT);
#ifdef QISDA_E600
#ifdef CONFIG_QISDA_BQ060B00_DVT
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 2); // Page down
#else
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 4); // Back
#endif
#endif
#ifdef QISDA_L600
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 13); // Right
#endif
/* Qisda, howard hsu, 2010/01/21, SW_DEBOUNCE for sd card { */
#ifndef CONFIG_SD_SW_DEBOUNCE
if(mmc_status_previous != (read_pin & (0x1<<1))){
if(mmc_counter != 0){
mmc_counter--;
}
else{
s3c_keypad_deal(dev, (read_pin & (0x1<<1)), 18); // SD card
mmc_status_previous = (read_pin & (0x1<<1));
printk("Key-SD_CHANGE(%d)\n",mmc_status_previous);
mmc_counter=16;
}
}
else{
mmc_counter=16;
}
#endif /* CONFIG_SD_SW_DEBOUNCE */
/* } Qisda, howard hsu, 2010/01/21, SW_DEBOUNCE for sd card */
if(headphonr_insert != (read_pin & (1<<4))){ // Headphone
if(headphonr_insert_counter != 0){
headphonr_insert_counter --;
}
else{
if(read_pin & (1<<4)){
//printk("Earphone removed\n");
input_report_switch(dev, SW_HEADPHONE_INSERT, 0);
input_sync(dev);
}
else {
//printk("Earphone inserted\n");
input_report_switch(dev, SW_HEADPHONE_INSERT, 1);
input_sync(dev);
}
headphonr_insert = read_pin & (1<<4);
headphonr_insert_counter = 2;
}
}
else{
headphonr_insert_counter = 2;
}
read_pin = readl(S3C2410_GPGDAT);
#ifdef QISDA_E600
#ifdef CONFIG_QISDA_BQ060B00_DVT
//s3c_keypad_deal(dev, (read_pin & (0x1<<4)), 8); // Refresh
s3c_keypad_deal(dev, (read_pin & (0x1<<6)), 1); // Search
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 3); // Page up
if(board_id ==BQ060B00_A02)
{
s3c_keypad_deal(dev, (read_pin & (0x1<<3)), 0); // Menu
s3c_keypad_deal(dev, (read_pin & (0x1<<4)), 4); // Back
}
#else
s3c_keypad_deal(dev, (read_pin & (0x1<<4)), 3); // Page up
if(board_id ==QD060B00_A02) {
s3c_keypad_deal(dev, (read_pin & (0x1<<3)), 0); // Menu
s3c_keypad_deal(dev, (read_pin & (0x1<<6)), 2); // Page down
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 1); // Search
} else if(board_id == QD060B00_A01_And_Before){
s3c_keypad_deal(dev, (read_pin & (0x1<<6)), 6); // Volume
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 8); // Refresh
}
#endif
#endif
#ifdef QISDA_L600
s3c_keypad_deal(dev, (read_pin & (0x1<<6)), 11); // Down
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 12); // Left
#endif
#ifdef CONFIG_QISDA_BK060B00
s3c_keypad_deal(dev, (read_pin & (0x1<<0)), 12); // LEFT
s3c_keypad_deal(dev, (read_pin & (0x1<<2)), 13); // RIGHT
#endif
read_pin = readl(S3C2410_GPHDAT);
#ifdef QISDA_E600
#ifdef CONFIG_QISDA_BQ060B00_DVT
s3c_keypad_deal(dev, read_pin & 1<<4, 5); // Volume down
s3c_keypad_deal(dev, read_pin & 1<<5, 6); // Volume up
#else
// Qisda Jonas modify for keypad rework 20100104
if(board_id ==QD060B00_A02) {
s3c_keypad_deal(dev, read_pin & 1<<5, 8); // Refresh
} else if (board_id == QD060B00_A01_And_Before){
s3c_keypad_deal(dev, read_pin & 1<<5, 1); // Search
}
// Qisda Jonas modify for keypad rework
#endif
#endif
#ifdef QISDA_L600
s3c_keypad_deal(dev, read_pin & 1<<4, 9); // OK
s3c_keypad_deal(dev, read_pin & 1<<5, 10); // Up
#endif
read_pin = readl(S3C2410_GPDDAT);
#ifdef QISDA_E600
#ifdef CONFIG_QISDA_BQ060B00_DVT
// Qisda Jonas modify for keypad rework 20100103
if(board_id ==BQ060B00_A01_And_Before)
{
s3c_keypad_deal(dev, read_pin & 1<<14, 0); // Menu
s3c_keypad_deal(dev, read_pin & 1<<15, 4); // Back
}
#else
// Qisda Jonas modify for keypad rework
if(board_id == QD060B00_A02) {
s3c_keypad_deal(dev, read_pin & 1<<15, 6); // Volumn
} else if(board_id == QD060B00_A01_And_Before){
s3c_keypad_deal(dev, read_pin & 1<<14, 0); // Menu
s3c_keypad_deal(dev, read_pin & 1<<15, 2); // Page down
}
#endif
#endif
#ifdef QISDA_L600
s3c_keypad_deal(dev, read_pin & 1<<15, 4); // Back
#endif
//Benq,Aaron: no tilt sensor in Plato
#ifndef CONFIG_QISDA_BQ060B00_DVT
#ifdef CONFIG_QISDA_BK060B00
read_pin = readl(S3C2410_GPGDAT);
read_tilt = (read_pin & (0x3<<3)) >> 3;
#else
read_tilt = (read_pin & (0x3<<10)) >> 10;
#endif
if(tilt_status_previous != read_tilt){
if(tilt_counter != 0){
tilt_counter--;
}
else{
if(read_tilt == QISDA_TILT_270){
s3c_keypad_deal(dev, 1, 14);
s3c_keypad_deal(dev, 1, 15);
s3c_keypad_deal(dev, 1, 16);
s3c_keypad_deal(dev, 0, 17);
}
else if(read_tilt == QISDA_TILT_90){
s3c_keypad_deal(dev, 1, 14);
s3c_keypad_deal(dev, 1, 17);
s3c_keypad_deal(dev, 1, 16);
s3c_keypad_deal(dev, 0, 15);
}
else if(read_tilt == QISDA_TILT_180){
s3c_keypad_deal(dev, 1, 17);
s3c_keypad_deal(dev, 1, 14);
s3c_keypad_deal(dev, 1, 15);
s3c_keypad_deal(dev, 0, 16);
}
else{ //QISDA_TILT_0
s3c_keypad_deal(dev, 1, 17);
s3c_keypad_deal(dev, 1, 15);
s3c_keypad_deal(dev, 1, 16);
s3c_keypad_deal(dev, 0, 14);
}
tilt_status_previous = read_tilt;
tilt_counter = 3;
}
}
else{
tilt_counter = 3;
s3c_keypad_deal(dev, 1, 14);
s3c_keypad_deal(dev, 1, 15);
s3c_keypad_deal(dev, 1, 16);
s3c_keypad_deal(dev, 1, 17);
}
#endif // #ifndef CONFIG_QISDA_BQ060B00_DVT
#endif
if (is_timer_on_qisda == FALSE) {
add_timer(&keypad_timer_qisda);
is_timer_on_qisda = TRUE;
} else {
keypad_timer_qisda.expires = jiffies + (HZ/8);
mod_timer(&keypad_timer_qisda,keypad_timer_qisda.expires);
}
if(!keypad_set_irq){
s3c_keypad_set_irq(pdata->dev);
keypad_set_irq = TRUE;
}
}
static int __init s3c_keypad_qisda_probe(struct platform_device *pdev)
{
int ret=0;
int i;
struct input_dev *input_dev;
struct s3c_keypad_qisda *s3c_keypad_qisda;
DPRINTK("s3c_keypad_qisda_probe for Qisda eBook\n");
keypad_port_initialize();
s3c_keypad_qisda = kzalloc(sizeof(struct s3c_keypad_qisda), GFP_KERNEL);
input_dev = input_allocate_device();
if (!s3c_keypad_qisda || !input_dev) {
ret = -ENOMEM;
goto out;
}
platform_set_drvdata(pdev, s3c_keypad_qisda);
s3c_keypad_qisda->dev = input_dev;
/* create and register the input driver */
set_bit(EV_KEY, input_dev->evbit);
//set_bit(EV_REP, input_dev->evbit);
set_bit(EV_SW, input_dev->evbit);
set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
for(i=0; i<MAX_KEYPAD_QISDA; i++){
s3c_keypad_qisda->keycodes[i] = keypad_keycode_qisda[i];
s3c_keypad_qisda->pressed[i] = 0;
set_bit(s3c_keypad_qisda->keycodes[i] & KEY_MAX, input_dev->keybit);
}
input_dev->name = DEVICE_NAME;
input_dev->phys = "s3c-keypad-qisda/input0";
input_dev->cdev.dev = &pdev->dev;
input_dev->private = s3c_keypad_qisda;
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0001;
input_dev->keycode = keypad_keycode_qisda;
input_register_device(input_dev);
/* Scan timer init */
init_timer(&keypad_timer_qisda);
keypad_timer_qisda.function = keypad_timer_handler_qisda;
keypad_timer_qisda.data = (unsigned long)s3c_keypad_qisda;
keypad_timer_qisda.expires = jiffies + (HZ*10);
if (is_timer_on_qisda == FALSE) {
add_timer(&keypad_timer_qisda);
is_timer_on_qisda = TRUE;
} else {
mod_timer(&keypad_timer_qisda,keypad_timer_qisda.expires);
}
/* Qisda, ShiYong Lin, 2009/11/11, Fix the trembling voice issue when plugging usb {*/
init_timer(&charger_source_timer);
charger_source_timer.function = charger_source_handler;
/* } Qisda, ShiYong Lin, 2009/11/11, Fix the trembling voice issue when plugging usb */
/*joey add timer to avoid bouncing with usb in/out 20100127*/
init_timer(&battery_status_timer);
battery_status_timer.function = battery_status_handler;
/* Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading {*/
init_timer(&power_fail_timer);
power_fail_timer.function = power_fail_handler;
INIT_WORK(&power_fail_workq, power_fail_workqueue);
/* } Qisda, ShiYong Lin, 2009/11/11, Modify for pwr fail event occurring wrongly when heavy loading */
//initial work queue
//INIT_WORK(&wqReadData,s3c_keypad_qisda_workqueue);
//{Benq,Andy add for USB cable unplug bugfix
//If boot up with USB cable, s3c_adc_init will set charging_source to 0, without sending input_report_key,
//so recheck is needed when initializing keypad, setting KEY_CHA_STA_USB to 1
if( charging_source == 0 ){
if ( ((readl(S3C2410_GPGDAT) & (1<<1)) != 0) && (IsWallCharger() == 0) )
input_report_key(s3c_keypad_qisda->dev, KEY_CHA_STA_USB, 1);
}
//}Benq,Andy add for USB cable unplug bugfix
DPRINTK("s3c_keypad_qisda_probe finished\n");
/* Qisda, ShiYong Lin, 2009/08/27, Implement for message for AP {*/
Message_dev = input_dev;
/* } Qisda, ShiYong Lin, 2009/08/27, Implement for message for AP */
return 0;
out:
input_unregister_device(input_dev);
kfree(s3c_keypad_qisda);
return ret;
}
static int s3c_keypad_qisda_remove(struct platform_device *pdev)
{
struct input_dev *input_dev = platform_get_drvdata(pdev);
del_timer(&keypad_timer_qisda);
input_unregister_device(input_dev);
kfree(pdev->dev.platform_data);
DPRINTK("Removed");
return 0;
}
#ifdef CONFIG_PM
static int s3c_keypad_qisda_suspend(struct platform_device *dev, pm_message_t state)
{
return 0;
}
static int s3c_keypad_qisda_resume(struct platform_device *dev)
{
keypad_port_initialize();
return 0;
}
#else
#define s3c_keypad_suspend_qisda NULL
#define s3c_keypad_resume_qisda NULL
#endif /* CONFIG_PM */
static struct platform_driver s3c_keypad_qisda_driver = {
.probe = s3c_keypad_qisda_probe,
.remove = s3c_keypad_qisda_remove,
.suspend = s3c_keypad_qisda_suspend,
.resume = s3c_keypad_qisda_resume,
.driver = {
.owner = THIS_MODULE,
.name = DEVICE_NAME,
},
};
static int __init s3c_keypad_qisda_init(void) { return platform_driver_register(&s3c_keypad_qisda_driver); }
static void __exit s3c_keypad_qisda_exit(void) { platform_driver_unregister(&s3c_keypad_qisda_driver); }
module_init(s3c_keypad_qisda_init);
module_exit(s3c_keypad_qisda_exit);
MODULE_AUTHOR("Tony YC Huang");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("KeyPad interface for Samsung S3C 2416,Qisda eBook");
// Qisda Tony 090324, add keypad ]