keypad: avoid repetition of reporting power key event
authorXingyu Chen <xingyu.chen@amlogic.com>
Thu, 15 Mar 2018 03:11:12 +0000 (11:11 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Tue, 27 Mar 2018 01:58:00 +0000 (17:58 -0800)
PD#160889: keypad: avoid repetition of reporting power key event

If the adc_keypad and gpio_keypad driver are enabled at the same time,
the system will report two power key event when it resumes, and the
second event will result in the system suspend again. The patch resolves
the bug.

Change-Id: Iea4d9e2bf6632e4603dc9743fce07e5af74d0273
Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
drivers/amlogic/input/keyboard/adc_keypad.c
drivers/amlogic/input/keyboard/gpio_keypad.c

index 146f4bf..6c61fb7 100644 (file)
@@ -609,14 +609,24 @@ static int meson_adc_kp_suspend(struct platform_device *pdev,
 
 static int meson_adc_kp_resume(struct platform_device *pdev)
 {
+       struct adc_key *key;
        struct meson_adc_kp *kp = platform_get_drvdata(pdev);
 
        if (get_resume_method() == POWER_KEY_WAKEUP) {
-               dev_info(&pdev->dev, "adc keypad wakeup\n");
-               input_report_key(kp->poll_dev->input,  KEY_POWER,  1);
-               input_sync(kp->poll_dev->input);
-               input_report_key(kp->poll_dev->input,  KEY_POWER,  0);
-               input_sync(kp->poll_dev->input);
+               list_for_each_entry(key, &kp->adckey_head, list) {
+                       if (key->code == KEY_POWER) {
+                               dev_info(&pdev->dev, "adc keypad wakeup\n");
+
+                               input_report_key(kp->poll_dev->input,
+                                       KEY_POWER,  1);
+                               input_sync(kp->poll_dev->input);
+                               input_report_key(kp->poll_dev->input,
+                                       KEY_POWER,  0);
+                               input_sync(kp->poll_dev->input);
+
+                               break;
+                       }
+               }
        }
        return 0;
 }
index cc26ff9..35abea9 100644 (file)
@@ -51,6 +51,9 @@
 
 #define MOD_NAME       "gpio_key"
 
+#undef pr_fmt
+#define pr_fmt(fmt) "gpio_key: " fmt
+
 struct gpio_key {
        int code;         /* input key code */
        const char *name;
@@ -154,7 +157,7 @@ static irqreturn_t kp_isr(int irq,  void *data)
 {
        struct kp *kp_data = (struct kp *)data;
 
-       schedule_work(&(kp_data->work_update));
+       queue_work(system_freezable_wq, &(kp_data->work_update));
 
        /* if (!deep_suspend_flag)
         *      clr_pwr_key();
@@ -167,7 +170,7 @@ void kp_timer_sr(unsigned long data)
 {
        struct kp *kp_data = (struct kp *)data;
 
-       schedule_work(&(kp_data->work_update));
+       queue_work(system_freezable_wq, &(kp_data->work_update));
        mod_timer(&kp_data->timer, jiffies+msecs_to_jiffies(25));
 }
 #endif
@@ -441,12 +444,24 @@ static int gpio_key_suspend(struct platform_device *dev,  pm_message_t state)
 
 static int gpio_key_resume(struct platform_device *dev)
 {
+       int i;
+       struct gpio_platform_data *pdata;
+
+       pdata = (struct gpio_platform_data *)platform_get_drvdata(dev);
+
        if (get_resume_method() == POWER_KEY_WAKEUP) {
-               pr_info("gpio keypad wakeup\n");
-               input_report_key(gp_kp->input,  KEY_POWER,  1);
-               input_sync(gp_kp->input);
-               input_report_key(gp_kp->input,  KEY_POWER,  0);
-               input_sync(gp_kp->input);
+               for (i = 0; i < pdata->key_num; i++) {
+                       if (pdata->key[i].code == KEY_POWER) {
+                               pr_info("gpio keypad wakeup\n");
+
+                               input_report_key(gp_kp->input,  KEY_POWER,  1);
+                               input_sync(gp_kp->input);
+                               input_report_key(gp_kp->input,  KEY_POWER,  0);
+                               input_sync(gp_kp->input);
+
+                               break;
+                       }
+               }
        }
        return 0;
 }