adapt all kind of board
[firefly-linux-kernel-4.4.55.git] / drivers / input / keyboard / rk2818_adckey.c
old mode 100644 (file)
new mode 100755 (executable)
index 6d4d0cd..8c35be8
@@ -25,6 +25,7 @@
 #include <asm/mach/map.h>
 #include <mach/gpio.h>
 #include <mach/adc.h>
+#include <mach/board.h>
 
 #if 0
 #define DBG(x...)   printk(x)
 #define DBG(x...)
 #endif
 
-//ROCKCHIP AD KEY CODE ,for demo board
-//      key            --->    EV      
-#define AD2KEY1                 114   ///VOLUME_DOWN
-#define AD2KEY2                 115   ///VOLUME_UP
-#define AD2KEY3                 59    ///MENU
-#define AD2KEY4                 102   ///HOME
-#define AD2KEY5                 158   ///BACK
-#define AD2KEY6                 61    ///CALL
-
-#define        KEYSTART                28                      //ENTER
-#define KEYMENU                        AD2KEY6         ///CALL
-#define KEY_PLAYON_PIN RK2818_PIN_PE1
-#define ENDCALL                        62
-
-#define Valuedrift             50
-#define ADEmpty                        1000
-#define ADInvalid              20
-#define ADKEYNUM               10
-
-#define ADKEYCH                        1       //ADͨµÀ
-
 #define KEY_PHYS_NAME  "rk2818_adckey/input0"
 
 volatile int gADSampleTimes = 0;
 volatile int gStatePlaykey = 0;
-
 volatile unsigned int gCodeCount = 0;
 volatile unsigned int gThisCode = 0;
 volatile unsigned int gLastCode = 0;
-
-//ADC Registers
-typedef  struct tagADC_keyst
-{
-       unsigned int adc_value;
-       unsigned int adc_keycode;
-}ADC_keyst,*pADC_keyst;
-
-//     adc      ---> key       
-static  ADC_keyst gAdcValueTab[] = 
-{
-       {95,  AD2KEY1},
-       {249, AD2KEY2},
-       {406, AD2KEY3},
-       {561, AD2KEY4},
-       {726, AD2KEY5},
-       {899, AD2KEY6},
-       {ADEmpty,0}
-};
+volatile unsigned int gFlagShortPlay = 0;
+volatile unsigned int gFlagLongPlay = 0;
+volatile unsigned int gPlayCount = 0;
 
 //key code tab
-static unsigned char gInitKeyCode[ADKEYNUM] = 
-{
-       AD2KEY1,AD2KEY2,AD2KEY3,AD2KEY4,AD2KEY5,AD2KEY6,        
-       ENDCALL,KEYSTART,KEY_WAKEUP,
-};
-
-
 struct rk28_adckey 
 {
        struct semaphore        lock;
        struct rk28_adc_client  *client;
        struct input_dev *input_dev;
        struct timer_list timer;
-       unsigned char keycodes[ADKEYNUM];
+       unsigned char * keycodes;
        void __iomem *mmio_base;
 };
 
 struct rk28_adckey *pRk28AdcKey;
 
-unsigned int rk28_get_keycode(unsigned int advalue,pADC_keyst ptab)
+unsigned int rk28_get_keycode(unsigned int advalue,pADC_keyst ptab,struct adc_key_data *rk2818_adckey_data)
 {      
-       while(ptab->adc_value != ADEmpty)
+       while(ptab->adc_value != 0)
        {
-               if((advalue > ptab->adc_value - Valuedrift) && (advalue < ptab->adc_value + Valuedrift))
-               return ptab->adc_keycode;
+               if((advalue > ptab->adc_value - rk2818_adckey_data->adc_drift) && (advalue < ptab->adc_value + rk2818_adckey_data->adc_drift))
+                   return ptab->adc_keycode;
                ptab++;
        }
 
@@ -115,22 +71,20 @@ unsigned int rk28_get_keycode(unsigned int advalue,pADC_keyst ptab)
 
 static irqreturn_t rk28_playkey_irq(int irq, void *handle)
 { 
-       input_report_key(pRk28AdcKey->input_dev,KEYSTART,1);
-       input_sync(pRk28AdcKey->input_dev);
-       input_report_key(pRk28AdcKey->input_dev,KEYSTART,0);
-       input_sync(pRk28AdcKey->input_dev);
-       printk("Enter::%s,LINE=%d,KEYSTART=%d,0\n",__FUNCTION__,__LINE__,KEYSTART);
+       
+       //gFlagPlay = 1;        
+       //DBG("Enter::%s,LINE=%d,KEY_PLAY_SHORT_PRESS=%d\n",__FUNCTION__,__LINE__,KEY_PLAY_SHORT_PRESS);
        
        return IRQ_HANDLED;
 }
 
-
 void rk28_send_wakeup_key( void ) 
 {
-        input_report_key(pRk28AdcKey->input_dev,KEY_WAKEUP,1);
-        input_sync(pRk28AdcKey->input_dev);
-        input_report_key(pRk28AdcKey->input_dev,KEY_WAKEUP,0);
-        input_sync(pRk28AdcKey->input_dev);
+    input_report_key(pRk28AdcKey->input_dev,KEY_WAKEUP,1);
+    input_sync(pRk28AdcKey->input_dev);
+    input_report_key(pRk28AdcKey->input_dev,KEY_WAKEUP,0);
+    input_sync(pRk28AdcKey->input_dev);
+       DBG("Wake up system\n");
 }
 
 static int rk28_adckey_open(struct input_dev *dev)
@@ -172,10 +126,59 @@ static int rk28_adckey_resume(struct platform_device *pdev)
 static void rk28_adkeyscan_timer(unsigned long data)
 {
        unsigned int adcvalue = -1, code;
-
+       struct adc_key_data *rk2818_adckey_data = (struct adc_key_data *)data;
+       
        pRk28AdcKey->timer.expires  = jiffies + msecs_to_jiffies(10);
        add_timer(&pRk28AdcKey->timer);
-       
+
+       /*handle long press of play key*/
+       if(gpio_get_value(rk2818_adckey_data->pin_playon) == rk2818_adckey_data->playon_level)
+       {
+               if(++gPlayCount > 20000)
+                       gPlayCount = 101;
+               if((2 == gPlayCount) && (0 == gFlagShortPlay))
+               {
+                       gFlagShortPlay = 1;                     
+               }
+               else if((100 == gPlayCount) && (0 == gFlagLongPlay))
+               {
+                       gFlagLongPlay = 1;
+                       gFlagShortPlay = 0;     
+                       input_report_key(pRk28AdcKey->input_dev,KEY_PLAY_LONG_PRESS,1);
+                       input_sync(pRk28AdcKey->input_dev);
+                       DBG("Enter::%s,LINE=%d,KEY_PLAY_LONG_PRESS=%d,1\n",__FUNCTION__,__LINE__,KEY_PLAY_LONG_PRESS);
+               }
+       }
+       else
+       {
+               if (1 == gFlagShortPlay) 
+               {
+                       input_report_key(pRk28AdcKey->input_dev,ENDCALL,1);
+                   input_sync(pRk28AdcKey->input_dev);
+                   input_report_key(pRk28AdcKey->input_dev,ENDCALL,0);
+                   input_sync(pRk28AdcKey->input_dev);
+                       DBG("Wake up system,ENDCALL=%d\n",ENDCALL);
+                       
+                       input_report_key(pRk28AdcKey->input_dev,KEY_PLAY_SHORT_PRESS,1);
+                       input_sync(pRk28AdcKey->input_dev);
+                       DBG("Enter::%s,LINE=%d,KEY_PLAY_SHORT_PRESS=%d,1\n",__FUNCTION__,__LINE__,KEY_PLAY_SHORT_PRESS);
+                       input_report_key(pRk28AdcKey->input_dev,KEY_PLAY_SHORT_PRESS,0);
+                       input_sync(pRk28AdcKey->input_dev);
+                       DBG("Enter::%s,LINE=%d,KEY_PLAY_SHORT_PRESS=%d,0\n",__FUNCTION__,__LINE__,KEY_PLAY_SHORT_PRESS);
+               }       
+               else if(1 == gFlagLongPlay)
+               {
+                       input_report_key(pRk28AdcKey->input_dev,KEY_PLAY_LONG_PRESS,0);
+                       input_sync(pRk28AdcKey->input_dev);
+                       DBG("Enter::%s,LINE=%d,KEY_PLAY_LONG_PRESS=%d,0\n",__FUNCTION__,__LINE__,KEY_PLAY_LONG_PRESS);
+               }
+               
+               gFlagShortPlay = 0;     
+               gFlagLongPlay = 0;
+               gPlayCount = 0;
+       }
+
+       /*handle long press of adc key*/
        if (gADSampleTimes < 4)
        {
                gADSampleTimes ++;
@@ -185,11 +188,15 @@ static void rk28_adkeyscan_timer(unsigned long data)
        gADSampleTimes = 0;
 
        //rk28_read_adc(pRk28AdcKey);   
-       adcvalue = gAdcValue[ADKEYCH];
-       if((adcvalue > ADEmpty) || (adcvalue < ADInvalid))
+       adcvalue = gAdcValue[rk2818_adckey_data->adc_chn];
+       //printk("=========== adcvalue=0x%x ===========\n",adcvalue);
+
+       if((adcvalue > rk2818_adckey_data->adc_empty) || (adcvalue < rk2818_adckey_data->adc_invalid))
        {
-               if(gLastCode == 0)
-               return;
+           //DBG("adcvalue invalid !!!\n");
+               if(gLastCode == 0) {
+                       return;
+               }
                else
                {
                        if(gLastCode == KEYMENU)
@@ -214,9 +221,9 @@ static void rk28_adkeyscan_timer(unsigned long data)
                }
        }
        
-       DBG("adcvalue=0x%x\n",adcvalue);
+       //DBG("adcvalue=0x%x\n",adcvalue);
        
-       code=rk28_get_keycode(adcvalue,gAdcValueTab);
+       code=rk28_get_keycode(adcvalue,rk2818_adckey_data->adc_key_table,rk2818_adckey_data);
        if(code)
        {
                if(code == KEYMENU)
@@ -249,15 +256,20 @@ static int __devinit rk28_adckey_probe(struct platform_device *pdev)
 {
        struct rk28_adckey *adckey;
        struct input_dev *input_dev;
-       int error,i;
+       int error,i,irq_num;
+       struct rk2818_adckey_platform_data *pdata = pdev->dev.platform_data;
 
+       if (!(pdata->adc_key))
+               return -1;
+       
        adckey = kzalloc(sizeof(struct rk28_adckey), GFP_KERNEL);
        if (adckey == NULL) {
                dev_err(&pdev->dev, "failed to allocate driver data\n");
                return -ENOMEM;
        }
        
-       memcpy(adckey->keycodes, gInitKeyCode, sizeof(adckey->keycodes));
+       //memcpy(adckey->keycodes, gInitKeyCode, sizeof(adckey->keycodes));
+       adckey->keycodes = pdata->adc_key->initKeyCode;
        
        /* Create and register the input driver. */
        input_dev = input_allocate_device();
@@ -279,9 +291,9 @@ static int __devinit rk28_adckey_probe(struct platform_device *pdev)
 
        input_dev->keycode = adckey->keycodes;
        input_dev->keycodesize = sizeof(unsigned char);
-       input_dev->keycodemax = ARRAY_SIZE(gInitKeyCode);
-       for (i = 0; i < ARRAY_SIZE(gInitKeyCode); i++)
-               set_bit(gInitKeyCode[i], input_dev->keybit);
+       input_dev->keycodemax = pdata->adc_key->adc_key_cnt;
+       for (i = 0; i < pdata->adc_key->adc_key_cnt; i++)
+               set_bit(pdata->adc_key->initKeyCode[i], input_dev->keybit);
        clear_bit(0, input_dev->keybit);
 
        adckey->input_dev = input_dev;
@@ -301,30 +313,47 @@ static int __devinit rk28_adckey_probe(struct platform_device *pdev)
                goto failed_free_dev;
        }
 
-       error = gpio_request(KEY_PLAYON_PIN, "play key gpio");
+       error = gpio_request(pdata->adc_key->pin_playon, "play key gpio");
        if (error) {
                dev_err(&pdev->dev, "failed to request play key gpio\n");
                goto free_gpio;
        }
        
-       gpio_pull_updown(KEY_PLAYON_PIN,GPIOPullUp);
-       error = request_irq(gpio_to_irq(KEY_PLAYON_PIN),rk28_playkey_irq,IRQF_TRIGGER_FALLING,NULL,NULL);  
-       if(error)
-       {
-               printk("unable to request play key irq\n");
-               goto free_gpio_irq;
-       }       
+       irq_num = gpio_to_irq(pdata->adc_key->pin_playon);
+
+    if(pdata->adc_key->playon_level)
+    {
+       gpio_pull_updown(pdata->adc_key->pin_playon,GPIOPullDown);              
+       error = request_irq(irq_num,rk28_playkey_irq,IRQF_TRIGGER_RISING,NULL,NULL);
+       if(error)
+       {
+               printk("unable to request play key irq\n");
+               goto free_gpio_irq;
+       }
+    }
+    else
+    {
+       gpio_pull_updown(pdata->adc_key->pin_playon,GPIOPullUp);                
+       error = request_irq(irq_num,rk28_playkey_irq,IRQF_TRIGGER_FALLING,NULL,NULL);  
+       if(error)
+       {
+               printk("unable to request play key irq\n");
+               goto free_gpio_irq;
+       }
+    }
+       
+       enable_irq_wake(irq_num); // so play/wakeup key can wake up system
 
-       setup_timer(&adckey->timer, rk28_adkeyscan_timer, (unsigned long)adckey);
+       setup_timer(&adckey->timer, rk28_adkeyscan_timer, (unsigned long)(pdata->adc_key));
        adckey->timer.expires  = jiffies+50;
        add_timer(&adckey->timer);
        printk(KERN_INFO "rk2818_adckey: driver initialized\n");
        return 0;
        
 free_gpio_irq:
-       free_irq(gpio_to_irq(KEY_PLAYON_PIN),NULL);
+       free_irq(irq_num,NULL);
 free_gpio:     
-       gpio_free(KEY_PLAYON_PIN);
+       gpio_free(pdata->adc_key->pin_playon);
 failed_free_dev:
        platform_set_drvdata(pdev, NULL);
        input_free_device(input_dev);
@@ -336,14 +365,14 @@ failed_free:
 static int __devexit rk28_adckey_remove(struct platform_device *pdev)
 {
        struct rk28_adckey *adckey = platform_get_drvdata(pdev);
-
+       struct rk2818_adckey_platform_data *pdata = pdev->dev.platform_data;
+       
        input_unregister_device(adckey->input_dev);
        input_free_device(adckey->input_dev);
        platform_set_drvdata(pdev, NULL);
        kfree(adckey);
-       free_irq(gpio_to_irq(KEY_PLAYON_PIN),NULL);
-       gpio_free(KEY_PLAYON_PIN);
-       
+       free_irq(gpio_to_irq(pdata->adc_key->pin_playon), NULL);
+       gpio_free(pdata->adc_key->pin_playon);
        return 0;
 }