|
@@ -65,6 +65,7 @@ enum {
|
|
|
VPCCMD_R_ODD, /* 0x21 */
|
|
|
VPCCMD_R_RF = 0x23,
|
|
|
VPCCMD_W_RF,
|
|
|
+ VPCCMD_R_SPECIAL_BUTTONS = 0x31,
|
|
|
VPCCMD_W_BL_POWER = 0x33,
|
|
|
};
|
|
|
|
|
@@ -518,9 +519,13 @@ static void ideapad_platform_exit(struct ideapad_private *priv)
|
|
|
*/
|
|
|
static const struct key_entry ideapad_keymap[] = {
|
|
|
{ KE_KEY, 6, { KEY_SWITCHVIDEOMODE } },
|
|
|
+ { KE_KEY, 7, { KEY_CAMERA } },
|
|
|
+ { KE_KEY, 11, { KEY_F16 } },
|
|
|
{ KE_KEY, 13, { KEY_WLAN } },
|
|
|
{ KE_KEY, 16, { KEY_PROG1 } },
|
|
|
{ KE_KEY, 17, { KEY_PROG2 } },
|
|
|
+ { KE_KEY, 64, { KEY_PROG3 } },
|
|
|
+ { KE_KEY, 65, { KEY_PROG4 } },
|
|
|
{ KE_END, 0 },
|
|
|
};
|
|
|
|
|
@@ -587,6 +592,28 @@ static void ideapad_input_novokey(struct ideapad_private *priv)
|
|
|
ideapad_input_report(priv, 16);
|
|
|
}
|
|
|
|
|
|
+static void ideapad_check_special_buttons(struct ideapad_private *priv)
|
|
|
+{
|
|
|
+ unsigned long bit, value;
|
|
|
+
|
|
|
+ read_ec_data(ideapad_handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
|
|
|
+
|
|
|
+ for (bit = 0; bit < 16; bit++) {
|
|
|
+ if (test_bit(bit, &value)) {
|
|
|
+ switch (bit) {
|
|
|
+ case 6:
|
|
|
+ /* Thermal Management button */
|
|
|
+ ideapad_input_report(priv, 65);
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ /* OneKey Theater button */
|
|
|
+ ideapad_input_report(priv, 64);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* backlight
|
|
|
*/
|
|
@@ -785,6 +812,8 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
|
|
|
ideapad_sync_rfk_state(priv);
|
|
|
break;
|
|
|
case 13:
|
|
|
+ case 11:
|
|
|
+ case 7:
|
|
|
case 6:
|
|
|
ideapad_input_report(priv, vpc_bit);
|
|
|
break;
|
|
@@ -797,6 +826,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
|
|
|
case 2:
|
|
|
ideapad_backlight_notify_power(priv);
|
|
|
break;
|
|
|
+ case 0:
|
|
|
+ ideapad_check_special_buttons(priv);
|
|
|
+ break;
|
|
|
default:
|
|
|
pr_info("Unknown event: %lu\n", vpc_bit);
|
|
|
}
|