aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2017-04-23 15:40:47 -0400
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>2017-04-28 14:51:26 -0400
commit9216e0dcb5533a999d544d0af8661118e0588e1d (patch)
tree3ac645ea3417e16c79e5ccc2e4864531e4542f9a
parent90a864b965e452ee2a15ed7b13f47142aeb4a40b (diff)
platform/x86: dell-laptop: Add keyboard backlight timeout AC settings
When changing keyboard backlight state on new Dell laptops, firmware expects a new timeout AC value filled in Set New State SMBIOS call. Without it any change of keyboard backlight state on new Dell laptops fails. And user can see following error message in dmesg: dell_laptop: Setting old previous keyboard state failed leds dell::kbd_backlight: Setting an LED's brightness failed (-6) This patch adds support for retrieving current timeout AC values and also updating them. Current timeout value in sysfs is displayed based on current AC status, like current display brightness value. Detection if Dell laptop supports or not new timeout AC settings is done by checking existence of Keyboard Backlight with AC SMBIOS token (0x0451). Signed-off-by: Pali Rohár <pali.rohar@gmail.com> Acked-by: Mario Limonciello <mario.limonciello@dell.com> Tested-by: Arcadiy Ivanov <arcadiy@ivanov.biz> [andy: fixed merge conflict with defined constants] Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-rw-r--r--drivers/platform/x86/dell-laptop.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 296cb9632a71..ec202094bd50 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -45,6 +45,7 @@
45#define KBD_LED_AUTO_100_TOKEN 0x02F6 45#define KBD_LED_AUTO_100_TOKEN 0x02F6
46#define GLOBAL_MIC_MUTE_ENABLE 0x0364 46#define GLOBAL_MIC_MUTE_ENABLE 0x0364
47#define GLOBAL_MIC_MUTE_DISABLE 0x0365 47#define GLOBAL_MIC_MUTE_DISABLE 0x0365
48#define KBD_LED_AC_TOKEN 0x0451
48 49
49struct quirk_entry { 50struct quirk_entry {
50 u8 touchpad_led; 51 u8 touchpad_led;
@@ -1027,7 +1028,7 @@ static void touchpad_led_exit(void)
1027 * bit 2 Pointing stick 1028 * bit 2 Pointing stick
1028 * bit 3 Any mouse 1029 * bit 3 Any mouse
1029 * bits 4-7 Reserved for future use 1030 * bits 4-7 Reserved for future use
1030 * cbRES2, byte3 Current Timeout 1031 * cbRES2, byte3 Current Timeout on battery
1031 * bits 7:6 Timeout units indicator: 1032 * bits 7:6 Timeout units indicator:
1032 * 00b Seconds 1033 * 00b Seconds
1033 * 01b Minutes 1034 * 01b Minutes
@@ -1039,6 +1040,15 @@ static void touchpad_led_exit(void)
1039 * cbRES3, byte0 Current setting of ALS value that turns the light on or off. 1040 * cbRES3, byte0 Current setting of ALS value that turns the light on or off.
1040 * cbRES3, byte1 Current ALS reading 1041 * cbRES3, byte1 Current ALS reading
1041 * cbRES3, byte2 Current keyboard light level. 1042 * cbRES3, byte2 Current keyboard light level.
1043 * cbRES3, byte3 Current timeout on AC Power
1044 * bits 7:6 Timeout units indicator:
1045 * 00b Seconds
1046 * 01b Minutes
1047 * 10b Hours
1048 * 11b Days
1049 * Bits 5:0 Timeout value (0-63) in sec/min/hr/day
1050 * NOTE: A value of 0 means always on (no timeout) if any bits of RES3 byte2
1051 * are set upon return from the upon return from the [Get Feature information] call.
1042 * 1052 *
1043 * cbArg1 0x2 = Set New State 1053 * cbArg1 0x2 = Set New State
1044 * cbRES1 Standard return codes (0, -1, -2) 1054 * cbRES1 Standard return codes (0, -1, -2)
@@ -1061,7 +1071,7 @@ static void touchpad_led_exit(void)
1061 * bit 2 Pointing stick 1071 * bit 2 Pointing stick
1062 * bit 3 Any mouse 1072 * bit 3 Any mouse
1063 * bits 4-7 Reserved for future use 1073 * bits 4-7 Reserved for future use
1064 * cbArg2, byte3 Desired Timeout 1074 * cbArg2, byte3 Desired Timeout on battery
1065 * bits 7:6 Timeout units indicator: 1075 * bits 7:6 Timeout units indicator:
1066 * 00b Seconds 1076 * 00b Seconds
1067 * 01b Minutes 1077 * 01b Minutes
@@ -1070,6 +1080,13 @@ static void touchpad_led_exit(void)
1070 * bits 5:0 Timeout value (0-63) in sec/min/hr/day 1080 * bits 5:0 Timeout value (0-63) in sec/min/hr/day
1071 * cbArg3, byte0 Desired setting of ALS value that turns the light on or off. 1081 * cbArg3, byte0 Desired setting of ALS value that turns the light on or off.
1072 * cbArg3, byte2 Desired keyboard light level. 1082 * cbArg3, byte2 Desired keyboard light level.
1083 * cbArg3, byte3 Desired Timeout on AC power
1084 * bits 7:6 Timeout units indicator:
1085 * 00b Seconds
1086 * 01b Minutes
1087 * 10b Hours
1088 * 11b Days
1089 * bits 5:0 Timeout value (0-63) in sec/min/hr/day
1073 */ 1090 */
1074 1091
1075 1092
@@ -1115,6 +1132,8 @@ struct kbd_state {
1115 u8 triggers; 1132 u8 triggers;
1116 u8 timeout_value; 1133 u8 timeout_value;
1117 u8 timeout_unit; 1134 u8 timeout_unit;
1135 u8 timeout_value_ac;
1136 u8 timeout_unit_ac;
1118 u8 als_setting; 1137 u8 als_setting;
1119 u8 als_value; 1138 u8 als_value;
1120 u8 level; 1139 u8 level;
@@ -1134,6 +1153,7 @@ static u16 kbd_token_bits;
1134static struct kbd_info kbd_info; 1153static struct kbd_info kbd_info;
1135static bool kbd_als_supported; 1154static bool kbd_als_supported;
1136static bool kbd_triggers_supported; 1155static bool kbd_triggers_supported;
1156static bool kbd_timeout_ac_supported;
1137 1157
1138static u8 kbd_mode_levels[16]; 1158static u8 kbd_mode_levels[16];
1139static int kbd_mode_levels_count; 1159static int kbd_mode_levels_count;
@@ -1273,6 +1293,8 @@ static int kbd_get_state(struct kbd_state *state)
1273 state->als_setting = buffer->output[2] & 0xFF; 1293 state->als_setting = buffer->output[2] & 0xFF;
1274 state->als_value = (buffer->output[2] >> 8) & 0xFF; 1294 state->als_value = (buffer->output[2] >> 8) & 0xFF;
1275 state->level = (buffer->output[2] >> 16) & 0xFF; 1295 state->level = (buffer->output[2] >> 16) & 0xFF;
1296 state->timeout_value_ac = (buffer->output[2] >> 24) & 0x3F;
1297 state->timeout_unit_ac = (buffer->output[2] >> 30) & 0x3;
1276 1298
1277 out: 1299 out:
1278 dell_smbios_release_buffer(); 1300 dell_smbios_release_buffer();
@@ -1292,6 +1314,8 @@ static int kbd_set_state(struct kbd_state *state)
1292 buffer->input[1] |= (state->timeout_unit & 0x3) << 30; 1314 buffer->input[1] |= (state->timeout_unit & 0x3) << 30;
1293 buffer->input[2] = state->als_setting & 0xFF; 1315 buffer->input[2] = state->als_setting & 0xFF;
1294 buffer->input[2] |= (state->level & 0xFF) << 16; 1316 buffer->input[2] |= (state->level & 0xFF) << 16;
1317 buffer->input[2] |= (state->timeout_value_ac & 0x3F) << 24;
1318 buffer->input[2] |= (state->timeout_unit_ac & 0x3) << 30;
1295 dell_smbios_send_request(4, 11); 1319 dell_smbios_send_request(4, 11);
1296 ret = buffer->output[0]; 1320 ret = buffer->output[0];
1297 dell_smbios_release_buffer(); 1321 dell_smbios_release_buffer();
@@ -1398,6 +1422,13 @@ static inline int kbd_init_info(void)
1398 if (ret) 1422 if (ret)
1399 return ret; 1423 return ret;
1400 1424
1425 /* NOTE: Old models without KBD_LED_AC_TOKEN token supports only one
1426 * timeout value which is shared for both battery and AC power
1427 * settings. So do not try to set AC values on old models.
1428 */
1429 if (dell_smbios_find_token(KBD_LED_AC_TOKEN))
1430 kbd_timeout_ac_supported = true;
1431
1401 kbd_get_state(&state); 1432 kbd_get_state(&state);
1402 1433
1403 /* NOTE: timeout value is stored in 6 bits so max value is 63 */ 1434 /* NOTE: timeout value is stored in 6 bits so max value is 63 */
@@ -1579,8 +1610,14 @@ static ssize_t kbd_led_timeout_store(struct device *dev,
1579 goto out; 1610 goto out;
1580 1611
1581 new_state = state; 1612 new_state = state;
1582 new_state.timeout_value = value; 1613
1583 new_state.timeout_unit = unit; 1614 if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) {
1615 new_state.timeout_value_ac = value;
1616 new_state.timeout_unit_ac = unit;
1617 } else {
1618 new_state.timeout_value = value;
1619 new_state.timeout_unit = unit;
1620 }
1584 1621
1585 ret = kbd_set_state_safe(&new_state, &state); 1622 ret = kbd_set_state_safe(&new_state, &state);
1586 if (ret) 1623 if (ret)
@@ -1596,16 +1633,26 @@ static ssize_t kbd_led_timeout_show(struct device *dev,
1596 struct device_attribute *attr, char *buf) 1633 struct device_attribute *attr, char *buf)
1597{ 1634{
1598 struct kbd_state state; 1635 struct kbd_state state;
1636 int value;
1599 int ret; 1637 int ret;
1600 int len; 1638 int len;
1639 u8 unit;
1601 1640
1602 ret = kbd_get_state(&state); 1641 ret = kbd_get_state(&state);
1603 if (ret) 1642 if (ret)
1604 return ret; 1643 return ret;
1605 1644
1606 len = sprintf(buf, "%d", state.timeout_value); 1645 if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) {
1646 value = state.timeout_value_ac;
1647 unit = state.timeout_unit_ac;
1648 } else {
1649 value = state.timeout_value;
1650 unit = state.timeout_unit;
1651 }
1652
1653 len = sprintf(buf, "%d", value);
1607 1654
1608 switch (state.timeout_unit) { 1655 switch (unit) {
1609 case KBD_TIMEOUT_SECONDS: 1656 case KBD_TIMEOUT_SECONDS:
1610 return len + sprintf(buf+len, "s\n"); 1657 return len + sprintf(buf+len, "s\n");
1611 case KBD_TIMEOUT_MINUTES: 1658 case KBD_TIMEOUT_MINUTES: