aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2014-12-05 06:53:31 -0500
committerDarren Hart <dvhart@linux.intel.com>2014-12-03 13:10:18 -0500
commit02b2aaaa57ab41504e8d03a3b2ceeb9440a2c188 (patch)
tree8d6a31fef8d4787faf70963a3bf46c314437e58a
parent805469053ba9dc3c14ebbc8287f2c051ba848aa4 (diff)
platform: x86: dell-laptop: Add support for keyboard backlight
This patch adds support for configuring keyboard backlight settings on supported Dell laptops. It exports kernel leds interface and uses Dell SMBIOS tokens or keyboard class interface. With this patch it is possible to set: * keyboard backlight level * timeout after which will be backlight automatically turned off * input activity triggers (keyboard, touchpad, mouse) which enable backlight * ambient light settings Settings are exported via sysfs: /sys/class/leds/dell::kbd_backlight/ Code is based on newly released documentation by Dell in libsmbios project. Thanks to Dan Carpenter who reported bug about unpredictable results in quirks->kbd_timeouts for loop. His fix adds needs_kbd_timeouts flag to quirk structure to indicate if kbd_timeouts array is empty or not. Signed-off-by: Pali Rohár <pali.rohar@gmail.com> Signed-off-by: Gabriele Mazzotta <gabriele.mzt@gmail.com> Cc: Dan Carpenter <dan.carpenter@oracle.com> Minor English corrections to comments. Signed-off-by: Darren Hart <dvhart@linux.intel.com>
-rw-r--r--drivers/platform/x86/dell-laptop.c1055
1 files changed, 1049 insertions, 6 deletions
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 60bfc8ebc541..1266b36cb2c5 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -2,9 +2,11 @@
2 * Driver for Dell laptop extras 2 * Driver for Dell laptop extras
3 * 3 *
4 * Copyright (c) Red Hat <mjg@redhat.com> 4 * Copyright (c) Red Hat <mjg@redhat.com>
5 * Copyright (c) 2014 Gabriele Mazzotta <gabriele.mzt@gmail.com>
6 * Copyright (c) 2014 Pali Rohár <pali.rohar@gmail.com>
5 * 7 *
6 * Based on documentation in the libsmbios package, Copyright (C) 2005 Dell 8 * Based on documentation in the libsmbios package:
7 * Inc. 9 * Copyright (C) 2005-2014 Dell Inc.
8 * 10 *
9 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
@@ -32,6 +34,13 @@
32#include "../../firmware/dcdbas.h" 34#include "../../firmware/dcdbas.h"
33 35
34#define BRIGHTNESS_TOKEN 0x7d 36#define BRIGHTNESS_TOKEN 0x7d
37#define KBD_LED_OFF_TOKEN 0x01E1
38#define KBD_LED_ON_TOKEN 0x01E2
39#define KBD_LED_AUTO_TOKEN 0x01E3
40#define KBD_LED_AUTO_25_TOKEN 0x02EA
41#define KBD_LED_AUTO_50_TOKEN 0x02EB
42#define KBD_LED_AUTO_75_TOKEN 0x02EC
43#define KBD_LED_AUTO_100_TOKEN 0x02F6
35 44
36/* This structure will be modified by the firmware when we enter 45/* This structure will be modified by the firmware when we enter
37 * system management mode, hence the volatiles */ 46 * system management mode, hence the volatiles */
@@ -62,6 +71,13 @@ struct calling_interface_structure {
62 71
63struct quirk_entry { 72struct quirk_entry {
64 u8 touchpad_led; 73 u8 touchpad_led;
74
75 int needs_kbd_timeouts;
76 /*
77 * Ordered list of timeouts expressed in seconds.
78 * The list must end with -1
79 */
80 int kbd_timeouts[];
65}; 81};
66 82
67static struct quirk_entry *quirks; 83static struct quirk_entry *quirks;
@@ -76,6 +92,15 @@ static int __init dmi_matched(const struct dmi_system_id *dmi)
76 return 1; 92 return 1;
77} 93}
78 94
95/*
96 * These values come from Windows utility provided by Dell. If any other value
97 * is used then BIOS silently set timeout to 0 without any error message.
98 */
99static struct quirk_entry quirk_dell_xps13_9333 = {
100 .needs_kbd_timeouts = 1,
101 .kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 },
102};
103
79static int da_command_address; 104static int da_command_address;
80static int da_command_code; 105static int da_command_code;
81static int da_num_tokens; 106static int da_num_tokens;
@@ -268,6 +293,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
268 }, 293 },
269 .driver_data = &quirk_dell_vostro_v130, 294 .driver_data = &quirk_dell_vostro_v130,
270 }, 295 },
296 {
297 .callback = dmi_matched,
298 .ident = "Dell XPS13 9333",
299 .matches = {
300 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
301 DMI_MATCH(DMI_PRODUCT_NAME, "XPS13 9333"),
302 },
303 .driver_data = &quirk_dell_xps13_9333,
304 },
271 { } 305 { }
272}; 306};
273 307
@@ -332,17 +366,29 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy)
332 } 366 }
333} 367}
334 368
335static int find_token_location(int tokenid) 369static int find_token_id(int tokenid)
336{ 370{
337 int i; 371 int i;
372
338 for (i = 0; i < da_num_tokens; i++) { 373 for (i = 0; i < da_num_tokens; i++) {
339 if (da_tokens[i].tokenID == tokenid) 374 if (da_tokens[i].tokenID == tokenid)
340 return da_tokens[i].location; 375 return i;
341 } 376 }
342 377
343 return -1; 378 return -1;
344} 379}
345 380
381static int find_token_location(int tokenid)
382{
383 int id;
384
385 id = find_token_id(tokenid);
386 if (id == -1)
387 return -1;
388
389 return da_tokens[id].location;
390}
391
346static struct calling_interface_buffer * 392static struct calling_interface_buffer *
347dell_send_request(struct calling_interface_buffer *buffer, int class, 393dell_send_request(struct calling_interface_buffer *buffer, int class,
348 int select) 394 int select)
@@ -363,6 +409,20 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
363 return buffer; 409 return buffer;
364} 410}
365 411
412static inline int dell_smi_error(int value)
413{
414 switch (value) {
415 case 0: /* Completed successfully */
416 return 0;
417 case -1: /* Completed with error */
418 return -EIO;
419 case -2: /* Function not supported */
420 return -ENXIO;
421 default: /* Unknown error */
422 return -EINVAL;
423 }
424}
425
366/* Derived from information in DellWirelessCtl.cpp: 426/* Derived from information in DellWirelessCtl.cpp:
367 Class 17, select 11 is radio control. It returns an array of 32-bit values. 427 Class 17, select 11 is radio control. It returns an array of 32-bit values.
368 428
@@ -717,7 +777,7 @@ static int dell_send_intensity(struct backlight_device *bd)
717 else 777 else
718 dell_send_request(buffer, 1, 1); 778 dell_send_request(buffer, 1, 1);
719 779
720out: 780 out:
721 release_buffer(); 781 release_buffer();
722 return ret; 782 return ret;
723} 783}
@@ -741,7 +801,7 @@ static int dell_get_intensity(struct backlight_device *bd)
741 801
742 ret = buffer->output[1]; 802 ret = buffer->output[1];
743 803
744out: 804 out:
745 release_buffer(); 805 release_buffer();
746 return ret; 806 return ret;
747} 807}
@@ -790,6 +850,984 @@ static void touchpad_led_exit(void)
790 led_classdev_unregister(&touchpad_led); 850 led_classdev_unregister(&touchpad_led);
791} 851}
792 852
853/*
854 * Derived from information in smbios-keyboard-ctl:
855 *
856 * cbClass 4
857 * cbSelect 11
858 * Keyboard illumination
859 * cbArg1 determines the function to be performed
860 *
861 * cbArg1 0x0 = Get Feature Information
862 * cbRES1 Standard return codes (0, -1, -2)
863 * cbRES2, word0 Bitmap of user-selectable modes
864 * bit 0 Always off (All systems)
865 * bit 1 Always on (Travis ATG, Siberia)
866 * bit 2 Auto: ALS-based On; ALS-based Off (Travis ATG)
867 * bit 3 Auto: ALS- and input-activity-based On; input-activity based Off
868 * bit 4 Auto: Input-activity-based On; input-activity based Off
869 * bit 5 Auto: Input-activity-based On (illumination level 25%); input-activity based Off
870 * bit 6 Auto: Input-activity-based On (illumination level 50%); input-activity based Off
871 * bit 7 Auto: Input-activity-based On (illumination level 75%); input-activity based Off
872 * bit 8 Auto: Input-activity-based On (illumination level 100%); input-activity based Off
873 * bits 9-15 Reserved for future use
874 * cbRES2, byte2 Reserved for future use
875 * cbRES2, byte3 Keyboard illumination type
876 * 0 Reserved
877 * 1 Tasklight
878 * 2 Backlight
879 * 3-255 Reserved for future use
880 * cbRES3, byte0 Supported auto keyboard illumination trigger bitmap.
881 * bit 0 Any keystroke
882 * bit 1 Touchpad activity
883 * bit 2 Pointing stick
884 * bit 3 Any mouse
885 * bits 4-7 Reserved for future use
886 * cbRES3, byte1 Supported timeout unit bitmap
887 * bit 0 Seconds
888 * bit 1 Minutes
889 * bit 2 Hours
890 * bit 3 Days
891 * bits 4-7 Reserved for future use
892 * cbRES3, byte2 Number of keyboard light brightness levels
893 * cbRES4, byte0 Maximum acceptable seconds value (0 if seconds not supported).
894 * cbRES4, byte1 Maximum acceptable minutes value (0 if minutes not supported).
895 * cbRES4, byte2 Maximum acceptable hours value (0 if hours not supported).
896 * cbRES4, byte3 Maximum acceptable days value (0 if days not supported)
897 *
898 * cbArg1 0x1 = Get Current State
899 * cbRES1 Standard return codes (0, -1, -2)
900 * cbRES2, word0 Bitmap of current mode state
901 * bit 0 Always off (All systems)
902 * bit 1 Always on (Travis ATG, Siberia)
903 * bit 2 Auto: ALS-based On; ALS-based Off (Travis ATG)
904 * bit 3 Auto: ALS- and input-activity-based On; input-activity based Off
905 * bit 4 Auto: Input-activity-based On; input-activity based Off
906 * bit 5 Auto: Input-activity-based On (illumination level 25%); input-activity based Off
907 * bit 6 Auto: Input-activity-based On (illumination level 50%); input-activity based Off
908 * bit 7 Auto: Input-activity-based On (illumination level 75%); input-activity based Off
909 * bit 8 Auto: Input-activity-based On (illumination level 100%); input-activity based Off
910 * bits 9-15 Reserved for future use
911 * Note: Only One bit can be set
912 * cbRES2, byte2 Currently active auto keyboard illumination triggers.
913 * bit 0 Any keystroke
914 * bit 1 Touchpad activity
915 * bit 2 Pointing stick
916 * bit 3 Any mouse
917 * bits 4-7 Reserved for future use
918 * cbRES2, byte3 Current Timeout
919 * bits 7:6 Timeout units indicator:
920 * 00b Seconds
921 * 01b Minutes
922 * 10b Hours
923 * 11b Days
924 * bits 5:0 Timeout value (0-63) in sec/min/hr/day
925 * NOTE: A value of 0 means always on (no timeout) if any bits of RES3 byte
926 * are set upon return from the [Get feature information] call.
927 * cbRES3, byte0 Current setting of ALS value that turns the light on or off.
928 * cbRES3, byte1 Current ALS reading
929 * cbRES3, byte2 Current keyboard light level.
930 *
931 * cbArg1 0x2 = Set New State
932 * cbRES1 Standard return codes (0, -1, -2)
933 * cbArg2, word0 Bitmap of current mode state
934 * bit 0 Always off (All systems)
935 * bit 1 Always on (Travis ATG, Siberia)
936 * bit 2 Auto: ALS-based On; ALS-based Off (Travis ATG)
937 * bit 3 Auto: ALS- and input-activity-based On; input-activity based Off
938 * bit 4 Auto: Input-activity-based On; input-activity based Off
939 * bit 5 Auto: Input-activity-based On (illumination level 25%); input-activity based Off
940 * bit 6 Auto: Input-activity-based On (illumination level 50%); input-activity based Off
941 * bit 7 Auto: Input-activity-based On (illumination level 75%); input-activity based Off
942 * bit 8 Auto: Input-activity-based On (illumination level 100%); input-activity based Off
943 * bits 9-15 Reserved for future use
944 * Note: Only One bit can be set
945 * cbArg2, byte2 Desired auto keyboard illumination triggers. Must remain inactive to allow
946 * keyboard to turn off automatically.
947 * bit 0 Any keystroke
948 * bit 1 Touchpad activity
949 * bit 2 Pointing stick
950 * bit 3 Any mouse
951 * bits 4-7 Reserved for future use
952 * cbArg2, byte3 Desired Timeout
953 * bits 7:6 Timeout units indicator:
954 * 00b Seconds
955 * 01b Minutes
956 * 10b Hours
957 * 11b Days
958 * bits 5:0 Timeout value (0-63) in sec/min/hr/day
959 * cbArg3, byte0 Desired setting of ALS value that turns the light on or off.
960 * cbArg3, byte2 Desired keyboard light level.
961 */
962
963
964enum kbd_timeout_unit {
965 KBD_TIMEOUT_SECONDS = 0,
966 KBD_TIMEOUT_MINUTES,
967 KBD_TIMEOUT_HOURS,
968 KBD_TIMEOUT_DAYS,
969};
970
971enum kbd_mode_bit {
972 KBD_MODE_BIT_OFF = 0,
973 KBD_MODE_BIT_ON,
974 KBD_MODE_BIT_ALS,
975 KBD_MODE_BIT_TRIGGER_ALS,
976 KBD_MODE_BIT_TRIGGER,
977 KBD_MODE_BIT_TRIGGER_25,
978 KBD_MODE_BIT_TRIGGER_50,
979 KBD_MODE_BIT_TRIGGER_75,
980 KBD_MODE_BIT_TRIGGER_100,
981};
982
983#define kbd_is_als_mode_bit(bit) \
984 ((bit) == KBD_MODE_BIT_ALS || (bit) == KBD_MODE_BIT_TRIGGER_ALS)
985#define kbd_is_trigger_mode_bit(bit) \
986 ((bit) >= KBD_MODE_BIT_TRIGGER_ALS && (bit) <= KBD_MODE_BIT_TRIGGER_100)
987#define kbd_is_level_mode_bit(bit) \
988 ((bit) >= KBD_MODE_BIT_TRIGGER_25 && (bit) <= KBD_MODE_BIT_TRIGGER_100)
989
990struct kbd_info {
991 u16 modes;
992 u8 type;
993 u8 triggers;
994 u8 levels;
995 u8 seconds;
996 u8 minutes;
997 u8 hours;
998 u8 days;
999};
1000
1001struct kbd_state {
1002 u8 mode_bit;
1003 u8 triggers;
1004 u8 timeout_value;
1005 u8 timeout_unit;
1006 u8 als_setting;
1007 u8 als_value;
1008 u8 level;
1009};
1010
1011static const int kbd_tokens[] = {
1012 KBD_LED_OFF_TOKEN,
1013 KBD_LED_AUTO_25_TOKEN,
1014 KBD_LED_AUTO_50_TOKEN,
1015 KBD_LED_AUTO_75_TOKEN,
1016 KBD_LED_AUTO_100_TOKEN,
1017 KBD_LED_ON_TOKEN,
1018};
1019
1020static u16 kbd_token_bits;
1021
1022static struct kbd_info kbd_info;
1023static bool kbd_als_supported;
1024static bool kbd_triggers_supported;
1025
1026static u8 kbd_mode_levels[16];
1027static int kbd_mode_levels_count;
1028
1029static u8 kbd_previous_level;
1030static u8 kbd_previous_mode_bit;
1031
1032static bool kbd_led_present;
1033
1034/*
1035 * NOTE: there are three ways to set the keyboard backlight level.
1036 * First, via kbd_state.mode_bit (assigning KBD_MODE_BIT_TRIGGER_* value).
1037 * Second, via kbd_state.level (assigning numerical value <= kbd_info.levels).
1038 * Third, via SMBIOS tokens (KBD_LED_* in kbd_tokens)
1039 *
1040 * There are laptops which support only one of these methods. If we want to
1041 * support as many machines as possible we need to implement all three methods.
1042 * The first two methods use the kbd_state structure. The third uses SMBIOS
1043 * tokens. If kbd_info.levels == 0, the machine does not support setting the
1044 * keyboard backlight level via kbd_state.level.
1045 */
1046
1047static int kbd_get_info(struct kbd_info *info)
1048{
1049 u8 units;
1050 int ret;
1051
1052 get_buffer();
1053
1054 buffer->input[0] = 0x0;
1055 dell_send_request(buffer, 4, 11);
1056 ret = buffer->output[0];
1057
1058 if (ret) {
1059 ret = dell_smi_error(ret);
1060 goto out;
1061 }
1062
1063 info->modes = buffer->output[1] & 0xFFFF;
1064 info->type = (buffer->output[1] >> 24) & 0xFF;
1065 info->triggers = buffer->output[2] & 0xFF;
1066 units = (buffer->output[2] >> 8) & 0xFF;
1067 info->levels = (buffer->output[2] >> 16) & 0xFF;
1068
1069 if (units & BIT(0))
1070 info->seconds = (buffer->output[3] >> 0) & 0xFF;
1071 if (units & BIT(1))
1072 info->minutes = (buffer->output[3] >> 8) & 0xFF;
1073 if (units & BIT(2))
1074 info->hours = (buffer->output[3] >> 16) & 0xFF;
1075 if (units & BIT(3))
1076 info->days = (buffer->output[3] >> 24) & 0xFF;
1077
1078 out:
1079 release_buffer();
1080 return ret;
1081}
1082
1083static unsigned int kbd_get_max_level(void)
1084{
1085 if (kbd_info.levels != 0)
1086 return kbd_info.levels;
1087 if (kbd_mode_levels_count > 0)
1088 return kbd_mode_levels_count - 1;
1089 return 0;
1090}
1091
1092static int kbd_get_level(struct kbd_state *state)
1093{
1094 int i;
1095
1096 if (kbd_info.levels != 0)
1097 return state->level;
1098
1099 if (kbd_mode_levels_count > 0) {
1100 for (i = 0; i < kbd_mode_levels_count; ++i)
1101 if (kbd_mode_levels[i] == state->mode_bit)
1102 return i;
1103 return 0;
1104 }
1105
1106 return -EINVAL;
1107}
1108
1109static int kbd_set_level(struct kbd_state *state, u8 level)
1110{
1111 if (kbd_info.levels != 0) {
1112 if (level != 0)
1113 kbd_previous_level = level;
1114 if (state->level == level)
1115 return 0;
1116 state->level = level;
1117 if (level != 0 && state->mode_bit == KBD_MODE_BIT_OFF)
1118 state->mode_bit = kbd_previous_mode_bit;
1119 else if (level == 0 && state->mode_bit != KBD_MODE_BIT_OFF) {
1120 kbd_previous_mode_bit = state->mode_bit;
1121 state->mode_bit = KBD_MODE_BIT_OFF;
1122 }
1123 return 0;
1124 }
1125
1126 if (kbd_mode_levels_count > 0 && level < kbd_mode_levels_count) {
1127 if (level != 0)
1128 kbd_previous_level = level;
1129 state->mode_bit = kbd_mode_levels[level];
1130 return 0;
1131 }
1132
1133 return -EINVAL;
1134}
1135
1136static int kbd_get_state(struct kbd_state *state)
1137{
1138 int ret;
1139
1140 get_buffer();
1141
1142 buffer->input[0] = 0x1;
1143 dell_send_request(buffer, 4, 11);
1144 ret = buffer->output[0];
1145
1146 if (ret) {
1147 ret = dell_smi_error(ret);
1148 goto out;
1149 }
1150
1151 state->mode_bit = ffs(buffer->output[1] & 0xFFFF);
1152 if (state->mode_bit != 0)
1153 state->mode_bit--;
1154
1155 state->triggers = (buffer->output[1] >> 16) & 0xFF;
1156 state->timeout_value = (buffer->output[1] >> 24) & 0x3F;
1157 state->timeout_unit = (buffer->output[1] >> 30) & 0x3;
1158 state->als_setting = buffer->output[2] & 0xFF;
1159 state->als_value = (buffer->output[2] >> 8) & 0xFF;
1160 state->level = (buffer->output[2] >> 16) & 0xFF;
1161
1162 out:
1163 release_buffer();
1164 return ret;
1165}
1166
1167static int kbd_set_state(struct kbd_state *state)
1168{
1169 int ret;
1170
1171 get_buffer();
1172 buffer->input[0] = 0x2;
1173 buffer->input[1] = BIT(state->mode_bit) & 0xFFFF;
1174 buffer->input[1] |= (state->triggers & 0xFF) << 16;
1175 buffer->input[1] |= (state->timeout_value & 0x3F) << 24;
1176 buffer->input[1] |= (state->timeout_unit & 0x3) << 30;
1177 buffer->input[2] = state->als_setting & 0xFF;
1178 buffer->input[2] |= (state->level & 0xFF) << 16;
1179 dell_send_request(buffer, 4, 11);
1180 ret = buffer->output[0];
1181 release_buffer();
1182
1183 return dell_smi_error(ret);
1184}
1185
1186static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old)
1187{
1188 int ret;
1189
1190 ret = kbd_set_state(state);
1191 if (ret == 0)
1192 return 0;
1193
1194 /*
1195 * When setting the new state fails,try to restore the previous one.
1196 * This is needed on some machines where BIOS sets a default state when
1197 * setting a new state fails. This default state could be all off.
1198 */
1199
1200 if (kbd_set_state(old))
1201 pr_err("Setting old previous keyboard state failed\n");
1202
1203 return ret;
1204}
1205
1206static int kbd_set_token_bit(u8 bit)
1207{
1208 int id;
1209 int ret;
1210
1211 if (bit >= ARRAY_SIZE(kbd_tokens))
1212 return -EINVAL;
1213
1214 id = find_token_id(kbd_tokens[bit]);
1215 if (id == -1)
1216 return -EINVAL;
1217
1218 get_buffer();
1219 buffer->input[0] = da_tokens[id].location;
1220 buffer->input[1] = da_tokens[id].value;
1221 dell_send_request(buffer, 1, 0);
1222 ret = buffer->output[0];
1223 release_buffer();
1224
1225 return dell_smi_error(ret);
1226}
1227
1228static int kbd_get_token_bit(u8 bit)
1229{
1230 int id;
1231 int ret;
1232 int val;
1233
1234 if (bit >= ARRAY_SIZE(kbd_tokens))
1235 return -EINVAL;
1236
1237 id = find_token_id(kbd_tokens[bit]);
1238 if (id == -1)
1239 return -EINVAL;
1240
1241 get_buffer();
1242 buffer->input[0] = da_tokens[id].location;
1243 dell_send_request(buffer, 0, 0);
1244 ret = buffer->output[0];
1245 val = buffer->output[1];
1246 release_buffer();
1247
1248 if (ret)
1249 return dell_smi_error(ret);
1250
1251 return (val == da_tokens[id].value);
1252}
1253
1254static int kbd_get_first_active_token_bit(void)
1255{
1256 int i;
1257 int ret;
1258
1259 for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i) {
1260 ret = kbd_get_token_bit(i);
1261 if (ret == 1)
1262 return i;
1263 }
1264
1265 return ret;
1266}
1267
1268static int kbd_get_valid_token_counts(void)
1269{
1270 return hweight16(kbd_token_bits);
1271}
1272
1273static inline int kbd_init_info(void)
1274{
1275 struct kbd_state state;
1276 int ret;
1277 int i;
1278
1279 ret = kbd_get_info(&kbd_info);
1280 if (ret)
1281 return ret;
1282
1283 kbd_get_state(&state);
1284
1285 /* NOTE: timeout value is stored in 6 bits so max value is 63 */
1286 if (kbd_info.seconds > 63)
1287 kbd_info.seconds = 63;
1288 if (kbd_info.minutes > 63)
1289 kbd_info.minutes = 63;
1290 if (kbd_info.hours > 63)
1291 kbd_info.hours = 63;
1292 if (kbd_info.days > 63)
1293 kbd_info.days = 63;
1294
1295 /* NOTE: On tested machines ON mode did not work and caused
1296 * problems (turned backlight off) so do not use it
1297 */
1298 kbd_info.modes &= ~BIT(KBD_MODE_BIT_ON);
1299
1300 kbd_previous_level = kbd_get_level(&state);
1301 kbd_previous_mode_bit = state.mode_bit;
1302
1303 if (kbd_previous_level == 0 && kbd_get_max_level() != 0)
1304 kbd_previous_level = 1;
1305
1306 if (kbd_previous_mode_bit == KBD_MODE_BIT_OFF) {
1307 kbd_previous_mode_bit =
1308 ffs(kbd_info.modes & ~BIT(KBD_MODE_BIT_OFF));
1309 if (kbd_previous_mode_bit != 0)
1310 kbd_previous_mode_bit--;
1311 }
1312
1313 if (kbd_info.modes & (BIT(KBD_MODE_BIT_ALS) |
1314 BIT(KBD_MODE_BIT_TRIGGER_ALS)))
1315 kbd_als_supported = true;
1316
1317 if (kbd_info.modes & (
1318 BIT(KBD_MODE_BIT_TRIGGER_ALS) | BIT(KBD_MODE_BIT_TRIGGER) |
1319 BIT(KBD_MODE_BIT_TRIGGER_25) | BIT(KBD_MODE_BIT_TRIGGER_50) |
1320 BIT(KBD_MODE_BIT_TRIGGER_75) | BIT(KBD_MODE_BIT_TRIGGER_100)
1321 ))
1322 kbd_triggers_supported = true;
1323
1324 /* kbd_mode_levels[0] is reserved, see below */
1325 for (i = 0; i < 16; ++i)
1326 if (kbd_is_level_mode_bit(i) && (BIT(i) & kbd_info.modes))
1327 kbd_mode_levels[1 + kbd_mode_levels_count++] = i;
1328
1329 /*
1330 * Find the first supported mode and assign to kbd_mode_levels[0].
1331 * This should be 0 (off), but we cannot depend on the BIOS to
1332 * support 0.
1333 */
1334 if (kbd_mode_levels_count > 0) {
1335 for (i = 0; i < 16; ++i) {
1336 if (BIT(i) & kbd_info.modes) {
1337 kbd_mode_levels[0] = i;
1338 break;
1339 }
1340 }
1341 kbd_mode_levels_count++;
1342 }
1343
1344 return 0;
1345
1346}
1347
1348static inline void kbd_init_tokens(void)
1349{
1350 int i;
1351
1352 for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i)
1353 if (find_token_id(kbd_tokens[i]) != -1)
1354 kbd_token_bits |= BIT(i);
1355}
1356
1357static void kbd_init(void)
1358{
1359 int ret;
1360
1361 ret = kbd_init_info();
1362 kbd_init_tokens();
1363
1364 if (kbd_token_bits != 0 || ret == 0)
1365 kbd_led_present = true;
1366}
1367
1368static ssize_t kbd_led_timeout_store(struct device *dev,
1369 struct device_attribute *attr,
1370 const char *buf, size_t count)
1371{
1372 struct kbd_state new_state;
1373 struct kbd_state state;
1374 bool convert;
1375 int value;
1376 int ret;
1377 char ch;
1378 u8 unit;
1379 int i;
1380
1381 ret = sscanf(buf, "%d %c", &value, &ch);
1382 if (ret < 1)
1383 return -EINVAL;
1384 else if (ret == 1)
1385 ch = 's';
1386
1387 if (value < 0)
1388 return -EINVAL;
1389
1390 convert = false;
1391
1392 switch (ch) {
1393 case 's':
1394 if (value > kbd_info.seconds)
1395 convert = true;
1396 unit = KBD_TIMEOUT_SECONDS;
1397 break;
1398 case 'm':
1399 if (value > kbd_info.minutes)
1400 convert = true;
1401 unit = KBD_TIMEOUT_MINUTES;
1402 break;
1403 case 'h':
1404 if (value > kbd_info.hours)
1405 convert = true;
1406 unit = KBD_TIMEOUT_HOURS;
1407 break;
1408 case 'd':
1409 if (value > kbd_info.days)
1410 convert = true;
1411 unit = KBD_TIMEOUT_DAYS;
1412 break;
1413 default:
1414 return -EINVAL;
1415 }
1416
1417 if (quirks && quirks->needs_kbd_timeouts)
1418 convert = true;
1419
1420 if (convert) {
1421 /* Convert value from current units to seconds */
1422 switch (unit) {
1423 case KBD_TIMEOUT_DAYS:
1424 value *= 24;
1425 case KBD_TIMEOUT_HOURS:
1426 value *= 60;
1427 case KBD_TIMEOUT_MINUTES:
1428 value *= 60;
1429 unit = KBD_TIMEOUT_SECONDS;
1430 }
1431
1432 if (quirks && quirks->needs_kbd_timeouts) {
1433 for (i = 0; quirks->kbd_timeouts[i] != -1; i++) {
1434 if (value <= quirks->kbd_timeouts[i]) {
1435 value = quirks->kbd_timeouts[i];
1436 break;
1437 }
1438 }
1439 }
1440
1441 if (value <= kbd_info.seconds && kbd_info.seconds) {
1442 unit = KBD_TIMEOUT_SECONDS;
1443 } else if (value / 60 <= kbd_info.minutes && kbd_info.minutes) {
1444 value /= 60;
1445 unit = KBD_TIMEOUT_MINUTES;
1446 } else if (value / (60 * 60) <= kbd_info.hours && kbd_info.hours) {
1447 value /= (60 * 60);
1448 unit = KBD_TIMEOUT_HOURS;
1449 } else if (value / (60 * 60 * 24) <= kbd_info.days && kbd_info.days) {
1450 value /= (60 * 60 * 24);
1451 unit = KBD_TIMEOUT_DAYS;
1452 } else {
1453 return -EINVAL;
1454 }
1455 }
1456
1457 ret = kbd_get_state(&state);
1458 if (ret)
1459 return ret;
1460
1461 new_state = state;
1462 new_state.timeout_value = value;
1463 new_state.timeout_unit = unit;
1464
1465 ret = kbd_set_state_safe(&new_state, &state);
1466 if (ret)
1467 return ret;
1468
1469 return count;
1470}
1471
1472static ssize_t kbd_led_timeout_show(struct device *dev,
1473 struct device_attribute *attr, char *buf)
1474{
1475 struct kbd_state state;
1476 int ret;
1477 int len;
1478
1479 ret = kbd_get_state(&state);
1480 if (ret)
1481 return ret;
1482
1483 len = sprintf(buf, "%d", state.timeout_value);
1484
1485 switch (state.timeout_unit) {
1486 case KBD_TIMEOUT_SECONDS:
1487 return len + sprintf(buf+len, "s\n");
1488 case KBD_TIMEOUT_MINUTES:
1489 return len + sprintf(buf+len, "m\n");
1490 case KBD_TIMEOUT_HOURS:
1491 return len + sprintf(buf+len, "h\n");
1492 case KBD_TIMEOUT_DAYS:
1493 return len + sprintf(buf+len, "d\n");
1494 default:
1495 return -EINVAL;
1496 }
1497
1498 return len;
1499}
1500
1501static DEVICE_ATTR(stop_timeout, S_IRUGO | S_IWUSR,
1502 kbd_led_timeout_show, kbd_led_timeout_store);
1503
1504static const char * const kbd_led_triggers[] = {
1505 "keyboard",
1506 "touchpad",
1507 /*"trackstick"*/ NULL, /* NOTE: trackstick is just alias for touchpad */
1508 "mouse",
1509};
1510
1511static ssize_t kbd_led_triggers_store(struct device *dev,
1512 struct device_attribute *attr,
1513 const char *buf, size_t count)
1514{
1515 struct kbd_state new_state;
1516 struct kbd_state state;
1517 bool triggers_enabled = false;
1518 bool als_enabled = false;
1519 bool disable_als = false;
1520 bool enable_als = false;
1521 int trigger_bit = -1;
1522 char trigger[21];
1523 int i, ret;
1524
1525 ret = sscanf(buf, "%20s", trigger);
1526 if (ret != 1)
1527 return -EINVAL;
1528
1529 if (trigger[0] != '+' && trigger[0] != '-')
1530 return -EINVAL;
1531
1532 ret = kbd_get_state(&state);
1533 if (ret)
1534 return ret;
1535
1536 if (kbd_als_supported)
1537 als_enabled = kbd_is_als_mode_bit(state.mode_bit);
1538
1539 if (kbd_triggers_supported)
1540 triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit);
1541
1542 if (kbd_als_supported) {
1543 if (strcmp(trigger, "+als") == 0) {
1544 if (als_enabled)
1545 return count;
1546 enable_als = true;
1547 } else if (strcmp(trigger, "-als") == 0) {
1548 if (!als_enabled)
1549 return count;
1550 disable_als = true;
1551 }
1552 }
1553
1554 if (enable_als || disable_als) {
1555 new_state = state;
1556 if (enable_als) {
1557 if (triggers_enabled)
1558 new_state.mode_bit = KBD_MODE_BIT_TRIGGER_ALS;
1559 else
1560 new_state.mode_bit = KBD_MODE_BIT_ALS;
1561 } else {
1562 if (triggers_enabled) {
1563 new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
1564 kbd_set_level(&new_state, kbd_previous_level);
1565 } else {
1566 new_state.mode_bit = KBD_MODE_BIT_ON;
1567 }
1568 }
1569 if (!(kbd_info.modes & BIT(new_state.mode_bit)))
1570 return -EINVAL;
1571 ret = kbd_set_state_safe(&new_state, &state);
1572 if (ret)
1573 return ret;
1574 kbd_previous_mode_bit = new_state.mode_bit;
1575 return count;
1576 }
1577
1578 if (kbd_triggers_supported) {
1579 for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); ++i) {
1580 if (!(kbd_info.triggers & BIT(i)))
1581 continue;
1582 if (!kbd_led_triggers[i])
1583 continue;
1584 if (strcmp(trigger+1, kbd_led_triggers[i]) != 0)
1585 continue;
1586 if (trigger[0] == '+' &&
1587 triggers_enabled && (state.triggers & BIT(i)))
1588 return count;
1589 if (trigger[0] == '-' &&
1590 (!triggers_enabled || !(state.triggers & BIT(i))))
1591 return count;
1592 trigger_bit = i;
1593 break;
1594 }
1595 }
1596
1597 if (trigger_bit != -1) {
1598 new_state = state;
1599 if (trigger[0] == '+')
1600 new_state.triggers |= BIT(trigger_bit);
1601 else {
1602 new_state.triggers &= ~BIT(trigger_bit);
1603 /* NOTE: trackstick bit (2) must be disabled when
1604 * disabling touchpad bit (1), otherwise touchpad
1605 * bit (1) will not be disabled */
1606 if (trigger_bit == 1)
1607 new_state.triggers &= ~BIT(2);
1608 }
1609 if ((kbd_info.triggers & new_state.triggers) !=
1610 new_state.triggers)
1611 return -EINVAL;
1612 if (new_state.triggers && !triggers_enabled) {
1613 if (als_enabled)
1614 new_state.mode_bit = KBD_MODE_BIT_TRIGGER_ALS;
1615 else {
1616 new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
1617 kbd_set_level(&new_state, kbd_previous_level);
1618 }
1619 } else if (new_state.triggers == 0) {
1620 if (als_enabled)
1621 new_state.mode_bit = KBD_MODE_BIT_ALS;
1622 else
1623 kbd_set_level(&new_state, 0);
1624 }
1625 if (!(kbd_info.modes & BIT(new_state.mode_bit)))
1626 return -EINVAL;
1627 ret = kbd_set_state_safe(&new_state, &state);
1628 if (ret)
1629 return ret;
1630 if (new_state.mode_bit != KBD_MODE_BIT_OFF)
1631 kbd_previous_mode_bit = new_state.mode_bit;
1632 return count;
1633 }
1634
1635 return -EINVAL;
1636}
1637
1638static ssize_t kbd_led_triggers_show(struct device *dev,
1639 struct device_attribute *attr, char *buf)
1640{
1641 struct kbd_state state;
1642 bool triggers_enabled;
1643 int level, i, ret;
1644 int len = 0;
1645
1646 ret = kbd_get_state(&state);
1647 if (ret)
1648 return ret;
1649
1650 len = 0;
1651
1652 if (kbd_triggers_supported) {
1653 triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit);
1654 level = kbd_get_level(&state);
1655 for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); ++i) {
1656 if (!(kbd_info.triggers & BIT(i)))
1657 continue;
1658 if (!kbd_led_triggers[i])
1659 continue;
1660 if ((triggers_enabled || level <= 0) &&
1661 (state.triggers & BIT(i)))
1662 buf[len++] = '+';
1663 else
1664 buf[len++] = '-';
1665 len += sprintf(buf+len, "%s ", kbd_led_triggers[i]);
1666 }
1667 }
1668
1669 if (kbd_als_supported) {
1670 if (kbd_is_als_mode_bit(state.mode_bit))
1671 len += sprintf(buf+len, "+als ");
1672 else
1673 len += sprintf(buf+len, "-als ");
1674 }
1675
1676 if (len)
1677 buf[len - 1] = '\n';
1678
1679 return len;
1680}
1681
1682static DEVICE_ATTR(start_triggers, S_IRUGO | S_IWUSR,
1683 kbd_led_triggers_show, kbd_led_triggers_store);
1684
1685static ssize_t kbd_led_als_store(struct device *dev,
1686 struct device_attribute *attr,
1687 const char *buf, size_t count)
1688{
1689 struct kbd_state state;
1690 struct kbd_state new_state;
1691 u8 setting;
1692 int ret;
1693
1694 ret = kstrtou8(buf, 10, &setting);
1695 if (ret)
1696 return ret;
1697
1698 ret = kbd_get_state(&state);
1699 if (ret)
1700 return ret;
1701
1702 new_state = state;
1703 new_state.als_setting = setting;
1704
1705 ret = kbd_set_state_safe(&new_state, &state);
1706 if (ret)
1707 return ret;
1708
1709 return count;
1710}
1711
1712static ssize_t kbd_led_als_show(struct device *dev,
1713 struct device_attribute *attr, char *buf)
1714{
1715 struct kbd_state state;
1716 int ret;
1717
1718 ret = kbd_get_state(&state);
1719 if (ret)
1720 return ret;
1721
1722 return sprintf(buf, "%d\n", state.als_setting);
1723}
1724
1725static DEVICE_ATTR(als_setting, S_IRUGO | S_IWUSR,
1726 kbd_led_als_show, kbd_led_als_store);
1727
1728static struct attribute *kbd_led_attrs[] = {
1729 &dev_attr_stop_timeout.attr,
1730 &dev_attr_start_triggers.attr,
1731 &dev_attr_als_setting.attr,
1732 NULL,
1733};
1734ATTRIBUTE_GROUPS(kbd_led);
1735
1736static enum led_brightness kbd_led_level_get(struct led_classdev *led_cdev)
1737{
1738 int ret;
1739 u16 num;
1740 struct kbd_state state;
1741
1742 if (kbd_get_max_level()) {
1743 ret = kbd_get_state(&state);
1744 if (ret)
1745 return 0;
1746 ret = kbd_get_level(&state);
1747 if (ret < 0)
1748 return 0;
1749 return ret;
1750 }
1751
1752 if (kbd_get_valid_token_counts()) {
1753 ret = kbd_get_first_active_token_bit();
1754 if (ret < 0)
1755 return 0;
1756 for (num = kbd_token_bits; num != 0 && ret > 0; --ret)
1757 num &= num - 1; /* clear the first bit set */
1758 if (num == 0)
1759 return 0;
1760 return ffs(num) - 1;
1761 }
1762
1763 pr_warn("Keyboard brightness level control not supported\n");
1764 return 0;
1765}
1766
1767static void kbd_led_level_set(struct led_classdev *led_cdev,
1768 enum led_brightness value)
1769{
1770 struct kbd_state state;
1771 struct kbd_state new_state;
1772 u16 num;
1773
1774 if (kbd_get_max_level()) {
1775 if (kbd_get_state(&state))
1776 return;
1777 new_state = state;
1778 if (kbd_set_level(&new_state, value))
1779 return;
1780 kbd_set_state_safe(&new_state, &state);
1781 return;
1782 }
1783
1784 if (kbd_get_valid_token_counts()) {
1785 for (num = kbd_token_bits; num != 0 && value > 0; --value)
1786 num &= num - 1; /* clear the first bit set */
1787 if (num == 0)
1788 return;
1789 kbd_set_token_bit(ffs(num) - 1);
1790 return;
1791 }
1792
1793 pr_warn("Keyboard brightness level control not supported\n");
1794}
1795
1796static struct led_classdev kbd_led = {
1797 .name = "dell::kbd_backlight",
1798 .brightness_set = kbd_led_level_set,
1799 .brightness_get = kbd_led_level_get,
1800 .groups = kbd_led_groups,
1801};
1802
1803static int __init kbd_led_init(struct device *dev)
1804{
1805 kbd_init();
1806 if (!kbd_led_present)
1807 return -ENODEV;
1808 kbd_led.max_brightness = kbd_get_max_level();
1809 if (!kbd_led.max_brightness) {
1810 kbd_led.max_brightness = kbd_get_valid_token_counts();
1811 if (kbd_led.max_brightness)
1812 kbd_led.max_brightness--;
1813 }
1814 return led_classdev_register(dev, &kbd_led);
1815}
1816
1817static void brightness_set_exit(struct led_classdev *led_cdev,
1818 enum led_brightness value)
1819{
1820 /* Don't change backlight level on exit */
1821};
1822
1823static void kbd_led_exit(void)
1824{
1825 if (!kbd_led_present)
1826 return;
1827 kbd_led.brightness_set = brightness_set_exit;
1828 led_classdev_unregister(&kbd_led);
1829}
1830
793static int __init dell_init(void) 1831static int __init dell_init(void)
794{ 1832{
795 int max_intensity = 0; 1833 int max_intensity = 0;
@@ -842,6 +1880,8 @@ static int __init dell_init(void)
842 if (quirks && quirks->touchpad_led) 1880 if (quirks && quirks->touchpad_led)
843 touchpad_led_init(&platform_device->dev); 1881 touchpad_led_init(&platform_device->dev);
844 1882
1883 kbd_led_init(&platform_device->dev);
1884
845 dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); 1885 dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
846 if (dell_laptop_dir != NULL) 1886 if (dell_laptop_dir != NULL)
847 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, 1887 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
@@ -909,6 +1949,7 @@ static void __exit dell_exit(void)
909 debugfs_remove_recursive(dell_laptop_dir); 1949 debugfs_remove_recursive(dell_laptop_dir);
910 if (quirks && quirks->touchpad_led) 1950 if (quirks && quirks->touchpad_led)
911 touchpad_led_exit(); 1951 touchpad_led_exit();
1952 kbd_led_exit();
912 i8042_remove_filter(dell_laptop_i8042_filter); 1953 i8042_remove_filter(dell_laptop_i8042_filter);
913 cancel_delayed_work_sync(&dell_rfkill_work); 1954 cancel_delayed_work_sync(&dell_rfkill_work);
914 backlight_device_unregister(dell_backlight_device); 1955 backlight_device_unregister(dell_backlight_device);
@@ -925,5 +1966,7 @@ module_init(dell_init);
925module_exit(dell_exit); 1966module_exit(dell_exit);
926 1967
927MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); 1968MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
1969MODULE_AUTHOR("Gabriele Mazzotta <gabriele.mzt@gmail.com>");
1970MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
928MODULE_DESCRIPTION("Dell laptop driver"); 1971MODULE_DESCRIPTION("Dell laptop driver");
929MODULE_LICENSE("GPL"); 1972MODULE_LICENSE("GPL");