Input: atkbd - postpone restoring LED/repeat rate at resume
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / input / keyboard / atkbd.c
index c9523e48c6ad4240c125e0c168ee77ba1010433c..de520386f13f76192cfc241fa665ea56808e7c84 100644 (file)
@@ -574,11 +574,22 @@ static void atkbd_event_work(struct work_struct *work)
 
        mutex_lock(&atkbd->event_mutex);
 
-       if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
-               atkbd_set_leds(atkbd);
+       if (!atkbd->enabled) {
+               /*
+                * Serio ports are resumed asynchronously so while driver core
+                * thinks that device is already fully operational in reality
+                * it may not be ready yet. In this case we need to keep
+                * rescheduling till reconnect completes.
+                */
+               schedule_delayed_work(&atkbd->event_work,
+                                       msecs_to_jiffies(100));
+       } else {
+               if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
+                       atkbd_set_leds(atkbd);
 
-       if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
-               atkbd_set_repeat_rate(atkbd);
+               if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
+                       atkbd_set_repeat_rate(atkbd);
+       }
 
        mutex_unlock(&atkbd->event_mutex);
 }
@@ -770,13 +781,13 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra
        return 3;
 }
 
-static int atkbd_activate(struct atkbd *atkbd)
+static int atkbd_reset_state(struct atkbd *atkbd)
 {
-       struct ps2dev *ps2dev = &atkbd->ps2dev;
+        struct ps2dev *ps2dev = &atkbd->ps2dev;
        unsigned char param[1];
 
 /*
- * Set the LEDs to a defined state.
+ * Set the LEDs to a predefined state (all off).
  */
 
        param[0] = 0;
@@ -791,6 +802,13 @@ static int atkbd_activate(struct atkbd *atkbd)
        if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
                return -1;
 
+       return 0;
+}
+
+static int atkbd_activate(struct atkbd *atkbd)
+{
+       struct ps2dev *ps2dev = &atkbd->ps2dev;
+
 /*
  * Enable the keyboard to receive keystrokes.
  */
@@ -1104,6 +1122,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
                }
 
                atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
+               atkbd_reset_state(atkbd);
                atkbd_activate(atkbd);
 
        } else {
@@ -1158,14 +1177,6 @@ static int atkbd_reconnect(struct serio *serio)
                        return -1;
 
                atkbd_activate(atkbd);
-
-/*
- * Restore repeat rate and LEDs (that were reset by atkbd_activate)
- * to pre-resume state
- */
-               if (!atkbd->softrepeat)
-                       atkbd_set_repeat_rate(atkbd);
-               atkbd_set_leds(atkbd);
        }
 
        atkbd_enable(atkbd);
@@ -1292,6 +1303,7 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
 
                atkbd->dev = new_dev;
                atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
+               atkbd_reset_state(atkbd);
                atkbd_activate(atkbd);
                atkbd_set_keycode_table(atkbd);
                atkbd_set_device_attrs(atkbd);