1067 lines
35 KiB
C
1067 lines
35 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, 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
|
|
|
|
#if defined(CONFIG_QISDA_AS090B00_EVT1) || defined(CONFIG_QISDA_AS090B00_EVT1_1)
|
|
#define MAX_KEYPAD_QISDA 22
|
|
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,
|
|
/* } Qisda, ShiYong Lin, 2009/09/08, Implement for message for AP */
|
|
KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_SOUND,
|
|
KEY_SD_INSERT
|
|
};
|
|
#endif
|
|
|
|
|
|
#ifdef CONFIG_QISDA_QD060B00
|
|
|
|
#define QISDA_E600
|
|
//#define QISDA_L600
|
|
|
|
|
|
#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_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
|
|
/* } Qisda, ShiYong Lin, 2009/09/08, Implement for message for AP */
|
|
};
|
|
#endif
|
|
|
|
|
|
#ifdef CONFIG_QISDA_QD090B00
|
|
#define MAX_KEYPAD_QISDA 25
|
|
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
|
|
/* } Qisda, ShiYong Lin, 2009/09/08, Implement for message for AP */
|
|
};
|
|
#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 */
|
|
|
|
/* 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
|
|
//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_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);
|
|
|
|
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_GPD10, S3C2410_GPD10_INP); //T_SENSOR2
|
|
s3c2410_gpio_cfgpin(S3C2410_GPD11, S3C2410_GPD11_INP); //T_SENSOR1
|
|
|
|
//Set gpio as input and pull-up enable
|
|
s3c2410_gpio_cfgpin(S3C2410_GPD14, S3C2410_GPD14_INP); // Menu
|
|
s3c2410_gpio_pullup(S3C2410_GPD14, 2);
|
|
|
|
s3c2410_gpio_cfgpin(S3C2410_GPD15, S3C2410_GPD15_INP); // Page down / Back
|
|
s3c2410_gpio_pullup(S3C2410_GPD15, 2);
|
|
|
|
s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0); // power
|
|
s3c2410_gpio_pullup(S3C2410_GPF0, 2);
|
|
|
|
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_INP); // Back / Right
|
|
s3c2410_gpio_pullup(S3C2410_GPF7, 2);
|
|
|
|
#ifdef QISDA_E600
|
|
s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_INP); // Page up
|
|
s3c2410_gpio_pullup(S3C2410_GPG4, 2);
|
|
#endif
|
|
|
|
s3c2410_gpio_cfgpin(S3C2410_GPG6, S3C2410_GPG6_INP); // VOL / Down
|
|
s3c2410_gpio_pullup(S3C2410_GPG6, 2);
|
|
|
|
s3c2410_gpio_cfgpin(S3C2410_GPG7, S3C2410_GPG7_INP); // Refresh / Left
|
|
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
|
|
|
|
s3c2410_gpio_cfgpin(S3C2410_GPH5, S3C2410_GPH5_INP); // Search / UP
|
|
s3c2410_gpio_pullup(S3C2410_GPH5, 2);
|
|
#endif
|
|
|
|
/* Qisda, ShiYong Lin, 2009/08/27, Implement for message for AP {*/
|
|
// Power_Fail, GPG5, need to open when EVT2
|
|
// Both edge triggered
|
|
s3c2410_gpio_cfgpin(S3C2410_GPG5, S3C2410_GPG5_EINT13);
|
|
s3c2410_gpio_pullup(S3C2410_GPG5, 2);
|
|
writel((readl(S3C2410_EXTINT1) & ~(1<<23)), S3C2410_EXTINT1); /* EINT13 filter enable */
|
|
writel(((readl(S3C2410_EXTINT1) & ~(7<<20))|(6<<20)), S3C2410_EXTINT1);
|
|
|
|
// CHG_STA, GPG1, need to open when EVT2,
|
|
// Both edge triggered
|
|
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);
|
|
}
|
|
|
|
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)|(0<<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<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
|
|
}
|
|
|
|
|
|
read_pin = __raw_readl(S3C_UDC_SYS_STATUS_REG)&0x60;
|
|
if(read_pin !=0x60){
|
|
|
|
// 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
|
|
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
|
|
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
|
|
//close system by letting P_KEEP low
|
|
|
|
#ifdef POWER_KEY_FOR_SYS_SHUTDOWN
|
|
s3c2410_gpio_setpin(S3C2410_GPG0, 0);
|
|
s3c2410_gpio_cfgpin(S3C2410_GPG0, S3C2410_GPG0_OUTP);
|
|
#endif
|
|
/* } Qisda, ShiYong Lin, 2009/08/27, Implementing power btn behavior */
|
|
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)
|
|
{
|
|
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);
|
|
}
|
|
else
|
|
{
|
|
input_report_key(Message_dev,KEY_F6,0);
|
|
input_sync(Message_dev);
|
|
printk("USB_SaftRemove_keypad_message_to_ap, USB_SaftRemove_keypad_message_to_ap press\n");
|
|
}
|
|
}
|
|
/*} Qisda, Leo SJ Yang, 2009/10/26*/
|
|
|
|
|
|
|
|
/* 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_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){
|
|
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{
|
|
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);
|
|
}
|
|
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;
|
|
|
|
//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
|
|
s3c_keypad_deal(dev, (read_pin & (0x1<<1)), 16); // 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
|
|
|
|
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);
|
|
s3c_keypad_deal(dev, read_pin & 1<<14, 1); // Search
|
|
s3c_keypad_deal(dev, read_pin & 1<<15, 4); // Return
|
|
|
|
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
|
|
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 4); // Back
|
|
#endif
|
|
#ifdef QISDA_L600
|
|
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 13); // Right
|
|
#endif
|
|
s3c_keypad_deal(dev, (read_pin & (0x1<<1)), 18); // 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
|
|
s3c_keypad_deal(dev, (read_pin & (0x1<<4)), 3); // Page up
|
|
s3c_keypad_deal(dev, (read_pin & (0x1<<6)), 6); // Volume
|
|
s3c_keypad_deal(dev, (read_pin & (0x1<<7)), 8); // Refresh
|
|
#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
|
|
|
|
|
|
read_pin = readl(S3C2410_GPHDAT);
|
|
#ifdef QISDA_E600
|
|
s3c_keypad_deal(dev, read_pin & 1<<5, 1); // Search
|
|
#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);
|
|
s3c_keypad_deal(dev, read_pin & 1<<14, 0); // Menu
|
|
#ifdef QISDA_E600
|
|
s3c_keypad_deal(dev, read_pin & 1<<15, 2); // Page down
|
|
#endif
|
|
#ifdef QISDA_L600
|
|
s3c_keypad_deal(dev, read_pin & 1<<15, 4); // Back
|
|
#endif
|
|
|
|
|
|
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, 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
|
|
|
|
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 */
|
|
|
|
/* 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);
|
|
|
|
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 ]
|