AndroidComputer: add rkxx remote driver
authorwlq <wlq@rock-chips.com>
Wed, 23 Oct 2013 08:11:49 +0000 (16:11 +0800)
committerwlq <wlq@rock-chips.com>
Wed, 23 Oct 2013 08:11:49 +0000 (16:11 +0800)
modified:
arch/arm/configs/rk3188_ac_defconfig
arch/arm/mach-rk3188/board-rk3188-ac.c
drivers/input/Kconfig
drivers/input/Makefile
new file:
arch/arm/mach-rk3188/include/mach/remotectl.h
drivers/input/remotectl/Kconfig
drivers/input/remotectl/Makefile
drivers/input/remotectl/rkxx_remotectl.c

arch/arm/configs/rk3188_ac_defconfig [changed mode: 0644->0755]
arch/arm/mach-rk3188/board-rk3188-ac.c
arch/arm/mach-rk3188/include/mach/remotectl.h [new file with mode: 0755]
drivers/input/Kconfig
drivers/input/Makefile
drivers/input/remotectl/Kconfig [new file with mode: 0755]
drivers/input/remotectl/Makefile [new file with mode: 0755]
drivers/input/remotectl/rkxx_remotectl.c [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index 311e55f..a0d9a46
@@ -194,7 +194,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_MISC_DEVICES=y
 CONFIG_UID_STAT=y
 CONFIG_APANIC=y
-CONFIG_AC_USB_SWITCH=y
 CONFIG_SCALER_DEVICE=y
 CONFIG_SCALER_TEST=y
 CONFIG_SCSI=y
@@ -255,6 +254,7 @@ CONFIG_GSENSOR_DEVICE=y
 CONFIG_COMPASS_DEVICE=y
 CONFIG_COMPASS_AK8963=y
 CONFIG_GYROSCOPE_DEVICE=y
+CONFIG_RK_IR_WAKEUP=y
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
@@ -310,7 +310,6 @@ CONFIG_FB_ROCKCHIP=y
 CONFIG_ONE_LCDC_DUAL_OUTPUT_INF=y
 CONFIG_LCDC_RK3188=y
 CONFIG_LCDC0_RK3188=y
-CONFIG_LCDC1_RK3188=y
 CONFIG_LCD_ANDROIDCOMPUTER=y
 CONFIG_RK_HDMI=y
 CONFIG_HDMI_CAT66121=y
@@ -397,6 +396,7 @@ CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_OPTION=y
 CONFIG_USB_SERIAL_USI=y
 CONFIG_USB_GADGET=y
+CONFIG_BYPASS_INPUT_TO_HIDG=y
 CONFIG_USB20_HOST=y
 CONFIG_USB20_OTG=y
 CONFIG_MMC=y
index cebd9e481ec07c7de8a230eaa7053c237f20b04f..297ec33415b16ff06343b0a2225c0fd3f72f8586 100755 (executable)
@@ -72,6 +72,9 @@
 #if defined(CONFIG_MT6620)
 #include <linux/gps.h>
 #endif
+#ifdef CONFIG_RK_REMOTECTL
+#include <mach/remotectl.h>
+#endif
 
 #include "../mach-rk30/board-rk3168-ds1006h-camera.c"
 #include <plat/key.h>
@@ -254,6 +257,28 @@ static struct platform_device rk29_device_backlight = {
        }
 };
 
+#endif
+#ifdef CONFIG_RK_REMOTECTL
+
+void rk30_remotectl_iomux(void)
+{
+        ;
+}
+
+struct RKxx_remotectl_platform_data rk30_remotectl_pdata = {
+    .gpio       =   RK30_PIN0_PA3,
+    .wakeup     = 1,
+    .rep    = 0,
+    .set_iomux = rk30_remotectl_iomux,
+};
+
+static struct platform_device rk30_device_remotectl = {
+        .name           = "rkxx-remotectl",
+        .id             = -1,
+        .dev            = {
+                .platform_data  = &rk30_remotectl_pdata,
+        },
+};
 #endif
 
 /*MMA8452 gsensor*/
@@ -1398,6 +1423,10 @@ static struct platform_device *devices[] __initdata = {
 #if defined(CONFIG_AC_USB_SWITCH)
        &device_ac_usb_switch,
 #endif
+#ifdef CONFIG_RK_REMOTECTL      
+    &rk30_device_remotectl,
+#endif
+
 };
 
 
@@ -2258,15 +2287,17 @@ static struct cpufreq_frequency_table dvfs_gpu_table_volt_level1[] = {
 static struct cpufreq_frequency_table dvfs_ddr_table_volt_level0[] = {
        {.frequency = 200 * 1000 + DDR_FREQ_SUSPEND,    .index = 950 * 1000},
        {.frequency = 300 * 1000 + DDR_FREQ_VIDEO,      .index = 1000 * 1000},
-       {.frequency = 396 * 1000 + DDR_FREQ_NORMAL,     .index = 1100 * 1000},
-        {.frequency = 460 * 1000 + DDR_FREQ_DUALVIEW,     .index = 1150 * 1000},
+       //{.frequency = 396 * 1000 + DDR_FREQ_NORMAL,     .index = 1100 * 1000},
+       {.frequency = 666 * 1000 + DDR_FREQ_NORMAL,     .index = 1250 * 1000},
+        {.frequency = 666 * 1000 + DDR_FREQ_DUALVIEW,     .index = 1250 * 1000},
        //{.frequency = 528 * 1000 + DDR_FREQ_NORMAL,     .index = 1200 * 1000},
        {.frequency = CPUFREQ_TABLE_END},
 };
 
 static struct cpufreq_frequency_table dvfs_ddr_table_t[] = {
        {.frequency = 200 * 1000 + DDR_FREQ_SUSPEND,    .index = 950 * 1000},
-       {.frequency = 460 * 1000 + DDR_FREQ_NORMAL,     .index = 1150 * 1000},
+       //{.frequency = 460 * 1000 + DDR_FREQ_NORMAL,     .index = 1150 * 1000},
+       {.frequency = 666 * 1000 + DDR_FREQ_NORMAL,     .index = 1250 * 1000},
        {.frequency = CPUFREQ_TABLE_END},
 };
 #define dvfs_ddr_table dvfs_ddr_table_volt_level0
diff --git a/arch/arm/mach-rk3188/include/mach/remotectl.h b/arch/arm/mach-rk3188/include/mach/remotectl.h
new file mode 100755 (executable)
index 0000000..b3605b9
--- /dev/null
@@ -0,0 +1,52 @@
+\r
+#ifndef __RKXX_REMOTECTL_H__\r
+#define __RKXX_REMOTECTL_H__\r
+#include <linux/input.h>\r
+\r
+/********************************************************************\r
+**                            ºê¶¨Òå                                *\r
+********************************************************************/\r
+#define TIME_BIT0_MIN  625  /*Bit0  1.125ms*/\r
+#define TIME_BIT0_MAX  1625\r
+\r
+#define TIME_BIT1_MIN  1700  /*Bit1  2.25ms*/\r
+#define TIME_BIT1_MAX  3000\r
+\r
+#define TIME_PRE_MIN   13000   /*4500*/\r
+#define TIME_PRE_MAX   14000   /*5500*/           /*PreLoad 4.5+0.56 = 5.06ms*/\r
+\r
+#define TIME_RPT_MIN   95000   /*101000*/\r
+#define TIME_RPT_MAX   98000   /*103000*/         /*Repeat  105-2.81=102.19ms*/  //110-9-2.25-0.56=98.19ms\r
+\r
+#define TIME_SEQ1_MIN   10000   /*2650*/\r
+#define TIME_SEQ1_MAX   12000   /*3000*/           /*sequence  2.25+0.56=2.81ms*/ //11.25ms\r
+\r
+#define TIME_SEQ2_MIN   40000   /*101000*/\r
+#define TIME_SEQ2_MAX   47000   /*103000*/         /*Repeat  105-2.81=102.19ms*/  //110-9-2.25-0.56=98.19ms\r
+\r
+/********************************************************************\r
+**                          ½á¹¹¶¨Òå                                *\r
+********************************************************************/\r
+typedef enum _RMC_STATE\r
+{\r
+    RMC_IDLE,\r
+    RMC_PRELOAD,\r
+    RMC_USERCODE,\r
+    RMC_GETDATA,\r
+    RMC_SEQUENCE\r
+}eRMC_STATE;\r
+\r
+\r
+struct RKxx_remotectl_platform_data {\r
+       //struct rkxx_remotectl_button *buttons;\r
+       int nbuttons;\r
+       int rep;\r
+       int gpio;\r
+       int active_low;\r
+       int timer;\r
+       int wakeup;\r
+       void (*set_iomux)(void);\r
+};\r
+\r
+#endif\r
+\r
index 1682dbae1bda737686f3324c568988fd7f86b9c9..6d23a32aa1f4cc9f3d38b82fb82dc247c01c65f3 100755 (executable)
@@ -198,6 +198,7 @@ source "drivers/input/lightsensor/Kconfig"
 
 source "drivers/input/sensors/Kconfig"
 
+source "drivers/input/remotectl/Kconfig"
 endif
 
 menu "Hardware I/O ports"
index 89a28d2b86236a3cf6c4787164142db8915a611e..8ebc120ba3e536b7b7199a10cb6c7a8b15ba9c16 100755 (executable)
@@ -33,3 +33,4 @@ obj-$(CONFIG_TS_AUTO) += ts/
 
 obj-$(CONFIG_INPUT_APMPOWER)   += apm-power.o
 obj-$(CONFIG_INPUT_KEYRESET)   += keyreset.o
+obj-$(CONFIG_ROCKCHIP_REMOTECTL) +=remotectl/
diff --git a/drivers/input/remotectl/Kconfig b/drivers/input/remotectl/Kconfig
new file mode 100755 (executable)
index 0000000..b52921f
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# Touchscreen driver configuration
+#
+menuconfig ROCKCHIP_REMOTECTL
+       bool "rkxx remotectl"
+       default y
+       help
+         Say Y here, will suport rk remotectl.
+         This option doesn't affect the kernel.
+         If unsure, say Y.
+         
+if ROCKCHIP_REMOTECTL  
+
+config RK_REMOTECTL
+       bool "rkxx remoctrl"
+       default y
+       
+config RK_IR_WAKEUP
+       bool "rkxx remoctrl wakeup"
+       depends on PLAT_RK
+       default n       
+endif
diff --git a/drivers/input/remotectl/Makefile b/drivers/input/remotectl/Makefile
new file mode 100755 (executable)
index 0000000..0edc158
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the touchscreen drivers.
+#
+# Each configuration option enables a list of files.
+
+
+obj-$(CONFIG_RK_REMOTECTL)      += rkxx_remotectl.o
diff --git a/drivers/input/remotectl/rkxx_remotectl.c b/drivers/input/remotectl/rkxx_remotectl.c
new file mode 100755 (executable)
index 0000000..94f6319
--- /dev/null
@@ -0,0 +1,686 @@
+\r
+/*\r
+ * Driver for keys on GPIO lines capable of generating interrupts.\r
+ *\r
+ * Copyright 2005 Phil Blundell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License version 2 as\r
+ * published by the Free Software Foundation.\r
+ */\r
+\r
+#include <linux/module.h>\r
+#include <linux/init.h>\r
+#include <linux/fs.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/irq.h>\r
+#include <linux/sched.h>\r
+#include <linux/pm.h>\r
+#include <linux/sysctl.h>\r
+#include <linux/proc_fs.h>\r
+#include <linux/delay.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/adc.h>\r
+#include <asm/gpio.h>\r
+#include <mach/remotectl.h>\r
+#include <mach/iomux.h>\r
+#include <linux/wakelock.h>\r
+#include <linux/suspend.h>\r
+\r
+\r
+#if 1\r
+#define remotectl_dbg(bdata, format, arg...)           \\r
+       dev_printk(KERN_INFO , &bdata->input->dev , format , ## arg)\r
+#else\r
+#define remotectl_dbg(bdata, format, arg...)   \r
+#endif\r
+\r
+extern suspend_state_t get_suspend_state(void);\r
+\r
+struct rkxx_remotectl_suspend_data{\r
+    int suspend_flag;\r
+    int cnt;\r
+    long scanTime[50];\r
+};\r
+\r
+struct rkxx_remote_key_table{\r
+    int scanCode;\r
+       int keyCode;            \r
+};\r
+\r
+struct rkxx_remotectl_button { \r
+    int usercode;\r
+    int nbuttons;\r
+    struct rkxx_remote_key_table *key_table;\r
+};\r
+\r
+struct rkxx_remotectl_drvdata {\r
+    int state;\r
+       int nbuttons;\r
+       int result;\r
+    unsigned long pre_time;\r
+    unsigned long cur_time;\r
+    long int pre_sec;\r
+    long int cur_sec;\r
+    long period;\r
+    int scanData;\r
+    int count;\r
+    int keybdNum;\r
+    int keycode;\r
+    int press;\r
+    int pre_press;\r
+    \r
+    struct input_dev *input;\r
+    struct timer_list timer;\r
+    struct tasklet_struct remote_tasklet;\r
+    struct wake_lock remotectl_wake_lock;\r
+    struct rkxx_remotectl_suspend_data remotectl_suspend_data;\r
+};\r
+\r
+\r
+\r
+//ÌØÊ⹦ÄܼüÖµ¶¨Òå\r
+    //193      //photo\r
+    //194      //video\r
+    //195      //music\r
+    //196      //IE\r
+    //197      //\r
+    //198\r
+    //199\r
+    //200\r
+    \r
+    //183      //rorate_left\r
+    //184      //rorate_right\r
+    //185      //zoom out\r
+    //186      //zoom in\r
+    \r
+static struct rkxx_remote_key_table remote_key_table_meiyu_202[] = {\r
+    {0xB0, KEY_ENTER},//ok = DPAD CENTER\r
+    {0xA2, KEY_BACK}, \r
+    {0xD0, KEY_UP},\r
+    {0x70, KEY_DOWN},\r
+    {0x08, KEY_LEFT},\r
+    {0x88, KEY_RIGHT},  ////////\r
+    {0x42, KEY_HOME},     //home\r
+    {0xA8, KEY_VOLUMEUP},\r
+    {0x38, KEY_VOLUMEDOWN},\r
+    {0xE2, KEY_SEARCH},     //search\r
+    {0xB2, KEY_POWER},     //power off\r
+    {0xC2, KEY_MUTE},       //mute\r
+    {0xC8, KEY_MENU},\r
+\r
+//media ctrl\r
+    {0x78,   0x190},      //play pause\r
+    {0xF8,   0x191},      //pre\r
+    {0x02,   0x192},      //next\r
+\r
+//pic\r
+    {0xB8, 183},          //rorate left\r
+    {0x58, 248},          //rorate right\r
+    {0x68, 185},          //zoom out\r
+    {0x98, 186},          //zoom in\r
+//mouse switch\r
+    {0xf0,388},\r
+//display switch\r
+    {0x82,   0x175},\r
+};\r
+\r
+static struct rkxx_remote_key_table remote_key_table_df[] = {\r
+    {0xf8, KEY_REPLY},\r
+    {0xc0, KEY_BACK}, \r
+    {0xf0, KEY_UP},\r
+    {0xd8, KEY_DOWN},\r
+    {0xd0, KEY_LEFT},\r
+    {0xe8,KEY_RIGHT},  ////////\r
+    {0x90, KEY_VOLUMEDOWN},\r
+    {0x60, KEY_VOLUMEUP},\r
+    {0x80, KEY_HOME},     //home\r
+    {0xe0, 183},          //rorate left\r
+    {0x10, 184},          //rorate right\r
+    {0x20, 185},          //zoom out\r
+    {0xa0, 186},          //zoom in\r
+    {0x70, KEY_MUTE},       //mute\r
+    {0x50, KEY_POWER},     //power off\r
+    {0x40, KEY_SEARCH},     //search\r
+};\r
+\r
+extern suspend_state_t get_suspend_state(void);\r
+\r
+\r
+static struct rkxx_remotectl_button remotectl_button[] = \r
+{\r
+    {  \r
+       .usercode = 0x206, \r
+       .nbuttons =  22, \r
+       .key_table = &remote_key_table_meiyu_202[0],\r
+    },\r
+    {\r
+       .usercode = 0x12ee,\r
+       .nbuttons =  22,\r
+       .key_table = &remote_key_table_meiyu_202[0],\r
+    },\r
+    {  \r
+       .usercode = 0x202, \r
+       .nbuttons =  22, \r
+       .key_table = &remote_key_table_meiyu_202[0],\r
+    },\r
+    {  \r
+       .usercode = 0xdf, \r
+       .nbuttons =  16, \r
+       .key_table = &remote_key_table_df[0],\r
+    },    \r
+    \r
+};\r
+\r
+\r
+static int remotectl_keybdNum_lookup(struct rkxx_remotectl_drvdata *ddata)\r
+{      \r
+    int i;     \r
+\r
+    for (i = 0; i < sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button); i++){               \r
+        if (remotectl_button[i].usercode == (ddata->scanData&0xFFFF)){                 \r
+            ddata->keybdNum = i;\r
+            return 1;\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+static int remotectl_keycode_lookup(struct rkxx_remotectl_drvdata *ddata)\r
+{      \r
+    int i;     \r
+    unsigned char keyData = ((ddata->scanData >> 8) & 0xff);\r
+\r
+    for (i = 0; i < remotectl_button[ddata->keybdNum].nbuttons; i++){\r
+        if (remotectl_button[ddata->keybdNum].key_table[i].scanCode == keyData){                       \r
+            ddata->keycode = remotectl_button[ddata->keybdNum].key_table[i].keyCode;\r
+            return 1;\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+static void remotectl_get_pwr_scanData(struct rkxx_remotectl_drvdata *ddata,int *pwr_data,int loop)\r
+{      \r
+    int i;\r
+    int temp_scanCode;\r
+    int temp_pwr_data;\r
+    \r
+    for (i = 0; i < remotectl_button[loop].nbuttons; i++){\r
+        if (remotectl_button[loop].key_table[i].keyCode == KEY_POWER){                 \r
+            temp_scanCode = remotectl_button[loop].key_table[i].scanCode;\r
+            temp_pwr_data = (temp_scanCode<<8)|((~temp_scanCode)&0xFF);\r
+            //printk("pwr data =0x%x\n",temp_pwr_data);\r
+        }\r
+    }\r
+    *pwr_data = temp_pwr_data;\r
+}\r
+\r
+static void remotectl_do_something(unsigned long  data)\r
+{\r
+    struct rkxx_remotectl_drvdata *ddata = (struct rkxx_remotectl_drvdata *)data;\r
+\r
+    switch (ddata->state)\r
+    {\r
+        case RMC_IDLE:\r
+        {\r
+            ;\r
+        }\r
+        break;\r
+        \r
+        case RMC_PRELOAD:\r
+        {\r
+            mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(130));\r
+            //printk("RMC_PRELOAD,period=%d\n",ddata->period);\r
+            if ((TIME_PRE_MIN < ddata->period) && (ddata->period < TIME_PRE_MAX)){\r
+                \r
+                ddata->scanData = 0;\r
+                ddata->count = 0;\r
+                ddata->state = RMC_USERCODE;\r
+            }else{\r
+                ddata->state = RMC_PRELOAD;\r
+            }\r
+            ddata->pre_time = ddata->cur_time;\r
+            //mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(130));\r
+        }\r
+        break;\r
+        \r
+        case RMC_USERCODE:\r
+        {\r
+            ddata->scanData <<= 1;\r
+            ddata->count ++;\r
+           printk("RMC_USERCODE,period=%d£¬count=%d\n",ddata->period,ddata->count );\r
+            if ((TIME_BIT1_MIN < ddata->period) && (ddata->period < TIME_BIT1_MAX)){\r
+                ddata->scanData |= 0x01;\r
+            }\r
+               \r
+            if (ddata->count == 0x10){//16 bit user code\r
+                printk("u=0x%x\n",((ddata->scanData)&0xFFFF));\r
+                if (remotectl_keybdNum_lookup(ddata)){\r
+                    ddata->state = RMC_GETDATA;\r
+                    ddata->scanData = 0;\r
+                    ddata->count = 0;\r
+                }else{                //user code error\r
+                    ddata->state = RMC_PRELOAD;\r
+                }\r
+            }\r
+        }\r
+        break;\r
+        \r
+        case RMC_GETDATA:\r
+        {\r
+            ddata->count ++;\r
+            ddata->scanData <<= 1;\r
+\r
+          \r
+            if ((TIME_BIT1_MIN < ddata->period) && (ddata->period < TIME_BIT1_MAX)){\r
+                ddata->scanData |= 0x01;\r
+            }           \r
+            if (ddata->count == 0x10){\r
+                //printk("RMC_GETDATA=%x\n",(ddata->scanData&0xFFFF));\r
+\r
+                if ((ddata->scanData&0x0ff) == ((~ddata->scanData >> 8)&0x0ff)){\r
+                    if (remotectl_keycode_lookup(ddata)){\r
+                        ddata->press = 1;\r
+                        /*\r
+                         if (get_suspend_state()==0){\r
+                                input_event(ddata->input, EV_KEY, ddata->keycode, 1);\r
+                                input_sync(ddata->input);\r
+                            }else if ((get_suspend_state())&&(ddata->keycode==KEY_POWER)){\r
+                                input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1);\r
+                                input_sync(ddata->input);\r
+                            }*/\r
+                            //printk("0\n");\r
+                            input_event(ddata->input, EV_KEY, ddata->keycode, 1);\r
+                            input_sync(ddata->input);\r
+                        //input_event(ddata->input, EV_KEY, ddata->keycode, ddata->press);\r
+                               //input_sync(ddata->input);\r
+                        ddata->state = RMC_SEQUENCE;\r
+                    }else{\r
+                        ddata->state = RMC_PRELOAD;\r
+                    }\r
+                }else{\r
+                    ddata->state = RMC_PRELOAD;\r
+                }\r
+            }\r
+        }\r
+        break;\r
+             \r
+        case RMC_SEQUENCE:{\r
+\r
+            //printk( "S=%d\n",ddata->period);\r
+  \r
+            if ((TIME_RPT_MIN < ddata->period) && (ddata->period < TIME_RPT_MAX)){\r
+                        mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(110));\r
+                 //printk("1\n");;\r
+            }else if ((TIME_SEQ1_MIN < ddata->period) && (ddata->period < TIME_SEQ1_MAX)){\r
+                                                                 mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(110));\r
+                                                                 //printk("2\n");\r
+            }else if ((TIME_SEQ2_MIN < ddata->period) && (ddata->period < TIME_SEQ2_MAX)){\r
+                         mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(110));\r
+                         //printk("3\n");;   \r
+            }else{\r
+                        input_event(ddata->input, EV_KEY, ddata->keycode, 0);\r
+                              input_sync(ddata->input);\r
+                        ddata->state = RMC_PRELOAD;\r
+                        ddata->press = 0;\r
+                        //printk("4\n");\r
+            }\r
+        }\r
+        break;\r
+       \r
+        default:\r
+            break;\r
+    } \r
+       return;\r
+}\r
+\r
+\r
+#ifdef CONFIG_PM\r
+void remotectl_wakeup(unsigned long _data)\r
+{\r
+    struct rkxx_remotectl_drvdata *ddata =  (struct rkxx_remotectl_drvdata*)_data;\r
+    long *time;\r
+    int i;\r
+       int power_scanData;\r
+                \r
+    time = ddata->remotectl_suspend_data.scanTime;\r
+\r
+    if (get_suspend_state()){\r
+        ddata->remotectl_suspend_data.suspend_flag = 0;\r
+        ddata->count = 0;\r
+        ddata->state = RMC_USERCODE;\r
+        ddata->scanData = 0;\r
+        \r
+        for (i=0;i<ddata->remotectl_suspend_data.cnt;i++){\r
+                       if (ddata->count>=32)\r
+                               break;\r
+\r
+           if ((TIME_BIT1_MIN < time[i]) && (time[i] < TIME_BIT1_MAX)){\r
+                ddata->scanData |= 0x01;\r
+                ddata->scanData <<= 1;\r
+                ddata->count ++;;\r
+            }else if ((TIME_BIT0_MIN < time[i]) && (time[i] < TIME_BIT0_MAX)){\r
+                 ddata->scanData <<= 1;\r
+                 ddata->count ++;;\r
+            }/*else{\r
+                  if (ddata->count>16){\r
+                         break;\r
+                  }else{\r
+                       \r
+                       printk(KERN_ERR "ddata->count=0x%x**********************\n",ddata->count);\r
+                       ddata->count = 0;\r
+                       ddata->scanData = 0;\r
+                  }            \r
+            }*/\r
+        }\r
+        //printk(KERN_ERR"data=0x%x\n",ddata->scanData);\r
+        if (ddata->scanData)                                   //(ddata->scanData>16)                  \r
+                               {\r
+                                         ddata->scanData=(ddata->scanData>>1)&0xFFFF;                          \r
+                                         printk(KERN_ERR"data=0x%x\n",ddata->scanData);\r
+                                         \r
+                                         for (i=0;i<sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button);i++){\r
+                                               remotectl_get_pwr_scanData(ddata,&power_scanData,i);\r
+                                               if ((ddata->scanData == power_scanData)||((ddata->scanData&0x0fff) == (power_scanData&0x0fff))||((ddata->scanData&0x00ff) == (power_scanData&0x00ff)))                                  //modified by zwm       2013.06.19\r
+                                           {\r
+                                               input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1);\r
+                       input_sync(ddata->input);\r
+                       input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0);\r
+                       input_sync(ddata->input);\r
+                       break;\r
+                                           }\r
+                                         }\r
+                               }\r
+    }\r
+    memset(ddata->remotectl_suspend_data.scanTime,0,50*sizeof(long));\r
+    ddata->remotectl_suspend_data.cnt= 0; \r
+    ddata->state = RMC_PRELOAD;\r
+    \r
+}\r
+\r
+#endif\r
+\r
+\r
+static void remotectl_timer(unsigned long _data)\r
+{\r
+    struct rkxx_remotectl_drvdata *ddata =  (struct rkxx_remotectl_drvdata*)_data;\r
+    \r
+    //printk("to\n");\r
+    \r
+    if(ddata->press != ddata->pre_press) {\r
+        ddata->pre_press = ddata->press = 0;\r
+        \r
+                               input_event(ddata->input, EV_KEY, ddata->keycode, 0);\r
+        input_sync(ddata->input);\r
+        //printk("5\n");\r
+        //if (get_suspend_state()==0){\r
+            //input_event(ddata->input, EV_KEY, ddata->keycode, 1);\r
+            //input_sync(ddata->input);\r
+            //input_event(ddata->input, EV_KEY, ddata->keycode, 0);\r
+                   //input_sync(ddata->input);\r
+        //}else if ((get_suspend_state())&&(ddata->keycode==KEY_POWER)){\r
+            //input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1);\r
+            //input_sync(ddata->input);\r
+            //input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0);\r
+            //input_sync(ddata->input);\r
+        //}\r
+    }\r
+#ifdef CONFIG_PM\r
+    remotectl_wakeup(_data);\r
+#endif\r
+    ddata->state = RMC_PRELOAD;\r
+}\r
+\r
+\r
+\r
+static irqreturn_t remotectl_isr(int irq, void *dev_id)\r
+{\r
+    struct rkxx_remotectl_drvdata *ddata =  (struct rkxx_remotectl_drvdata*)dev_id;\r
+    struct timeval  ts;\r
+\r
+\r
+    ddata->pre_time = ddata->cur_time;\r
+    ddata->pre_sec = ddata->cur_sec;\r
+    do_gettimeofday(&ts);\r
+    ddata->cur_time = ts.tv_usec;\r
+    ddata->cur_sec = ts.tv_sec;\r
+    \r
+               if (likely(ddata->cur_sec == ddata->pre_sec)){\r
+                       ddata->period =  ddata->cur_time - ddata->pre_time;\r
+         }else{\r
+                               ddata->period =  1000000 - ddata->pre_time + ddata->cur_time;\r
+               }\r
+\r
+    tasklet_hi_schedule(&ddata->remote_tasklet); \r
+    //if ((ddata->state==RMC_PRELOAD)||(ddata->state==RMC_SEQUENCE))\r
+    //mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(130));\r
+#ifdef CONFIG_PM\r
+   if (ddata->state==RMC_PRELOAD)\r
+       wake_lock_timeout(&ddata->remotectl_wake_lock, HZ);\r
+   if ((get_suspend_state())&&(ddata->remotectl_suspend_data.cnt<50))          //zwm\r
+       ddata->remotectl_suspend_data.scanTime[ddata->remotectl_suspend_data.cnt++] = ddata->period;\r
+#endif\r
+\r
+    return IRQ_HANDLED;\r
+}\r
+\r
+\r
+static int __devinit remotectl_probe(struct platform_device *pdev)\r
+{\r
+    struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data;\r
+    struct rkxx_remotectl_drvdata *ddata;\r
+    struct input_dev *input;\r
+    int i, j;\r
+    int irq;\r
+    int error = 0;\r
+\r
+    printk("++++++++remotectl_probe\n");\r
+\r
+    if(!pdata) \r
+        return -EINVAL;\r
+\r
+    ddata = kzalloc(sizeof(struct rkxx_remotectl_drvdata),GFP_KERNEL);\r
+    memset(ddata,0,sizeof(struct rkxx_remotectl_drvdata));\r
+\r
+    ddata->state = RMC_PRELOAD;\r
+    input = input_allocate_device();\r
+    \r
+    if (!ddata || !input) {\r
+        error = -ENOMEM;\r
+        goto fail0;\r
+    }\r
+\r
+    platform_set_drvdata(pdev, ddata);\r
+\r
+    input->name = pdev->name;\r
+    input->phys = "gpio-keys/input0";\r
+    input->dev.parent = &pdev->dev;\r
+\r
+    input->id.bustype = BUS_HOST;\r
+    input->id.vendor = 0x0001;\r
+    input->id.product = 0x0001;\r
+    input->id.version = 0x0100;\r
+\r
+       /* Enable auto repeat feature of Linux input subsystem */\r
+       if (pdata->rep)\r
+               __set_bit(EV_REP, input->evbit);\r
+    \r
+       ddata->nbuttons = pdata->nbuttons;\r
+       ddata->input = input;\r
+  wake_lock_init(&ddata->remotectl_wake_lock, WAKE_LOCK_SUSPEND, "rk29_remote");\r
+  if (pdata->set_iomux){\r
+       pdata->set_iomux();\r
+  }\r
+  error = gpio_request(pdata->gpio, "remotectl");\r
+       if (error < 0) {\r
+               printk("gpio-keys: failed to request GPIO %d,"\r
+               " error %d\n", pdata->gpio, error);\r
+               //goto fail1;\r
+       }\r
+       error = gpio_direction_input(pdata->gpio);\r
+       if (error < 0) {\r
+               pr_err("gpio-keys: failed to configure input"\r
+                       " direction for GPIO %d, error %d\n",\r
+               pdata->gpio, error);\r
+               gpio_free(pdata->gpio);\r
+               //goto fail1;\r
+       }\r
+    irq = gpio_to_irq(pdata->gpio);\r
+       if (irq < 0) {\r
+               error = irq;\r
+               pr_err("gpio-keys: Unable to get irq number for GPIO %d, error %d\n",\r
+               pdata->gpio, error);\r
+               gpio_free(pdata->gpio);\r
+               goto fail1;\r
+       }\r
+       \r
+       error = request_irq(irq, remotectl_isr, IRQF_TRIGGER_FALLING , "remotectl", ddata);\r
+       \r
+       if (error) {\r
+               pr_err("gpio-remotectl: Unable to claim irq %d; error %d\n", irq, error);\r
+               gpio_free(pdata->gpio);\r
+               goto fail1;\r
+       }\r
+    setup_timer(&ddata->timer,remotectl_timer, (unsigned long)ddata);\r
+    \r
+    tasklet_init(&ddata->remote_tasklet, remotectl_do_something, (unsigned long)ddata);\r
+    \r
+    for (j=0;j<sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button);j++){ \r
+       printk("remotectl probe j=0x%x\n",j);\r
+               for (i = 0; i < remotectl_button[j].nbuttons; i++) {\r
+                       unsigned int type = EV_KEY;\r
+               \r
+                       input_set_capability(input, type, remotectl_button[j].key_table[i].keyCode);\r
+               }\r
+  }\r
+       error = input_register_device(input);\r
+       if (error) {\r
+               pr_err("gpio-keys: Unable to register input device, error: %d\n", error);\r
+               goto fail2;\r
+       }\r
+    \r
+    input_set_capability(input, EV_KEY, KEY_WAKEUP);\r
+\r
+       device_init_wakeup(&pdev->dev, 1);\r
+\r
+       return 0;\r
+\r
+fail2:\r
+    pr_err("gpio-remotectl input_allocate_device fail\n");\r
+       input_free_device(input);\r
+       kfree(ddata);\r
+fail1:\r
+    pr_err("gpio-remotectl gpio irq request fail\n");\r
+    free_irq(gpio_to_irq(pdata->gpio), ddata);\r
+    del_timer_sync(&ddata->timer);\r
+    tasklet_kill(&ddata->remote_tasklet); \r
+    gpio_free(pdata->gpio);\r
+fail0: \r
+    pr_err("gpio-remotectl input_register_device fail\n");\r
+    platform_set_drvdata(pdev, NULL);\r
+\r
+       return error;\r
+}\r
+\r
+static int __devexit remotectl_remove(struct platform_device *pdev)\r
+{\r
+       struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data;\r
+       struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev);\r
+       struct input_dev *input = ddata->input;\r
+    int irq;\r
+\r
+       device_init_wakeup(&pdev->dev, 0);\r
+    irq = gpio_to_irq(pdata->gpio);\r
+    free_irq(irq, ddata);\r
+    tasklet_kill(&ddata->remote_tasklet); \r
+    gpio_free(pdata->gpio);\r
+\r
+       input_unregister_device(input);\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+#ifdef CONFIG_PM\r
+static int remotectl_suspend(struct device *dev)\r
+{\r
+       struct platform_device *pdev = to_platform_device(dev);\r
+       struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data;\r
+    struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev);\r
+    \r
+    //ddata->remotectl_suspend_data.suspend_flag = 1;\r
+    ddata->remotectl_suspend_data.cnt = 0;\r
+\r
+       if (device_may_wakeup(&pdev->dev)) {\r
+               if (pdata->wakeup) {\r
+                       int irq = gpio_to_irq(pdata->gpio);\r
+                       enable_irq_wake(irq);\r
+               }\r
+       }\r
+    \r
+       return 0;\r
+}\r
+\r
+static int remotectl_resume(struct device *dev)\r
+{\r
+       struct platform_device *pdev = to_platform_device(dev);\r
+       struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data;\r
+\r
+    if (device_may_wakeup(&pdev->dev)) {\r
+        if (pdata->wakeup) {\r
+            int irq = gpio_to_irq(pdata->gpio);\r
+            disable_irq_wake(irq);\r
+        }\r
+    }\r
+\r
+       return 0;\r
+}\r
+\r
+static const struct dev_pm_ops remotectl_pm_ops = {\r
+       .suspend        = remotectl_suspend,\r
+       .resume         = remotectl_resume,\r
+};\r
+#endif\r
+\r
+\r
+\r
+static struct platform_driver remotectl_device_driver = {\r
+       .probe          = remotectl_probe,\r
+       .remove         = __devexit_p(remotectl_remove),\r
+       .driver         = {\r
+               .name   = "rkxx-remotectl",\r
+               .owner  = THIS_MODULE,\r
+#ifdef CONFIG_PM\r
+           .pm = &remotectl_pm_ops,\r
+#endif\r
+       },\r
+\r
+};\r
+\r
+static int  remotectl_init(void)\r
+{\r
+    printk(KERN_INFO "++++++++remotectl_init\n");\r
+    return platform_driver_register(&remotectl_device_driver);\r
+}\r
+\r
+\r
+static void  remotectl_exit(void)\r
+{\r
+       platform_driver_unregister(&remotectl_device_driver);\r
+    printk(KERN_INFO "++++++++remotectl_init\n");\r
+}\r
+\r
+module_init(remotectl_init);\r
+module_exit(remotectl_exit);\r
+\r
+MODULE_LICENSE("GPL");\r
+MODULE_AUTHOR("rockchip");\r
+MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");\r
+MODULE_ALIAS("platform:gpio-keys1");\r
+\r
+\r