/* 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 #include #include #include #include #include #include #include #include #include #include #include #include #include /*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 #include /* } 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; ikeycodes[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 ]