--- /dev/null
+\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