From 6e7e238d420f23deb548a4a035e63854b50dc884 Mon Sep 17 00:00:00 2001 From: wlq Date: Wed, 23 Oct 2013 16:11:49 +0800 Subject: [PATCH] AndroidComputer: add rkxx remote driver 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 | 4 +- arch/arm/mach-rk3188/board-rk3188-ac.c | 37 +- arch/arm/mach-rk3188/include/mach/remotectl.h | 52 ++ drivers/input/Kconfig | 1 + drivers/input/Makefile | 1 + drivers/input/remotectl/Kconfig | 22 + drivers/input/remotectl/Makefile | 7 + drivers/input/remotectl/rkxx_remotectl.c | 686 ++++++++++++++++++ 8 files changed, 805 insertions(+), 5 deletions(-) mode change 100644 => 100755 arch/arm/configs/rk3188_ac_defconfig create mode 100755 arch/arm/mach-rk3188/include/mach/remotectl.h create mode 100755 drivers/input/remotectl/Kconfig create mode 100755 drivers/input/remotectl/Makefile create mode 100755 drivers/input/remotectl/rkxx_remotectl.c diff --git a/arch/arm/configs/rk3188_ac_defconfig b/arch/arm/configs/rk3188_ac_defconfig old mode 100644 new mode 100755 index 311e55f709a7..a0d9a46d887b --- a/arch/arm/configs/rk3188_ac_defconfig +++ b/arch/arm/configs/rk3188_ac_defconfig @@ -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 diff --git a/arch/arm/mach-rk3188/board-rk3188-ac.c b/arch/arm/mach-rk3188/board-rk3188-ac.c index cebd9e481ec0..297ec33415b1 100755 --- a/arch/arm/mach-rk3188/board-rk3188-ac.c +++ b/arch/arm/mach-rk3188/board-rk3188-ac.c @@ -72,6 +72,9 @@ #if defined(CONFIG_MT6620) #include #endif +#ifdef CONFIG_RK_REMOTECTL +#include +#endif #include "../mach-rk30/board-rk3168-ds1006h-camera.c" #include @@ -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 index 000000000000..b3605b9cefa2 --- /dev/null +++ b/arch/arm/mach-rk3188/include/mach/remotectl.h @@ -0,0 +1,52 @@ + +#ifndef __RKXX_REMOTECTL_H__ +#define __RKXX_REMOTECTL_H__ +#include + +/******************************************************************** +** ºê¶¨Òå * +********************************************************************/ +#define TIME_BIT0_MIN 625 /*Bit0 1.125ms*/ +#define TIME_BIT0_MAX 1625 + +#define TIME_BIT1_MIN 1700 /*Bit1 2.25ms*/ +#define TIME_BIT1_MAX 3000 + +#define TIME_PRE_MIN 13000 /*4500*/ +#define TIME_PRE_MAX 14000 /*5500*/ /*PreLoad 4.5+0.56 = 5.06ms*/ + +#define TIME_RPT_MIN 95000 /*101000*/ +#define TIME_RPT_MAX 98000 /*103000*/ /*Repeat 105-2.81=102.19ms*/ //110-9-2.25-0.56=98.19ms + +#define TIME_SEQ1_MIN 10000 /*2650*/ +#define TIME_SEQ1_MAX 12000 /*3000*/ /*sequence 2.25+0.56=2.81ms*/ //11.25ms + +#define TIME_SEQ2_MIN 40000 /*101000*/ +#define TIME_SEQ2_MAX 47000 /*103000*/ /*Repeat 105-2.81=102.19ms*/ //110-9-2.25-0.56=98.19ms + +/******************************************************************** +** ½á¹¹¶¨Òå * +********************************************************************/ +typedef enum _RMC_STATE +{ + RMC_IDLE, + RMC_PRELOAD, + RMC_USERCODE, + RMC_GETDATA, + RMC_SEQUENCE +}eRMC_STATE; + + +struct RKxx_remotectl_platform_data { + //struct rkxx_remotectl_button *buttons; + int nbuttons; + int rep; + int gpio; + int active_low; + int timer; + int wakeup; + void (*set_iomux)(void); +}; + +#endif + diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 1682dbae1bda..6d23a32aa1f4 100755 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -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" diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 89a28d2b8623..8ebc120ba3e5 100755 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -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 index 000000000000..b52921fc4b33 --- /dev/null +++ b/drivers/input/remotectl/Kconfig @@ -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 index 000000000000..0edc158f05c2 --- /dev/null +++ b/drivers/input/remotectl/Makefile @@ -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 index 000000000000..94f631952d17 --- /dev/null +++ b/drivers/input/remotectl/rkxx_remotectl.c @@ -0,0 +1,686 @@ + +/* + * Driver for keys on GPIO lines capable of generating interrupts. + * + * Copyright 2005 Phil Blundell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if 1 +#define remotectl_dbg(bdata, format, arg...) \ + dev_printk(KERN_INFO , &bdata->input->dev , format , ## arg) +#else +#define remotectl_dbg(bdata, format, arg...) +#endif + +extern suspend_state_t get_suspend_state(void); + +struct rkxx_remotectl_suspend_data{ + int suspend_flag; + int cnt; + long scanTime[50]; +}; + +struct rkxx_remote_key_table{ + int scanCode; + int keyCode; +}; + +struct rkxx_remotectl_button { + int usercode; + int nbuttons; + struct rkxx_remote_key_table *key_table; +}; + +struct rkxx_remotectl_drvdata { + int state; + int nbuttons; + int result; + unsigned long pre_time; + unsigned long cur_time; + long int pre_sec; + long int cur_sec; + long period; + int scanData; + int count; + int keybdNum; + int keycode; + int press; + int pre_press; + + struct input_dev *input; + struct timer_list timer; + struct tasklet_struct remote_tasklet; + struct wake_lock remotectl_wake_lock; + struct rkxx_remotectl_suspend_data remotectl_suspend_data; +}; + + + +//ÌØÊ⹦ÄܼüÖµ¶¨Òå + //193 //photo + //194 //video + //195 //music + //196 //IE + //197 // + //198 + //199 + //200 + + //183 //rorate_left + //184 //rorate_right + //185 //zoom out + //186 //zoom in + +static struct rkxx_remote_key_table remote_key_table_meiyu_202[] = { + {0xB0, KEY_ENTER},//ok = DPAD CENTER + {0xA2, KEY_BACK}, + {0xD0, KEY_UP}, + {0x70, KEY_DOWN}, + {0x08, KEY_LEFT}, + {0x88, KEY_RIGHT}, //////// + {0x42, KEY_HOME}, //home + {0xA8, KEY_VOLUMEUP}, + {0x38, KEY_VOLUMEDOWN}, + {0xE2, KEY_SEARCH}, //search + {0xB2, KEY_POWER}, //power off + {0xC2, KEY_MUTE}, //mute + {0xC8, KEY_MENU}, + +//media ctrl + {0x78, 0x190}, //play pause + {0xF8, 0x191}, //pre + {0x02, 0x192}, //next + +//pic + {0xB8, 183}, //rorate left + {0x58, 248}, //rorate right + {0x68, 185}, //zoom out + {0x98, 186}, //zoom in +//mouse switch + {0xf0,388}, +//display switch + {0x82, 0x175}, +}; + +static struct rkxx_remote_key_table remote_key_table_df[] = { + {0xf8, KEY_REPLY}, + {0xc0, KEY_BACK}, + {0xf0, KEY_UP}, + {0xd8, KEY_DOWN}, + {0xd0, KEY_LEFT}, + {0xe8,KEY_RIGHT}, //////// + {0x90, KEY_VOLUMEDOWN}, + {0x60, KEY_VOLUMEUP}, + {0x80, KEY_HOME}, //home + {0xe0, 183}, //rorate left + {0x10, 184}, //rorate right + {0x20, 185}, //zoom out + {0xa0, 186}, //zoom in + {0x70, KEY_MUTE}, //mute + {0x50, KEY_POWER}, //power off + {0x40, KEY_SEARCH}, //search +}; + +extern suspend_state_t get_suspend_state(void); + + +static struct rkxx_remotectl_button remotectl_button[] = +{ + { + .usercode = 0x206, + .nbuttons = 22, + .key_table = &remote_key_table_meiyu_202[0], + }, + { + .usercode = 0x12ee, + .nbuttons = 22, + .key_table = &remote_key_table_meiyu_202[0], + }, + { + .usercode = 0x202, + .nbuttons = 22, + .key_table = &remote_key_table_meiyu_202[0], + }, + { + .usercode = 0xdf, + .nbuttons = 16, + .key_table = &remote_key_table_df[0], + }, + +}; + + +static int remotectl_keybdNum_lookup(struct rkxx_remotectl_drvdata *ddata) +{ + int i; + + for (i = 0; i < sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button); i++){ + if (remotectl_button[i].usercode == (ddata->scanData&0xFFFF)){ + ddata->keybdNum = i; + return 1; + } + } + return 0; +} + + +static int remotectl_keycode_lookup(struct rkxx_remotectl_drvdata *ddata) +{ + int i; + unsigned char keyData = ((ddata->scanData >> 8) & 0xff); + + for (i = 0; i < remotectl_button[ddata->keybdNum].nbuttons; i++){ + if (remotectl_button[ddata->keybdNum].key_table[i].scanCode == keyData){ + ddata->keycode = remotectl_button[ddata->keybdNum].key_table[i].keyCode; + return 1; + } + } + return 0; +} + + +static void remotectl_get_pwr_scanData(struct rkxx_remotectl_drvdata *ddata,int *pwr_data,int loop) +{ + int i; + int temp_scanCode; + int temp_pwr_data; + + for (i = 0; i < remotectl_button[loop].nbuttons; i++){ + if (remotectl_button[loop].key_table[i].keyCode == KEY_POWER){ + temp_scanCode = remotectl_button[loop].key_table[i].scanCode; + temp_pwr_data = (temp_scanCode<<8)|((~temp_scanCode)&0xFF); + //printk("pwr data =0x%x\n",temp_pwr_data); + } + } + *pwr_data = temp_pwr_data; +} + +static void remotectl_do_something(unsigned long data) +{ + struct rkxx_remotectl_drvdata *ddata = (struct rkxx_remotectl_drvdata *)data; + + switch (ddata->state) + { + case RMC_IDLE: + { + ; + } + break; + + case RMC_PRELOAD: + { + mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(130)); + //printk("RMC_PRELOAD,period=%d\n",ddata->period); + if ((TIME_PRE_MIN < ddata->period) && (ddata->period < TIME_PRE_MAX)){ + + ddata->scanData = 0; + ddata->count = 0; + ddata->state = RMC_USERCODE; + }else{ + ddata->state = RMC_PRELOAD; + } + ddata->pre_time = ddata->cur_time; + //mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(130)); + } + break; + + case RMC_USERCODE: + { + ddata->scanData <<= 1; + ddata->count ++; + printk("RMC_USERCODE,period=%d£¬count=%d\n",ddata->period,ddata->count ); + if ((TIME_BIT1_MIN < ddata->period) && (ddata->period < TIME_BIT1_MAX)){ + ddata->scanData |= 0x01; + } + + if (ddata->count == 0x10){//16 bit user code + printk("u=0x%x\n",((ddata->scanData)&0xFFFF)); + if (remotectl_keybdNum_lookup(ddata)){ + ddata->state = RMC_GETDATA; + ddata->scanData = 0; + ddata->count = 0; + }else{ //user code error + ddata->state = RMC_PRELOAD; + } + } + } + break; + + case RMC_GETDATA: + { + ddata->count ++; + ddata->scanData <<= 1; + + + if ((TIME_BIT1_MIN < ddata->period) && (ddata->period < TIME_BIT1_MAX)){ + ddata->scanData |= 0x01; + } + if (ddata->count == 0x10){ + //printk("RMC_GETDATA=%x\n",(ddata->scanData&0xFFFF)); + + if ((ddata->scanData&0x0ff) == ((~ddata->scanData >> 8)&0x0ff)){ + if (remotectl_keycode_lookup(ddata)){ + ddata->press = 1; + /* + if (get_suspend_state()==0){ + input_event(ddata->input, EV_KEY, ddata->keycode, 1); + input_sync(ddata->input); + }else if ((get_suspend_state())&&(ddata->keycode==KEY_POWER)){ + input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1); + input_sync(ddata->input); + }*/ + //printk("0\n"); + input_event(ddata->input, EV_KEY, ddata->keycode, 1); + input_sync(ddata->input); + //input_event(ddata->input, EV_KEY, ddata->keycode, ddata->press); + //input_sync(ddata->input); + ddata->state = RMC_SEQUENCE; + }else{ + ddata->state = RMC_PRELOAD; + } + }else{ + ddata->state = RMC_PRELOAD; + } + } + } + break; + + case RMC_SEQUENCE:{ + + //printk( "S=%d\n",ddata->period); + + if ((TIME_RPT_MIN < ddata->period) && (ddata->period < TIME_RPT_MAX)){ + mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(110)); + //printk("1\n");; + }else if ((TIME_SEQ1_MIN < ddata->period) && (ddata->period < TIME_SEQ1_MAX)){ + mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(110)); + //printk("2\n"); + }else if ((TIME_SEQ2_MIN < ddata->period) && (ddata->period < TIME_SEQ2_MAX)){ + mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(110)); + //printk("3\n");; + }else{ + input_event(ddata->input, EV_KEY, ddata->keycode, 0); + input_sync(ddata->input); + ddata->state = RMC_PRELOAD; + ddata->press = 0; + //printk("4\n"); + } + } + break; + + default: + break; + } + return; +} + + +#ifdef CONFIG_PM +void remotectl_wakeup(unsigned long _data) +{ + struct rkxx_remotectl_drvdata *ddata = (struct rkxx_remotectl_drvdata*)_data; + long *time; + int i; + int power_scanData; + + time = ddata->remotectl_suspend_data.scanTime; + + if (get_suspend_state()){ + ddata->remotectl_suspend_data.suspend_flag = 0; + ddata->count = 0; + ddata->state = RMC_USERCODE; + ddata->scanData = 0; + + for (i=0;iremotectl_suspend_data.cnt;i++){ + if (ddata->count>=32) + break; + + if ((TIME_BIT1_MIN < time[i]) && (time[i] < TIME_BIT1_MAX)){ + ddata->scanData |= 0x01; + ddata->scanData <<= 1; + ddata->count ++;; + }else if ((TIME_BIT0_MIN < time[i]) && (time[i] < TIME_BIT0_MAX)){ + ddata->scanData <<= 1; + ddata->count ++;; + }/*else{ + if (ddata->count>16){ + break; + }else{ + + printk(KERN_ERR "ddata->count=0x%x**********************\n",ddata->count); + ddata->count = 0; + ddata->scanData = 0; + } + }*/ + } + //printk(KERN_ERR"data=0x%x\n",ddata->scanData); + if (ddata->scanData) //(ddata->scanData>16) + { + ddata->scanData=(ddata->scanData>>1)&0xFFFF; + printk(KERN_ERR"data=0x%x\n",ddata->scanData); + + for (i=0;iscanData == power_scanData)||((ddata->scanData&0x0fff) == (power_scanData&0x0fff))||((ddata->scanData&0x00ff) == (power_scanData&0x00ff))) //modified by zwm 2013.06.19 + { + input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1); + input_sync(ddata->input); + input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0); + input_sync(ddata->input); + break; + } + } + } + } + memset(ddata->remotectl_suspend_data.scanTime,0,50*sizeof(long)); + ddata->remotectl_suspend_data.cnt= 0; + ddata->state = RMC_PRELOAD; + +} + +#endif + + +static void remotectl_timer(unsigned long _data) +{ + struct rkxx_remotectl_drvdata *ddata = (struct rkxx_remotectl_drvdata*)_data; + + //printk("to\n"); + + if(ddata->press != ddata->pre_press) { + ddata->pre_press = ddata->press = 0; + + input_event(ddata->input, EV_KEY, ddata->keycode, 0); + input_sync(ddata->input); + //printk("5\n"); + //if (get_suspend_state()==0){ + //input_event(ddata->input, EV_KEY, ddata->keycode, 1); + //input_sync(ddata->input); + //input_event(ddata->input, EV_KEY, ddata->keycode, 0); + //input_sync(ddata->input); + //}else if ((get_suspend_state())&&(ddata->keycode==KEY_POWER)){ + //input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1); + //input_sync(ddata->input); + //input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0); + //input_sync(ddata->input); + //} + } +#ifdef CONFIG_PM + remotectl_wakeup(_data); +#endif + ddata->state = RMC_PRELOAD; +} + + + +static irqreturn_t remotectl_isr(int irq, void *dev_id) +{ + struct rkxx_remotectl_drvdata *ddata = (struct rkxx_remotectl_drvdata*)dev_id; + struct timeval ts; + + + ddata->pre_time = ddata->cur_time; + ddata->pre_sec = ddata->cur_sec; + do_gettimeofday(&ts); + ddata->cur_time = ts.tv_usec; + ddata->cur_sec = ts.tv_sec; + + if (likely(ddata->cur_sec == ddata->pre_sec)){ + ddata->period = ddata->cur_time - ddata->pre_time; + }else{ + ddata->period = 1000000 - ddata->pre_time + ddata->cur_time; + } + + tasklet_hi_schedule(&ddata->remote_tasklet); + //if ((ddata->state==RMC_PRELOAD)||(ddata->state==RMC_SEQUENCE)) + //mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(130)); +#ifdef CONFIG_PM + if (ddata->state==RMC_PRELOAD) + wake_lock_timeout(&ddata->remotectl_wake_lock, HZ); + if ((get_suspend_state())&&(ddata->remotectl_suspend_data.cnt<50)) //zwm + ddata->remotectl_suspend_data.scanTime[ddata->remotectl_suspend_data.cnt++] = ddata->period; +#endif + + return IRQ_HANDLED; +} + + +static int __devinit remotectl_probe(struct platform_device *pdev) +{ + struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data; + struct rkxx_remotectl_drvdata *ddata; + struct input_dev *input; + int i, j; + int irq; + int error = 0; + + printk("++++++++remotectl_probe\n"); + + if(!pdata) + return -EINVAL; + + ddata = kzalloc(sizeof(struct rkxx_remotectl_drvdata),GFP_KERNEL); + memset(ddata,0,sizeof(struct rkxx_remotectl_drvdata)); + + ddata->state = RMC_PRELOAD; + input = input_allocate_device(); + + if (!ddata || !input) { + error = -ENOMEM; + goto fail0; + } + + platform_set_drvdata(pdev, ddata); + + input->name = pdev->name; + input->phys = "gpio-keys/input0"; + input->dev.parent = &pdev->dev; + + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; + input->id.product = 0x0001; + input->id.version = 0x0100; + + /* Enable auto repeat feature of Linux input subsystem */ + if (pdata->rep) + __set_bit(EV_REP, input->evbit); + + ddata->nbuttons = pdata->nbuttons; + ddata->input = input; + wake_lock_init(&ddata->remotectl_wake_lock, WAKE_LOCK_SUSPEND, "rk29_remote"); + if (pdata->set_iomux){ + pdata->set_iomux(); + } + error = gpio_request(pdata->gpio, "remotectl"); + if (error < 0) { + printk("gpio-keys: failed to request GPIO %d," + " error %d\n", pdata->gpio, error); + //goto fail1; + } + error = gpio_direction_input(pdata->gpio); + if (error < 0) { + pr_err("gpio-keys: failed to configure input" + " direction for GPIO %d, error %d\n", + pdata->gpio, error); + gpio_free(pdata->gpio); + //goto fail1; + } + irq = gpio_to_irq(pdata->gpio); + if (irq < 0) { + error = irq; + pr_err("gpio-keys: Unable to get irq number for GPIO %d, error %d\n", + pdata->gpio, error); + gpio_free(pdata->gpio); + goto fail1; + } + + error = request_irq(irq, remotectl_isr, IRQF_TRIGGER_FALLING , "remotectl", ddata); + + if (error) { + pr_err("gpio-remotectl: Unable to claim irq %d; error %d\n", irq, error); + gpio_free(pdata->gpio); + goto fail1; + } + setup_timer(&ddata->timer,remotectl_timer, (unsigned long)ddata); + + tasklet_init(&ddata->remote_tasklet, remotectl_do_something, (unsigned long)ddata); + + for (j=0;jdev, 1); + + return 0; + +fail2: + pr_err("gpio-remotectl input_allocate_device fail\n"); + input_free_device(input); + kfree(ddata); +fail1: + pr_err("gpio-remotectl gpio irq request fail\n"); + free_irq(gpio_to_irq(pdata->gpio), ddata); + del_timer_sync(&ddata->timer); + tasklet_kill(&ddata->remote_tasklet); + gpio_free(pdata->gpio); +fail0: + pr_err("gpio-remotectl input_register_device fail\n"); + platform_set_drvdata(pdev, NULL); + + return error; +} + +static int __devexit remotectl_remove(struct platform_device *pdev) +{ + struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data; + struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); + struct input_dev *input = ddata->input; + int irq; + + device_init_wakeup(&pdev->dev, 0); + irq = gpio_to_irq(pdata->gpio); + free_irq(irq, ddata); + tasklet_kill(&ddata->remote_tasklet); + gpio_free(pdata->gpio); + + input_unregister_device(input); + + return 0; +} + + +#ifdef CONFIG_PM +static int remotectl_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data; + struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); + + //ddata->remotectl_suspend_data.suspend_flag = 1; + ddata->remotectl_suspend_data.cnt = 0; + + if (device_may_wakeup(&pdev->dev)) { + if (pdata->wakeup) { + int irq = gpio_to_irq(pdata->gpio); + enable_irq_wake(irq); + } + } + + return 0; +} + +static int remotectl_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data; + + if (device_may_wakeup(&pdev->dev)) { + if (pdata->wakeup) { + int irq = gpio_to_irq(pdata->gpio); + disable_irq_wake(irq); + } + } + + return 0; +} + +static const struct dev_pm_ops remotectl_pm_ops = { + .suspend = remotectl_suspend, + .resume = remotectl_resume, +}; +#endif + + + +static struct platform_driver remotectl_device_driver = { + .probe = remotectl_probe, + .remove = __devexit_p(remotectl_remove), + .driver = { + .name = "rkxx-remotectl", + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &remotectl_pm_ops, +#endif + }, + +}; + +static int remotectl_init(void) +{ + printk(KERN_INFO "++++++++remotectl_init\n"); + return platform_driver_register(&remotectl_device_driver); +} + + +static void remotectl_exit(void) +{ + platform_driver_unregister(&remotectl_device_driver); + printk(KERN_INFO "++++++++remotectl_init\n"); +} + +module_init(remotectl_init); +module_exit(remotectl_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); +MODULE_ALIAS("platform:gpio-keys1"); + + -- 2.34.1