aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/debugfs-ideapad19
-rw-r--r--Documentation/ABI/testing/sysfs-platform-ideapad-laptop15
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/platform/x86/Kconfig17
-rw-r--r--drivers/platform/x86/acer-wmi.c488
-rw-r--r--drivers/platform/x86/asus-laptop.c378
-rw-r--r--drivers/platform/x86/asus-wmi.c4
-rw-r--r--drivers/platform/x86/dell-laptop.c84
-rw-r--r--drivers/platform/x86/eeepc-laptop.c2
-rw-r--r--drivers/platform/x86/hp_accel.c5
-rw-r--r--drivers/platform/x86/ideapad-laptop.c251
-rw-r--r--drivers/platform/x86/intel_scu_ipcutil.c8
-rw-r--r--drivers/platform/x86/samsung-laptop.c107
-rw-r--r--drivers/platform/x86/sony-laptop.c2
-rw-r--r--drivers/platform/x86/topstar-laptop.c1
-rw-r--r--drivers/platform/x86/toshiba_acpi.c641
-rw-r--r--drivers/platform/x86/wmi.c6
17 files changed, 1421 insertions, 614 deletions
diff --git a/Documentation/ABI/testing/debugfs-ideapad b/Documentation/ABI/testing/debugfs-ideapad
new file mode 100644
index 000000000000..7079c0b21030
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-ideapad
@@ -0,0 +1,19 @@
1What: /sys/kernel/debug/ideapad/cfg
2Date: Sep 2011
3KernelVersion: 3.2
4Contact: Ike Panhc <ike.pan@canonical.com>
5Description:
6
7cfg shows the return value of _CFG method in VPC2004 device. It tells machine
8capability and what graphic component within the machine.
9
10
11What: /sys/kernel/debug/ideapad/status
12Date: Sep 2011
13KernelVersion: 3.2
14Contact: Ike Panhc <ike.pan@canonical.com>
15Description:
16
17status shows infos we can read and tells its meaning and value.
18
19
diff --git a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
index ff53183c3848..814b01354c41 100644
--- a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
+++ b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
@@ -5,19 +5,4 @@ Contact: "Ike Panhc <ike.pan@canonical.com>"
5Description: 5Description:
6 Control the power of camera module. 1 means on, 0 means off. 6 Control the power of camera module. 1 means on, 0 means off.
7 7
8What: /sys/devices/platform/ideapad/cfg
9Date: Jun 2011
10KernelVersion: 3.1
11Contact: "Ike Panhc <ike.pan@canonical.com>"
12Description:
13 Ideapad capability bits.
14 Bit 8-10: 1 - Intel graphic only
15 2 - ATI graphic only
16 3 - Nvidia graphic only
17 4 - Intel and ATI graphic
18 5 - Intel and Nvidia graphic
19 Bit 16: Bluetooth exist (1 for exist)
20 Bit 17: 3G exist (1 for exist)
21 Bit 18: Wifi exist (1 for exist)
22 Bit 19: Camera exist (1 for exist)
23 8
diff --git a/MAINTAINERS b/MAINTAINERS
index 5e587fcaf4dc..d498c70e394a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3227,6 +3227,13 @@ F: Documentation/ide/
3227F: drivers/ide/ 3227F: drivers/ide/
3228F: include/linux/ide.h 3228F: include/linux/ide.h
3229 3229
3230IDEAPAD LAPTOP EXTRAS DRIVER
3231M: Ike Panhc <ike.pan@canonical.com>
3232L: platform-driver-x86@vger.kernel.org
3233W: http://launchpad.net/ideapad-laptop
3234S: Maintained
3235F: drivers/platform/x86/ideapad-laptop.c
3236
3230IDE/ATAPI DRIVERS 3237IDE/ATAPI DRIVERS
3231M: Borislav Petkov <petkovbb@gmail.com> 3238M: Borislav Petkov <petkovbb@gmail.com>
3232L: linux-ide@vger.kernel.org 3239L: linux-ide@vger.kernel.org
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 10cf2500522b..f4e3d82379d7 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -61,15 +61,18 @@ config ASUS_LAPTOP
61 depends on INPUT 61 depends on INPUT
62 depends on RFKILL || RFKILL = n 62 depends on RFKILL || RFKILL = n
63 select INPUT_SPARSEKMAP 63 select INPUT_SPARSEKMAP
64 select INPUT_POLLDEV
64 ---help--- 65 ---help---
65 This is the new Linux driver for Asus laptops. It may also support some 66 This is a driver for Asus laptops, Lenovo SL and the Pegatron
66 MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate 67 Lucid tablet. It may also support some MEDION, JVC or VICTOR
67 standard ACPI events and input events. It also adds 68 laptops. It makes all the extra buttons generate standard
68 support for video output switching, LCD backlight control, Bluetooth and 69 ACPI events and input events, and on the Lucid the built-in
69 Wlan control, and most importantly, allows you to blink those fancy LEDs. 70 accelerometer appears as an input device. It also adds
71 support for video output switching, LCD backlight control,
72 Bluetooth and Wlan control, and most importantly, allows you
73 to blink those fancy LEDs.
70 74
71 For more information and a userspace daemon for handling the extra 75 For more information see <http://acpi4asus.sf.net>.
72 buttons see <http://acpi4asus.sf.net>.
73 76
74 If you have an ACPI-compatible ASUS laptop, say Y or M here. 77 If you have an ACPI-compatible ASUS laptop, say Y or M here.
75 78
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index af2bb20cb2fb..b848277171a4 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -190,6 +190,7 @@ enum interface_flags {
190 ACER_AMW0, 190 ACER_AMW0,
191 ACER_AMW0_V2, 191 ACER_AMW0_V2,
192 ACER_WMID, 192 ACER_WMID,
193 ACER_WMID_v2,
193}; 194};
194 195
195#define ACER_DEFAULT_WIRELESS 0 196#define ACER_DEFAULT_WIRELESS 0
@@ -205,6 +206,7 @@ static int threeg = -1;
205static int force_series; 206static int force_series;
206static bool ec_raw_mode; 207static bool ec_raw_mode;
207static bool has_type_aa; 208static bool has_type_aa;
209static u16 commun_func_bitmap;
208 210
209module_param(mailled, int, 0444); 211module_param(mailled, int, 0444);
210module_param(brightness, int, 0444); 212module_param(brightness, int, 0444);
@@ -464,6 +466,15 @@ static struct dmi_system_id acer_quirks[] = {
464 }, 466 },
465 .driver_data = &quirk_lenovo_ideapad_s205, 467 .driver_data = &quirk_lenovo_ideapad_s205,
466 }, 468 },
469 {
470 .callback = dmi_matched,
471 .ident = "Lenovo 3000 N200",
472 .matches = {
473 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
474 DMI_MATCH(DMI_PRODUCT_NAME, "0687A31"),
475 },
476 .driver_data = &quirk_fujitsu_amilo_li_1718,
477 },
467 {} 478 {}
468}; 479};
469 480
@@ -868,6 +879,174 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
868 return WMI_execute_u32(method_id, (u32)value, NULL); 879 return WMI_execute_u32(method_id, (u32)value, NULL);
869} 880}
870 881
882static acpi_status wmid3_get_device_status(u32 *value, u16 device)
883{
884 struct wmid3_gds_return_value return_value;
885 acpi_status status;
886 union acpi_object *obj;
887 struct wmid3_gds_input_param params = {
888 .function_num = 0x1,
889 .hotkey_number = 0x01,
890 .devices = device,
891 };
892 struct acpi_buffer input = {
893 sizeof(struct wmid3_gds_input_param),
894 &params
895 };
896 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
897
898 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
899 if (ACPI_FAILURE(status))
900 return status;
901
902 obj = output.pointer;
903
904 if (!obj)
905 return AE_ERROR;
906 else if (obj->type != ACPI_TYPE_BUFFER) {
907 kfree(obj);
908 return AE_ERROR;
909 }
910 if (obj->buffer.length != 8) {
911 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
912 kfree(obj);
913 return AE_ERROR;
914 }
915
916 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
917 kfree(obj);
918
919 if (return_value.error_code || return_value.ec_return_value)
920 pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n",
921 device,
922 return_value.error_code,
923 return_value.ec_return_value);
924 else
925 *value = !!(return_value.devices & device);
926
927 return status;
928}
929
930static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
931{
932 u16 device;
933
934 switch (cap) {
935 case ACER_CAP_WIRELESS:
936 device = ACER_WMID3_GDS_WIRELESS;
937 break;
938 case ACER_CAP_BLUETOOTH:
939 device = ACER_WMID3_GDS_BLUETOOTH;
940 break;
941 case ACER_CAP_THREEG:
942 device = ACER_WMID3_GDS_THREEG;
943 break;
944 default:
945 return AE_ERROR;
946 }
947 return wmid3_get_device_status(value, device);
948}
949
950static acpi_status wmid3_set_device_status(u32 value, u16 device)
951{
952 struct wmid3_gds_return_value return_value;
953 acpi_status status;
954 union acpi_object *obj;
955 u16 devices;
956 struct wmid3_gds_input_param params = {
957 .function_num = 0x1,
958 .hotkey_number = 0x01,
959 .devices = commun_func_bitmap,
960 };
961 struct acpi_buffer input = {
962 sizeof(struct wmid3_gds_input_param),
963 &params
964 };
965 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
966 struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
967
968 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
969 if (ACPI_FAILURE(status))
970 return status;
971
972 obj = output.pointer;
973
974 if (!obj)
975 return AE_ERROR;
976 else if (obj->type != ACPI_TYPE_BUFFER) {
977 kfree(obj);
978 return AE_ERROR;
979 }
980 if (obj->buffer.length != 8) {
981 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
982 kfree(obj);
983 return AE_ERROR;
984 }
985
986 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
987 kfree(obj);
988
989 if (return_value.error_code || return_value.ec_return_value) {
990 pr_warning("Get Current Device Status failed: "
991 "0x%x - 0x%x\n", return_value.error_code,
992 return_value.ec_return_value);
993 return status;
994 }
995
996 devices = return_value.devices;
997 params.function_num = 0x2;
998 params.hotkey_number = 0x01;
999 params.devices = (value) ? (devices | device) : (devices & ~device);
1000
1001 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
1002 if (ACPI_FAILURE(status))
1003 return status;
1004
1005 obj = output2.pointer;
1006
1007 if (!obj)
1008 return AE_ERROR;
1009 else if (obj->type != ACPI_TYPE_BUFFER) {
1010 kfree(obj);
1011 return AE_ERROR;
1012 }
1013 if (obj->buffer.length != 4) {
1014 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1015 kfree(obj);
1016 return AE_ERROR;
1017 }
1018
1019 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1020 kfree(obj);
1021
1022 if (return_value.error_code || return_value.ec_return_value)
1023 pr_warning("Set Device Status failed: "
1024 "0x%x - 0x%x\n", return_value.error_code,
1025 return_value.ec_return_value);
1026
1027 return status;
1028}
1029
1030static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
1031{
1032 u16 device;
1033
1034 switch (cap) {
1035 case ACER_CAP_WIRELESS:
1036 device = ACER_WMID3_GDS_WIRELESS;
1037 break;
1038 case ACER_CAP_BLUETOOTH:
1039 device = ACER_WMID3_GDS_BLUETOOTH;
1040 break;
1041 case ACER_CAP_THREEG:
1042 device = ACER_WMID3_GDS_THREEG;
1043 break;
1044 default:
1045 return AE_ERROR;
1046 }
1047 return wmid3_set_device_status(value, device);
1048}
1049
871static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) 1050static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
872{ 1051{
873 struct hotkey_function_type_aa *type_aa; 1052 struct hotkey_function_type_aa *type_aa;
@@ -881,6 +1060,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
881 1060
882 pr_info("Function bitmap for Communication Button: 0x%x\n", 1061 pr_info("Function bitmap for Communication Button: 0x%x\n",
883 type_aa->commun_func_bitmap); 1062 type_aa->commun_func_bitmap);
1063 commun_func_bitmap = type_aa->commun_func_bitmap;
884 1064
885 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS) 1065 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
886 interface->capability |= ACER_CAP_WIRELESS; 1066 interface->capability |= ACER_CAP_WIRELESS;
@@ -913,17 +1093,13 @@ static acpi_status WMID_set_capabilities(void)
913 return AE_ERROR; 1093 return AE_ERROR;
914 } 1094 }
915 1095
916 dmi_walk(type_aa_dmi_decode, NULL); 1096 pr_info("Function bitmap for Communication Device: 0x%x\n", devices);
917 if (!has_type_aa) { 1097 if (devices & 0x07)
918 interface->capability |= ACER_CAP_WIRELESS; 1098 interface->capability |= ACER_CAP_WIRELESS;
919 if (devices & 0x40) 1099 if (devices & 0x40)
920 interface->capability |= ACER_CAP_THREEG; 1100 interface->capability |= ACER_CAP_THREEG;
921 if (devices & 0x10) 1101 if (devices & 0x10)
922 interface->capability |= ACER_CAP_BLUETOOTH; 1102 interface->capability |= ACER_CAP_BLUETOOTH;
923 }
924
925 /* WMID always provides brightness methods */
926 interface->capability |= ACER_CAP_BRIGHTNESS;
927 1103
928 if (!(devices & 0x20)) 1104 if (!(devices & 0x20))
929 max_brightness = 0x9; 1105 max_brightness = 0x9;
@@ -936,6 +1112,10 @@ static struct wmi_interface wmid_interface = {
936 .type = ACER_WMID, 1112 .type = ACER_WMID,
937}; 1113};
938 1114
1115static struct wmi_interface wmid_v2_interface = {
1116 .type = ACER_WMID_v2,
1117};
1118
939/* 1119/*
940 * Generic Device (interface-independent) 1120 * Generic Device (interface-independent)
941 */ 1121 */
@@ -956,6 +1136,14 @@ static acpi_status get_u32(u32 *value, u32 cap)
956 case ACER_WMID: 1136 case ACER_WMID:
957 status = WMID_get_u32(value, cap, interface); 1137 status = WMID_get_u32(value, cap, interface);
958 break; 1138 break;
1139 case ACER_WMID_v2:
1140 if (cap & (ACER_CAP_WIRELESS |
1141 ACER_CAP_BLUETOOTH |
1142 ACER_CAP_THREEG))
1143 status = wmid_v2_get_u32(value, cap);
1144 else if (wmi_has_guid(WMID_GUID2))
1145 status = WMID_get_u32(value, cap, interface);
1146 break;
959 } 1147 }
960 1148
961 return status; 1149 return status;
@@ -989,6 +1177,13 @@ static acpi_status set_u32(u32 value, u32 cap)
989 } 1177 }
990 case ACER_WMID: 1178 case ACER_WMID:
991 return WMID_set_u32(value, cap, interface); 1179 return WMID_set_u32(value, cap, interface);
1180 case ACER_WMID_v2:
1181 if (cap & (ACER_CAP_WIRELESS |
1182 ACER_CAP_BLUETOOTH |
1183 ACER_CAP_THREEG))
1184 return wmid_v2_set_u32(value, cap);
1185 else if (wmi_has_guid(WMID_GUID2))
1186 return WMID_set_u32(value, cap, interface);
992 default: 1187 default:
993 return AE_BAD_PARAMETER; 1188 return AE_BAD_PARAMETER;
994 } 1189 }
@@ -1095,186 +1290,6 @@ static void acer_backlight_exit(void)
1095 backlight_device_unregister(acer_backlight_device); 1290 backlight_device_unregister(acer_backlight_device);
1096} 1291}
1097 1292
1098static acpi_status wmid3_get_device_status(u32 *value, u16 device)
1099{
1100 struct wmid3_gds_return_value return_value;
1101 acpi_status status;
1102 union acpi_object *obj;
1103 struct wmid3_gds_input_param params = {
1104 .function_num = 0x1,
1105 .hotkey_number = 0x01,
1106 .devices = device,
1107 };
1108 struct acpi_buffer input = {
1109 sizeof(struct wmid3_gds_input_param),
1110 &params
1111 };
1112 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1113
1114 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1115 if (ACPI_FAILURE(status))
1116 return status;
1117
1118 obj = output.pointer;
1119
1120 if (!obj)
1121 return AE_ERROR;
1122 else if (obj->type != ACPI_TYPE_BUFFER) {
1123 kfree(obj);
1124 return AE_ERROR;
1125 }
1126 if (obj->buffer.length != 8) {
1127 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1128 kfree(obj);
1129 return AE_ERROR;
1130 }
1131
1132 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1133 kfree(obj);
1134
1135 if (return_value.error_code || return_value.ec_return_value)
1136 pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
1137 return_value.error_code,
1138 return_value.ec_return_value);
1139 else
1140 *value = !!(return_value.devices & device);
1141
1142 return status;
1143}
1144
1145static acpi_status get_device_status(u32 *value, u32 cap)
1146{
1147 if (wmi_has_guid(WMID_GUID3)) {
1148 u16 device;
1149
1150 switch (cap) {
1151 case ACER_CAP_WIRELESS:
1152 device = ACER_WMID3_GDS_WIRELESS;
1153 break;
1154 case ACER_CAP_BLUETOOTH:
1155 device = ACER_WMID3_GDS_BLUETOOTH;
1156 break;
1157 case ACER_CAP_THREEG:
1158 device = ACER_WMID3_GDS_THREEG;
1159 break;
1160 default:
1161 return AE_ERROR;
1162 }
1163 return wmid3_get_device_status(value, device);
1164
1165 } else {
1166 return get_u32(value, cap);
1167 }
1168}
1169
1170static acpi_status wmid3_set_device_status(u32 value, u16 device)
1171{
1172 struct wmid3_gds_return_value return_value;
1173 acpi_status status;
1174 union acpi_object *obj;
1175 u16 devices;
1176 struct wmid3_gds_input_param params = {
1177 .function_num = 0x1,
1178 .hotkey_number = 0x01,
1179 .devices = ACER_WMID3_GDS_WIRELESS |
1180 ACER_WMID3_GDS_THREEG |
1181 ACER_WMID3_GDS_WIMAX |
1182 ACER_WMID3_GDS_BLUETOOTH,
1183 };
1184 struct acpi_buffer input = {
1185 sizeof(struct wmid3_gds_input_param),
1186 &params
1187 };
1188 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1189 struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
1190
1191 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1192 if (ACPI_FAILURE(status))
1193 return status;
1194
1195 obj = output.pointer;
1196
1197 if (!obj)
1198 return AE_ERROR;
1199 else if (obj->type != ACPI_TYPE_BUFFER) {
1200 kfree(obj);
1201 return AE_ERROR;
1202 }
1203 if (obj->buffer.length != 8) {
1204 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1205 kfree(obj);
1206 return AE_ERROR;
1207 }
1208
1209 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1210 kfree(obj);
1211
1212 if (return_value.error_code || return_value.ec_return_value) {
1213 pr_warning("Get Current Device Status failed: "
1214 "0x%x - 0x%x\n", return_value.error_code,
1215 return_value.ec_return_value);
1216 return status;
1217 }
1218
1219 devices = return_value.devices;
1220 params.function_num = 0x2;
1221 params.hotkey_number = 0x01;
1222 params.devices = (value) ? (devices | device) : (devices & ~device);
1223
1224 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
1225 if (ACPI_FAILURE(status))
1226 return status;
1227
1228 obj = output2.pointer;
1229
1230 if (!obj)
1231 return AE_ERROR;
1232 else if (obj->type != ACPI_TYPE_BUFFER) {
1233 kfree(obj);
1234 return AE_ERROR;
1235 }
1236 if (obj->buffer.length != 4) {
1237 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1238 kfree(obj);
1239 return AE_ERROR;
1240 }
1241
1242 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1243 kfree(obj);
1244
1245 if (return_value.error_code || return_value.ec_return_value)
1246 pr_warning("Set Device Status failed: "
1247 "0x%x - 0x%x\n", return_value.error_code,
1248 return_value.ec_return_value);
1249
1250 return status;
1251}
1252
1253static acpi_status set_device_status(u32 value, u32 cap)
1254{
1255 if (wmi_has_guid(WMID_GUID3)) {
1256 u16 device;
1257
1258 switch (cap) {
1259 case ACER_CAP_WIRELESS:
1260 device = ACER_WMID3_GDS_WIRELESS;
1261 break;
1262 case ACER_CAP_BLUETOOTH:
1263 device = ACER_WMID3_GDS_BLUETOOTH;
1264 break;
1265 case ACER_CAP_THREEG:
1266 device = ACER_WMID3_GDS_THREEG;
1267 break;
1268 default:
1269 return AE_ERROR;
1270 }
1271 return wmid3_set_device_status(value, device);
1272
1273 } else {
1274 return set_u32(value, cap);
1275 }
1276}
1277
1278/* 1293/*
1279 * Rfkill devices 1294 * Rfkill devices
1280 */ 1295 */
@@ -1285,12 +1300,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
1285 u32 state; 1300 u32 state;
1286 acpi_status status; 1301 acpi_status status;
1287 1302
1288 status = get_u32(&state, ACER_CAP_WIRELESS); 1303 if (has_cap(ACER_CAP_WIRELESS)) {
1289 if (ACPI_SUCCESS(status)) { 1304 status = get_u32(&state, ACER_CAP_WIRELESS);
1290 if (quirks->wireless == 3) { 1305 if (ACPI_SUCCESS(status)) {
1291 rfkill_set_hw_state(wireless_rfkill, !state); 1306 if (quirks->wireless == 3)
1292 } else { 1307 rfkill_set_hw_state(wireless_rfkill, !state);
1293 rfkill_set_sw_state(wireless_rfkill, !state); 1308 else
1309 rfkill_set_sw_state(wireless_rfkill, !state);
1294 } 1310 }
1295 } 1311 }
1296 1312
@@ -1301,8 +1317,7 @@ static void acer_rfkill_update(struct work_struct *ignored)
1301 } 1317 }
1302 1318
1303 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) { 1319 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
1304 status = wmid3_get_device_status(&state, 1320 status = get_u32(&state, ACER_WMID3_GDS_THREEG);
1305 ACER_WMID3_GDS_THREEG);
1306 if (ACPI_SUCCESS(status)) 1321 if (ACPI_SUCCESS(status))
1307 rfkill_set_sw_state(threeg_rfkill, !state); 1322 rfkill_set_sw_state(threeg_rfkill, !state);
1308 } 1323 }
@@ -1316,7 +1331,7 @@ static int acer_rfkill_set(void *data, bool blocked)
1316 u32 cap = (unsigned long)data; 1331 u32 cap = (unsigned long)data;
1317 1332
1318 if (rfkill_inited) { 1333 if (rfkill_inited) {
1319 status = set_device_status(!blocked, cap); 1334 status = set_u32(!blocked, cap);
1320 if (ACPI_FAILURE(status)) 1335 if (ACPI_FAILURE(status))
1321 return -ENODEV; 1336 return -ENODEV;
1322 } 1337 }
@@ -1343,7 +1358,7 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
1343 if (!rfkill_dev) 1358 if (!rfkill_dev)
1344 return ERR_PTR(-ENOMEM); 1359 return ERR_PTR(-ENOMEM);
1345 1360
1346 status = get_device_status(&state, cap); 1361 status = get_u32(&state, cap);
1347 1362
1348 err = rfkill_register(rfkill_dev); 1363 err = rfkill_register(rfkill_dev);
1349 if (err) { 1364 if (err) {
@@ -1359,19 +1374,24 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
1359 1374
1360static int acer_rfkill_init(struct device *dev) 1375static int acer_rfkill_init(struct device *dev)
1361{ 1376{
1362 wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN, 1377 int err;
1363 "acer-wireless", ACER_CAP_WIRELESS); 1378
1364 if (IS_ERR(wireless_rfkill)) 1379 if (has_cap(ACER_CAP_WIRELESS)) {
1365 return PTR_ERR(wireless_rfkill); 1380 wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
1381 "acer-wireless", ACER_CAP_WIRELESS);
1382 if (IS_ERR(wireless_rfkill)) {
1383 err = PTR_ERR(wireless_rfkill);
1384 goto error_wireless;
1385 }
1386 }
1366 1387
1367 if (has_cap(ACER_CAP_BLUETOOTH)) { 1388 if (has_cap(ACER_CAP_BLUETOOTH)) {
1368 bluetooth_rfkill = acer_rfkill_register(dev, 1389 bluetooth_rfkill = acer_rfkill_register(dev,
1369 RFKILL_TYPE_BLUETOOTH, "acer-bluetooth", 1390 RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
1370 ACER_CAP_BLUETOOTH); 1391 ACER_CAP_BLUETOOTH);
1371 if (IS_ERR(bluetooth_rfkill)) { 1392 if (IS_ERR(bluetooth_rfkill)) {
1372 rfkill_unregister(wireless_rfkill); 1393 err = PTR_ERR(bluetooth_rfkill);
1373 rfkill_destroy(wireless_rfkill); 1394 goto error_bluetooth;
1374 return PTR_ERR(bluetooth_rfkill);
1375 } 1395 }
1376 } 1396 }
1377 1397
@@ -1380,30 +1400,44 @@ static int acer_rfkill_init(struct device *dev)
1380 RFKILL_TYPE_WWAN, "acer-threeg", 1400 RFKILL_TYPE_WWAN, "acer-threeg",
1381 ACER_CAP_THREEG); 1401 ACER_CAP_THREEG);
1382 if (IS_ERR(threeg_rfkill)) { 1402 if (IS_ERR(threeg_rfkill)) {
1383 rfkill_unregister(wireless_rfkill); 1403 err = PTR_ERR(threeg_rfkill);
1384 rfkill_destroy(wireless_rfkill); 1404 goto error_threeg;
1385 rfkill_unregister(bluetooth_rfkill);
1386 rfkill_destroy(bluetooth_rfkill);
1387 return PTR_ERR(threeg_rfkill);
1388 } 1405 }
1389 } 1406 }
1390 1407
1391 rfkill_inited = true; 1408 rfkill_inited = true;
1392 1409
1393 if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) 1410 if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
1411 has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
1394 schedule_delayed_work(&acer_rfkill_work, 1412 schedule_delayed_work(&acer_rfkill_work,
1395 round_jiffies_relative(HZ)); 1413 round_jiffies_relative(HZ));
1396 1414
1397 return 0; 1415 return 0;
1416
1417error_threeg:
1418 if (has_cap(ACER_CAP_BLUETOOTH)) {
1419 rfkill_unregister(bluetooth_rfkill);
1420 rfkill_destroy(bluetooth_rfkill);
1421 }
1422error_bluetooth:
1423 if (has_cap(ACER_CAP_WIRELESS)) {
1424 rfkill_unregister(wireless_rfkill);
1425 rfkill_destroy(wireless_rfkill);
1426 }
1427error_wireless:
1428 return err;
1398} 1429}
1399 1430
1400static void acer_rfkill_exit(void) 1431static void acer_rfkill_exit(void)
1401{ 1432{
1402 if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) 1433 if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
1434 has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
1403 cancel_delayed_work_sync(&acer_rfkill_work); 1435 cancel_delayed_work_sync(&acer_rfkill_work);
1404 1436
1405 rfkill_unregister(wireless_rfkill); 1437 if (has_cap(ACER_CAP_WIRELESS)) {
1406 rfkill_destroy(wireless_rfkill); 1438 rfkill_unregister(wireless_rfkill);
1439 rfkill_destroy(wireless_rfkill);
1440 }
1407 1441
1408 if (has_cap(ACER_CAP_BLUETOOTH)) { 1442 if (has_cap(ACER_CAP_BLUETOOTH)) {
1409 rfkill_unregister(bluetooth_rfkill); 1443 rfkill_unregister(bluetooth_rfkill);
@@ -1428,11 +1462,7 @@ static ssize_t show_bool_threeg(struct device *dev,
1428 1462
1429 pr_info("This threeg sysfs will be removed in 2012" 1463 pr_info("This threeg sysfs will be removed in 2012"
1430 " - used by: %s\n", current->comm); 1464 " - used by: %s\n", current->comm);
1431 if (wmi_has_guid(WMID_GUID3)) 1465 status = get_u32(&result, ACER_CAP_THREEG);
1432 status = wmid3_get_device_status(&result,
1433 ACER_WMID3_GDS_THREEG);
1434 else
1435 status = get_u32(&result, ACER_CAP_THREEG);
1436 if (ACPI_SUCCESS(status)) 1466 if (ACPI_SUCCESS(status))
1437 return sprintf(buf, "%u\n", result); 1467 return sprintf(buf, "%u\n", result);
1438 return sprintf(buf, "Read error\n"); 1468 return sprintf(buf, "Read error\n");
@@ -1464,6 +1494,8 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
1464 return sprintf(buf, "AMW0 v2\n"); 1494 return sprintf(buf, "AMW0 v2\n");
1465 case ACER_WMID: 1495 case ACER_WMID:
1466 return sprintf(buf, "WMID\n"); 1496 return sprintf(buf, "WMID\n");
1497 case ACER_WMID_v2:
1498 return sprintf(buf, "WMID v2\n");
1467 default: 1499 default:
1468 return sprintf(buf, "Error!\n"); 1500 return sprintf(buf, "Error!\n");
1469 } 1501 }
@@ -1883,12 +1915,20 @@ static int __init acer_wmi_init(void)
1883 if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) 1915 if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
1884 interface = &wmid_interface; 1916 interface = &wmid_interface;
1885 1917
1918 if (wmi_has_guid(WMID_GUID3))
1919 interface = &wmid_v2_interface;
1920
1921 if (interface)
1922 dmi_walk(type_aa_dmi_decode, NULL);
1923
1886 if (wmi_has_guid(WMID_GUID2) && interface) { 1924 if (wmi_has_guid(WMID_GUID2) && interface) {
1887 if (ACPI_FAILURE(WMID_set_capabilities())) { 1925 if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
1888 pr_err("Unable to detect available WMID devices\n"); 1926 pr_err("Unable to detect available WMID devices\n");
1889 return -ENODEV; 1927 return -ENODEV;
1890 } 1928 }
1891 } else if (!wmi_has_guid(WMID_GUID2) && interface) { 1929 /* WMID always provides brightness methods */
1930 interface->capability |= ACER_CAP_BRIGHTNESS;
1931 } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
1892 pr_err("No WMID device detection method found\n"); 1932 pr_err("No WMID device detection method found\n");
1893 return -ENODEV; 1933 return -ENODEV;
1894 } 1934 }
@@ -1912,7 +1952,7 @@ static int __init acer_wmi_init(void)
1912 1952
1913 set_quirks(); 1953 set_quirks();
1914 1954
1915 if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { 1955 if (acpi_video_backlight_support()) {
1916 interface->capability &= ~ACER_CAP_BRIGHTNESS; 1956 interface->capability &= ~ACER_CAP_BRIGHTNESS;
1917 pr_info("Brightness must be controlled by " 1957 pr_info("Brightness must be controlled by "
1918 "generic video driver\n"); 1958 "generic video driver\n");
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index fa6d7ec68b26..edaccad9b5bf 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor 5 * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
6 * Copyright (C) 2006-2007 Corentin Chary 6 * Copyright (C) 2006-2007 Corentin Chary
7 * Copyright (C) 2011 Wind River Systems
7 * 8 *
8 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -48,6 +49,7 @@
48#include <linux/uaccess.h> 49#include <linux/uaccess.h>
49#include <linux/input.h> 50#include <linux/input.h>
50#include <linux/input/sparse-keymap.h> 51#include <linux/input/sparse-keymap.h>
52#include <linux/input-polldev.h>
51#include <linux/rfkill.h> 53#include <linux/rfkill.h>
52#include <linux/slab.h> 54#include <linux/slab.h>
53#include <linux/dmi.h> 55#include <linux/dmi.h>
@@ -83,26 +85,32 @@ static int wlan_status = 1;
83static int bluetooth_status = 1; 85static int bluetooth_status = 1;
84static int wimax_status = -1; 86static int wimax_status = -1;
85static int wwan_status = -1; 87static int wwan_status = -1;
88static int als_status;
86 89
87module_param(wlan_status, int, 0444); 90module_param(wlan_status, int, 0444);
88MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " 91MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
89 "(0 = disabled, 1 = enabled, -1 = don't do anything). " 92 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
90 "default is 1"); 93 "default is -1");
91 94
92module_param(bluetooth_status, int, 0444); 95module_param(bluetooth_status, int, 0444);
93MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " 96MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
94 "(0 = disabled, 1 = enabled, -1 = don't do anything). " 97 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
95 "default is 1"); 98 "default is -1");
96 99
97module_param(wimax_status, int, 0444); 100module_param(wimax_status, int, 0444);
98MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot " 101MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot "
99 "(0 = disabled, 1 = enabled, -1 = don't do anything). " 102 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
100 "default is 1"); 103 "default is -1");
101 104
102module_param(wwan_status, int, 0444); 105module_param(wwan_status, int, 0444);
103MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot " 106MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
104 "(0 = disabled, 1 = enabled, -1 = don't do anything). " 107 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
105 "default is 1"); 108 "default is -1");
109
110module_param(als_status, int, 0444);
111MODULE_PARM_DESC(als_status, "Set the ALS status on boot "
112 "(0 = disabled, 1 = enabled). "
113 "default is 0");
106 114
107/* 115/*
108 * Some events we use, same for all Asus 116 * Some events we use, same for all Asus
@@ -173,6 +181,29 @@ MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
173#define METHOD_KBD_LIGHT_SET "SLKB" 181#define METHOD_KBD_LIGHT_SET "SLKB"
174#define METHOD_KBD_LIGHT_GET "GLKB" 182#define METHOD_KBD_LIGHT_GET "GLKB"
175 183
184/* For Pegatron Lucid tablet */
185#define DEVICE_NAME_PEGA "Lucid"
186
187#define METHOD_PEGA_ENABLE "ENPR"
188#define METHOD_PEGA_DISABLE "DAPR"
189#define PEGA_WLAN 0x00
190#define PEGA_BLUETOOTH 0x01
191#define PEGA_WWAN 0x02
192#define PEGA_ALS 0x04
193#define PEGA_ALS_POWER 0x05
194
195#define METHOD_PEGA_READ "RDLN"
196#define PEGA_READ_ALS_H 0x02
197#define PEGA_READ_ALS_L 0x03
198
199#define PEGA_ACCEL_NAME "pega_accel"
200#define PEGA_ACCEL_DESC "Pegatron Lucid Tablet Accelerometer"
201#define METHOD_XLRX "XLRX"
202#define METHOD_XLRY "XLRY"
203#define METHOD_XLRZ "XLRZ"
204#define PEGA_ACC_CLAMP 512 /* 1G accel is reported as ~256, so clamp to 2G */
205#define PEGA_ACC_RETRIES 3
206
176/* 207/*
177 * Define a specific led structure to keep the main structure clean 208 * Define a specific led structure to keep the main structure clean
178 */ 209 */
@@ -185,6 +216,15 @@ struct asus_led {
185}; 216};
186 217
187/* 218/*
219 * Same thing for rfkill
220 */
221struct asus_pega_rfkill {
222 int control_id; /* type of control. Maps to PEGA_* values */
223 struct rfkill *rfkill;
224 struct asus_laptop *asus;
225};
226
227/*
188 * This is the main structure, we can use it to store anything interesting 228 * This is the main structure, we can use it to store anything interesting
189 * about the hotk device 229 * about the hotk device
190 */ 230 */
@@ -198,6 +238,7 @@ struct asus_laptop {
198 238
199 struct input_dev *inputdev; 239 struct input_dev *inputdev;
200 struct key_entry *keymap; 240 struct key_entry *keymap;
241 struct input_polled_dev *pega_accel_poll;
201 242
202 struct asus_led mled; 243 struct asus_led mled;
203 struct asus_led tled; 244 struct asus_led tled;
@@ -209,9 +250,18 @@ struct asus_laptop {
209 250
210 int wireless_status; 251 int wireless_status;
211 bool have_rsts; 252 bool have_rsts;
253 bool is_pega_lucid;
254 bool pega_acc_live;
255 int pega_acc_x;
256 int pega_acc_y;
257 int pega_acc_z;
212 258
213 struct rfkill *gps_rfkill; 259 struct rfkill *gps_rfkill;
214 260
261 struct asus_pega_rfkill wlanrfk;
262 struct asus_pega_rfkill btrfk;
263 struct asus_pega_rfkill wwanrfk;
264
215 acpi_handle handle; /* the handle of the hotk device */ 265 acpi_handle handle; /* the handle of the hotk device */
216 u32 ledd_status; /* status of the LED display */ 266 u32 ledd_status; /* status of the LED display */
217 u8 light_level; /* light sensor level */ 267 u8 light_level; /* light sensor level */
@@ -323,6 +373,127 @@ static int acpi_check_handle(acpi_handle handle, const char *method,
323 return 0; 373 return 0;
324} 374}
325 375
376static bool asus_check_pega_lucid(struct asus_laptop *asus)
377{
378 return !strcmp(asus->name, DEVICE_NAME_PEGA) &&
379 !acpi_check_handle(asus->handle, METHOD_PEGA_ENABLE, NULL) &&
380 !acpi_check_handle(asus->handle, METHOD_PEGA_DISABLE, NULL) &&
381 !acpi_check_handle(asus->handle, METHOD_PEGA_READ, NULL);
382}
383
384static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable)
385{
386 char *method = enable ? METHOD_PEGA_ENABLE : METHOD_PEGA_DISABLE;
387 return write_acpi_int(asus->handle, method, unit);
388}
389
390static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method)
391{
392 int i, delta;
393 unsigned long long val;
394 for (i = 0; i < PEGA_ACC_RETRIES; i++) {
395 acpi_evaluate_integer(asus->handle, method, NULL, &val);
396
397 /* The output is noisy. From reading the ASL
398 * dissassembly, timeout errors are returned with 1's
399 * in the high word, and the lack of locking around
400 * thei hi/lo byte reads means that a transition
401 * between (for example) -1 and 0 could be read as
402 * 0xff00 or 0x00ff. */
403 delta = abs(curr - (short)val);
404 if (delta < 128 && !(val & ~0xffff))
405 break;
406 }
407 return clamp_val((short)val, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP);
408}
409
410static void pega_accel_poll(struct input_polled_dev *ipd)
411{
412 struct device *parent = ipd->input->dev.parent;
413 struct asus_laptop *asus = dev_get_drvdata(parent);
414
415 /* In some cases, the very first call to poll causes a
416 * recursive fault under the polldev worker. This is
417 * apparently related to very early userspace access to the
418 * device, and perhaps a firmware bug. Fake the first report. */
419 if (!asus->pega_acc_live) {
420 asus->pega_acc_live = true;
421 input_report_abs(ipd->input, ABS_X, 0);
422 input_report_abs(ipd->input, ABS_Y, 0);
423 input_report_abs(ipd->input, ABS_Z, 0);
424 input_sync(ipd->input);
425 return;
426 }
427
428 asus->pega_acc_x = pega_acc_axis(asus, asus->pega_acc_x, METHOD_XLRX);
429 asus->pega_acc_y = pega_acc_axis(asus, asus->pega_acc_y, METHOD_XLRY);
430 asus->pega_acc_z = pega_acc_axis(asus, asus->pega_acc_z, METHOD_XLRZ);
431
432 /* Note transform, convert to "right/up/out" in the native
433 * landscape orientation (i.e. the vector is the direction of
434 * "real up" in the device's cartiesian coordinates). */
435 input_report_abs(ipd->input, ABS_X, -asus->pega_acc_x);
436 input_report_abs(ipd->input, ABS_Y, -asus->pega_acc_y);
437 input_report_abs(ipd->input, ABS_Z, asus->pega_acc_z);
438 input_sync(ipd->input);
439}
440
441static void pega_accel_exit(struct asus_laptop *asus)
442{
443 if (asus->pega_accel_poll) {
444 input_unregister_polled_device(asus->pega_accel_poll);
445 input_free_polled_device(asus->pega_accel_poll);
446 }
447 asus->pega_accel_poll = NULL;
448}
449
450static int pega_accel_init(struct asus_laptop *asus)
451{
452 int err;
453 struct input_polled_dev *ipd;
454
455 if (!asus->is_pega_lucid)
456 return -ENODEV;
457
458 if (acpi_check_handle(asus->handle, METHOD_XLRX, NULL) ||
459 acpi_check_handle(asus->handle, METHOD_XLRY, NULL) ||
460 acpi_check_handle(asus->handle, METHOD_XLRZ, NULL))
461 return -ENODEV;
462
463 ipd = input_allocate_polled_device();
464 if (!ipd)
465 return -ENOMEM;
466
467 ipd->poll = pega_accel_poll;
468 ipd->poll_interval = 125;
469 ipd->poll_interval_min = 50;
470 ipd->poll_interval_max = 2000;
471
472 ipd->input->name = PEGA_ACCEL_DESC;
473 ipd->input->phys = PEGA_ACCEL_NAME "/input0";
474 ipd->input->dev.parent = &asus->platform_device->dev;
475 ipd->input->id.bustype = BUS_HOST;
476
477 set_bit(EV_ABS, ipd->input->evbit);
478 input_set_abs_params(ipd->input, ABS_X,
479 -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
480 input_set_abs_params(ipd->input, ABS_Y,
481 -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
482 input_set_abs_params(ipd->input, ABS_Z,
483 -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
484
485 err = input_register_polled_device(ipd);
486 if (err)
487 goto exit;
488
489 asus->pega_accel_poll = ipd;
490 return 0;
491
492exit:
493 input_free_polled_device(ipd);
494 return err;
495}
496
326/* Generic LED function */ 497/* Generic LED function */
327static int asus_led_set(struct asus_laptop *asus, const char *method, 498static int asus_led_set(struct asus_laptop *asus, const char *method,
328 int value) 499 int value)
@@ -430,17 +601,17 @@ static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev)
430 601
431static void asus_led_exit(struct asus_laptop *asus) 602static void asus_led_exit(struct asus_laptop *asus)
432{ 603{
433 if (asus->mled.led.dev) 604 if (!IS_ERR_OR_NULL(asus->mled.led.dev))
434 led_classdev_unregister(&asus->mled.led); 605 led_classdev_unregister(&asus->mled.led);
435 if (asus->tled.led.dev) 606 if (!IS_ERR_OR_NULL(asus->tled.led.dev))
436 led_classdev_unregister(&asus->tled.led); 607 led_classdev_unregister(&asus->tled.led);
437 if (asus->pled.led.dev) 608 if (!IS_ERR_OR_NULL(asus->pled.led.dev))
438 led_classdev_unregister(&asus->pled.led); 609 led_classdev_unregister(&asus->pled.led);
439 if (asus->rled.led.dev) 610 if (!IS_ERR_OR_NULL(asus->rled.led.dev))
440 led_classdev_unregister(&asus->rled.led); 611 led_classdev_unregister(&asus->rled.led);
441 if (asus->gled.led.dev) 612 if (!IS_ERR_OR_NULL(asus->gled.led.dev))
442 led_classdev_unregister(&asus->gled.led); 613 led_classdev_unregister(&asus->gled.led);
443 if (asus->kled.led.dev) 614 if (!IS_ERR_OR_NULL(asus->kled.led.dev))
444 led_classdev_unregister(&asus->kled.led); 615 led_classdev_unregister(&asus->kled.led);
445 if (asus->led_workqueue) { 616 if (asus->led_workqueue) {
446 destroy_workqueue(asus->led_workqueue); 617 destroy_workqueue(asus->led_workqueue);
@@ -474,6 +645,13 @@ static int asus_led_init(struct asus_laptop *asus)
474 int r; 645 int r;
475 646
476 /* 647 /*
648 * The Pegatron Lucid has no physical leds, but all methods are
649 * available in the DSDT...
650 */
651 if (asus->is_pega_lucid)
652 return 0;
653
654 /*
477 * Functions that actually update the LED's are called from a 655 * Functions that actually update the LED's are called from a
478 * workqueue. By doing this as separate work rather than when the LED 656 * workqueue. By doing this as separate work rather than when the LED
479 * subsystem asks, we avoid messing with the Asus ACPI stuff during a 657 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
@@ -907,8 +1085,18 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
907 */ 1085 */
908static void asus_als_switch(struct asus_laptop *asus, int value) 1086static void asus_als_switch(struct asus_laptop *asus, int value)
909{ 1087{
910 if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value)) 1088 int ret;
911 pr_warn("Error setting light sensor switch\n"); 1089
1090 if (asus->is_pega_lucid) {
1091 ret = asus_pega_lucid_set(asus, PEGA_ALS, value);
1092 if (!ret)
1093 ret = asus_pega_lucid_set(asus, PEGA_ALS_POWER, value);
1094 } else {
1095 ret = write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value);
1096 }
1097 if (ret)
1098 pr_warning("Error setting light sensor switch\n");
1099
912 asus->light_switch = value; 1100 asus->light_switch = value;
913} 1101}
914 1102
@@ -964,6 +1152,35 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
964 return rv; 1152 return rv;
965} 1153}
966 1154
1155static int pega_int_read(struct asus_laptop *asus, int arg, int *result)
1156{
1157 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1158 int err = write_acpi_int_ret(asus->handle, METHOD_PEGA_READ, arg,
1159 &buffer);
1160 if (!err) {
1161 union acpi_object *obj = buffer.pointer;
1162 if (obj && obj->type == ACPI_TYPE_INTEGER)
1163 *result = obj->integer.value;
1164 else
1165 err = -EIO;
1166 }
1167 return err;
1168}
1169
1170static ssize_t show_lsvalue(struct device *dev,
1171 struct device_attribute *attr, char *buf)
1172{
1173 struct asus_laptop *asus = dev_get_drvdata(dev);
1174 int err, hi, lo;
1175
1176 err = pega_int_read(asus, PEGA_READ_ALS_H, &hi);
1177 if (!err)
1178 err = pega_int_read(asus, PEGA_READ_ALS_L, &lo);
1179 if (!err)
1180 return sprintf(buf, "%d\n", 10 * hi + lo);
1181 return err;
1182}
1183
967/* 1184/*
968 * GPS 1185 * GPS
969 */ 1186 */
@@ -1062,6 +1279,86 @@ static int asus_rfkill_init(struct asus_laptop *asus)
1062 return result; 1279 return result;
1063} 1280}
1064 1281
1282static int pega_rfkill_set(void *data, bool blocked)
1283{
1284 struct asus_pega_rfkill *pega_rfk = data;
1285
1286 int ret = asus_pega_lucid_set(pega_rfk->asus, pega_rfk->control_id, !blocked);
1287 pr_warn("Setting rfkill %d, to %d; returned %d\n", pega_rfk->control_id, !blocked, ret);
1288
1289 return ret;
1290}
1291
1292static const struct rfkill_ops pega_rfkill_ops = {
1293 .set_block = pega_rfkill_set,
1294};
1295
1296static void pega_rfkill_terminate(struct asus_pega_rfkill *pega_rfk)
1297{
1298 pr_warn("Terminating %d\n", pega_rfk->control_id);
1299 if (pega_rfk->rfkill) {
1300 rfkill_unregister(pega_rfk->rfkill);
1301 rfkill_destroy(pega_rfk->rfkill);
1302 pega_rfk->rfkill = NULL;
1303 }
1304}
1305
1306static void pega_rfkill_exit(struct asus_laptop *asus)
1307{
1308 pega_rfkill_terminate(&asus->wwanrfk);
1309 pega_rfkill_terminate(&asus->btrfk);
1310 pega_rfkill_terminate(&asus->wlanrfk);
1311}
1312
1313static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_pega_rfkill *pega_rfk,
1314 const char *name, int controlid, int rfkill_type)
1315{
1316 int result;
1317
1318 pr_warn("Setting up rfk %s, control %d, type %d\n", name, controlid, rfkill_type);
1319 pega_rfk->control_id = controlid;
1320 pega_rfk->asus = asus;
1321 pega_rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev,
1322 rfkill_type, &pega_rfkill_ops, pega_rfk);
1323 if (!pega_rfk->rfkill)
1324 return -EINVAL;
1325
1326 result = rfkill_register(pega_rfk->rfkill);
1327 if (result) {
1328 rfkill_destroy(pega_rfk->rfkill);
1329 pega_rfk->rfkill = NULL;
1330 }
1331
1332 return result;
1333}
1334
1335static int pega_rfkill_init(struct asus_laptop *asus)
1336{
1337 int ret = 0;
1338
1339 if(!asus->is_pega_lucid)
1340 return -ENODEV;
1341
1342 ret = pega_rfkill_setup(asus, &asus->wlanrfk, "pega-wlan", PEGA_WLAN, RFKILL_TYPE_WLAN);
1343 if(ret)
1344 return ret;
1345 ret = pega_rfkill_setup(asus, &asus->btrfk, "pega-bt", PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH);
1346 if(ret)
1347 goto err_btrfk;
1348 ret = pega_rfkill_setup(asus, &asus->wwanrfk, "pega-wwan", PEGA_WWAN, RFKILL_TYPE_WWAN);
1349 if(ret)
1350 goto err_wwanrfk;
1351
1352 pr_warn("Pega rfkill init succeeded\n");
1353 return 0;
1354err_wwanrfk:
1355 pega_rfkill_terminate(&asus->btrfk);
1356err_btrfk:
1357 pega_rfkill_terminate(&asus->wlanrfk);
1358
1359 return ret;
1360}
1361
1065/* 1362/*
1066 * Input device (i.e. hotkeys) 1363 * Input device (i.e. hotkeys)
1067 */ 1364 */
@@ -1141,6 +1438,14 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
1141 } 1438 }
1142 return ; 1439 return ;
1143 } 1440 }
1441
1442 /* Accelerometer "coarse orientation change" event */
1443 if (asus->pega_accel_poll && event == 0xEA) {
1444 kobject_uevent(&asus->pega_accel_poll->input->dev.kobj,
1445 KOBJ_CHANGE);
1446 return ;
1447 }
1448
1144 asus_input_notify(asus, event); 1449 asus_input_notify(asus, event);
1145} 1450}
1146 1451
@@ -1152,6 +1457,7 @@ static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
1152static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan); 1457static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
1153static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp); 1458static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp);
1154static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); 1459static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
1460static DEVICE_ATTR(ls_value, S_IRUGO, show_lsvalue, NULL);
1155static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); 1461static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
1156static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw); 1462static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
1157static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps); 1463static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
@@ -1164,6 +1470,7 @@ static struct attribute *asus_attributes[] = {
1164 &dev_attr_wwan.attr, 1470 &dev_attr_wwan.attr,
1165 &dev_attr_display.attr, 1471 &dev_attr_display.attr,
1166 &dev_attr_ledd.attr, 1472 &dev_attr_ledd.attr,
1473 &dev_attr_ls_value.attr,
1167 &dev_attr_ls_level.attr, 1474 &dev_attr_ls_level.attr,
1168 &dev_attr_ls_switch.attr, 1475 &dev_attr_ls_switch.attr,
1169 &dev_attr_gps.attr, 1476 &dev_attr_gps.attr,
@@ -1180,6 +1487,19 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj,
1180 acpi_handle handle = asus->handle; 1487 acpi_handle handle = asus->handle;
1181 bool supported; 1488 bool supported;
1182 1489
1490 if (asus->is_pega_lucid) {
1491 /* no ls_level interface on the Lucid */
1492 if (attr == &dev_attr_ls_switch.attr)
1493 supported = true;
1494 else if (attr == &dev_attr_ls_level.attr)
1495 supported = false;
1496 else
1497 goto normal;
1498
1499 return supported;
1500 }
1501
1502normal:
1183 if (attr == &dev_attr_wlan.attr) { 1503 if (attr == &dev_attr_wlan.attr) {
1184 supported = !acpi_check_handle(handle, METHOD_WLAN, NULL); 1504 supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
1185 1505
@@ -1202,8 +1522,9 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj,
1202 } else if (attr == &dev_attr_ls_switch.attr || 1522 } else if (attr == &dev_attr_ls_switch.attr ||
1203 attr == &dev_attr_ls_level.attr) { 1523 attr == &dev_attr_ls_level.attr) {
1204 supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) && 1524 supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
1205 !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL); 1525 !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
1206 1526 } else if (attr == &dev_attr_ls_value.attr) {
1527 supported = asus->is_pega_lucid;
1207 } else if (attr == &dev_attr_gps.attr) { 1528 } else if (attr == &dev_attr_gps.attr) {
1208 supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) && 1529 supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
1209 !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) && 1530 !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
@@ -1258,7 +1579,7 @@ static struct platform_driver platform_driver = {
1258 .driver = { 1579 .driver = {
1259 .name = ASUS_LAPTOP_FILE, 1580 .name = ASUS_LAPTOP_FILE,
1260 .owner = THIS_MODULE, 1581 .owner = THIS_MODULE,
1261 } 1582 },
1262}; 1583};
1263 1584
1264/* 1585/*
@@ -1388,11 +1709,13 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
1388 asus->ledd_status = 0xFFF; 1709 asus->ledd_status = 0xFFF;
1389 1710
1390 /* Set initial values of light sensor and level */ 1711 /* Set initial values of light sensor and level */
1391 asus->light_switch = 0; /* Default to light sensor disabled */ 1712 asus->light_switch = !!als_status;
1392 asus->light_level = 5; /* level 5 for sensor sensitivity */ 1713 asus->light_level = 5; /* level 5 for sensor sensitivity */
1393 1714
1394 if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && 1715 if (asus->is_pega_lucid) {
1395 !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { 1716 asus_als_switch(asus, asus->light_switch);
1717 } else if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
1718 !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
1396 asus_als_switch(asus, asus->light_switch); 1719 asus_als_switch(asus, asus->light_switch);
1397 asus_als_level(asus, asus->light_level); 1720 asus_als_level(asus, asus->light_level);
1398 } 1721 }
@@ -1439,9 +1762,10 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
1439 goto fail_platform; 1762 goto fail_platform;
1440 1763
1441 /* 1764 /*
1442 * Register the platform device first. It is used as a parent for the 1765 * Need platform type detection first, then the platform
1443 * sub-devices below. 1766 * device. It is used as a parent for the sub-devices below.
1444 */ 1767 */
1768 asus->is_pega_lucid = asus_check_pega_lucid(asus);
1445 result = asus_platform_init(asus); 1769 result = asus_platform_init(asus);
1446 if (result) 1770 if (result)
1447 goto fail_platform; 1771 goto fail_platform;
@@ -1465,9 +1789,21 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
1465 if (result) 1789 if (result)
1466 goto fail_rfkill; 1790 goto fail_rfkill;
1467 1791
1792 result = pega_accel_init(asus);
1793 if (result && result != -ENODEV)
1794 goto fail_pega_accel;
1795
1796 result = pega_rfkill_init(asus);
1797 if (result && result != -ENODEV)
1798 goto fail_pega_rfkill;
1799
1468 asus_device_present = true; 1800 asus_device_present = true;
1469 return 0; 1801 return 0;
1470 1802
1803fail_pega_rfkill:
1804 pega_accel_exit(asus);
1805fail_pega_accel:
1806 asus_rfkill_exit(asus);
1471fail_rfkill: 1807fail_rfkill:
1472 asus_led_exit(asus); 1808 asus_led_exit(asus);
1473fail_led: 1809fail_led:
@@ -1491,6 +1827,8 @@ static int asus_acpi_remove(struct acpi_device *device, int type)
1491 asus_rfkill_exit(asus); 1827 asus_rfkill_exit(asus);
1492 asus_led_exit(asus); 1828 asus_led_exit(asus);
1493 asus_input_exit(asus); 1829 asus_input_exit(asus);
1830 pega_accel_exit(asus);
1831 pega_rfkill_exit(asus);
1494 asus_platform_exit(asus); 1832 asus_platform_exit(asus);
1495 1833
1496 kfree(asus->name); 1834 kfree(asus->name);
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 95cba9ebf6c0..d1049ee3c9e8 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -453,7 +453,9 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
453 453
454static void asus_wmi_led_exit(struct asus_wmi *asus) 454static void asus_wmi_led_exit(struct asus_wmi *asus)
455{ 455{
456 if (asus->tpd_led.dev) 456 if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
457 led_classdev_unregister(&asus->kbd_led);
458 if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
457 led_classdev_unregister(&asus->tpd_led); 459 led_classdev_unregister(&asus->tpd_led);
458 if (asus->led_workqueue) 460 if (asus->led_workqueue)
459 destroy_workqueue(asus->led_workqueue); 461 destroy_workqueue(asus->led_workqueue);
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index f31fa4efa725..a43cfd906c6d 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -60,6 +60,22 @@ struct calling_interface_structure {
60 struct calling_interface_token tokens[]; 60 struct calling_interface_token tokens[];
61} __packed; 61} __packed;
62 62
63struct quirk_entry {
64 u8 touchpad_led;
65};
66
67static struct quirk_entry *quirks;
68
69static struct quirk_entry quirk_dell_vostro_v130 = {
70 .touchpad_led = 1,
71};
72
73static int dmi_matched(const struct dmi_system_id *dmi)
74{
75 quirks = dmi->driver_data;
76 return 1;
77}
78
63static int da_command_address; 79static int da_command_address;
64static int da_command_code; 80static int da_command_code;
65static int da_num_tokens; 81static int da_num_tokens;
@@ -149,6 +165,27 @@ static struct dmi_system_id __devinitdata dell_blacklist[] = {
149 {} 165 {}
150}; 166};
151 167
168static struct dmi_system_id __devinitdata dell_quirks[] = {
169 {
170 .callback = dmi_matched,
171 .ident = "Dell Vostro V130",
172 .matches = {
173 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
174 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"),
175 },
176 .driver_data = &quirk_dell_vostro_v130,
177 },
178 {
179 .callback = dmi_matched,
180 .ident = "Dell Vostro V131",
181 .matches = {
182 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
183 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
184 },
185 .driver_data = &quirk_dell_vostro_v130,
186 },
187};
188
152static struct calling_interface_buffer *buffer; 189static struct calling_interface_buffer *buffer;
153static struct page *bufferpage; 190static struct page *bufferpage;
154static DEFINE_MUTEX(buffer_mutex); 191static DEFINE_MUTEX(buffer_mutex);
@@ -552,6 +589,44 @@ static const struct backlight_ops dell_ops = {
552 .update_status = dell_send_intensity, 589 .update_status = dell_send_intensity,
553}; 590};
554 591
592static void touchpad_led_on()
593{
594 int command = 0x97;
595 char data = 1;
596 i8042_command(&data, command | 1 << 12);
597}
598
599static void touchpad_led_off()
600{
601 int command = 0x97;
602 char data = 2;
603 i8042_command(&data, command | 1 << 12);
604}
605
606static void touchpad_led_set(struct led_classdev *led_cdev,
607 enum led_brightness value)
608{
609 if (value > 0)
610 touchpad_led_on();
611 else
612 touchpad_led_off();
613}
614
615static struct led_classdev touchpad_led = {
616 .name = "dell-laptop::touchpad",
617 .brightness_set = touchpad_led_set,
618};
619
620static int __devinit touchpad_led_init(struct device *dev)
621{
622 return led_classdev_register(dev, &touchpad_led);
623}
624
625static void touchpad_led_exit(void)
626{
627 led_classdev_unregister(&touchpad_led);
628}
629
555static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, 630static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
556 struct serio *port) 631 struct serio *port)
557{ 632{
@@ -584,6 +659,10 @@ static int __init dell_init(void)
584 if (!dmi_check_system(dell_device_table)) 659 if (!dmi_check_system(dell_device_table))
585 return -ENODEV; 660 return -ENODEV;
586 661
662 quirks = NULL;
663 /* find if this machine support other functions */
664 dmi_check_system(dell_quirks);
665
587 dmi_walk(find_tokens, NULL); 666 dmi_walk(find_tokens, NULL);
588 667
589 if (!da_tokens) { 668 if (!da_tokens) {
@@ -626,6 +705,9 @@ static int __init dell_init(void)
626 goto fail_filter; 705 goto fail_filter;
627 } 706 }
628 707
708 if (quirks && quirks->touchpad_led)
709 touchpad_led_init(&platform_device->dev);
710
629 dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); 711 dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
630 if (dell_laptop_dir != NULL) 712 if (dell_laptop_dir != NULL)
631 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, 713 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
@@ -692,6 +774,8 @@ fail_platform_driver:
692static void __exit dell_exit(void) 774static void __exit dell_exit(void)
693{ 775{
694 debugfs_remove_recursive(dell_laptop_dir); 776 debugfs_remove_recursive(dell_laptop_dir);
777 if (quirks && quirks->touchpad_led)
778 touchpad_led_exit();
695 i8042_remove_filter(dell_laptop_i8042_filter); 779 i8042_remove_filter(dell_laptop_i8042_filter);
696 cancel_delayed_work_sync(&dell_rfkill_work); 780 cancel_delayed_work_sync(&dell_rfkill_work);
697 backlight_device_unregister(dell_backlight_device); 781 backlight_device_unregister(dell_backlight_device);
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 1c45d92e2163..ea44abd8df48 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -568,7 +568,7 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc)
568 568
569static void eeepc_led_exit(struct eeepc_laptop *eeepc) 569static void eeepc_led_exit(struct eeepc_laptop *eeepc)
570{ 570{
571 if (eeepc->tpd_led.dev) 571 if (!IS_ERR_OR_NULL(eeepc->tpd_led.dev))
572 led_classdev_unregister(&eeepc->tpd_led); 572 led_classdev_unregister(&eeepc->tpd_led);
573 if (eeepc->led_workqueue) 573 if (eeepc->led_workqueue)
574 destroy_workqueue(eeepc->led_workqueue); 574 destroy_workqueue(eeepc->led_workqueue);
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 1b52d00e2f90..64b454855f65 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -76,6 +76,7 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
76/* For automatic insertion of the module */ 76/* For automatic insertion of the module */
77static struct acpi_device_id lis3lv02d_device_ids[] = { 77static struct acpi_device_id lis3lv02d_device_ids[] = {
78 {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ 78 {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
79 {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */
79 {"", 0}, 80 {"", 0},
80}; 81};
81MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); 82MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
@@ -228,6 +229,10 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
228 AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap), 229 AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
229 AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted), 230 AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
230 AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd), 231 AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
232 AXIS_DMI_MATCH("HPB63xx", "HP ProBook 63", xy_swap),
233 AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap),
234 AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap),
235 AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted),
231 { NULL, } 236 { NULL, }
232/* Laptop models without axis info (yet): 237/* Laptop models without axis info (yet):
233 * "NC6910" "HP Compaq 6910" 238 * "NC6910" "HP Compaq 6910"
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 0c595410e788..a36addf106a0 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -34,6 +34,8 @@
34#include <linux/input/sparse-keymap.h> 34#include <linux/input/sparse-keymap.h>
35#include <linux/backlight.h> 35#include <linux/backlight.h>
36#include <linux/fb.h> 36#include <linux/fb.h>
37#include <linux/debugfs.h>
38#include <linux/seq_file.h>
37 39
38#define IDEAPAD_RFKILL_DEV_NUM (3) 40#define IDEAPAD_RFKILL_DEV_NUM (3)
39 41
@@ -42,15 +44,41 @@
42#define CFG_WIFI_BIT (18) 44#define CFG_WIFI_BIT (18)
43#define CFG_CAMERA_BIT (19) 45#define CFG_CAMERA_BIT (19)
44 46
47enum {
48 VPCCMD_R_VPC1 = 0x10,
49 VPCCMD_R_BL_MAX,
50 VPCCMD_R_BL,
51 VPCCMD_W_BL,
52 VPCCMD_R_WIFI,
53 VPCCMD_W_WIFI,
54 VPCCMD_R_BT,
55 VPCCMD_W_BT,
56 VPCCMD_R_BL_POWER,
57 VPCCMD_R_NOVO,
58 VPCCMD_R_VPC2,
59 VPCCMD_R_TOUCHPAD,
60 VPCCMD_W_TOUCHPAD,
61 VPCCMD_R_CAMERA,
62 VPCCMD_W_CAMERA,
63 VPCCMD_R_3G,
64 VPCCMD_W_3G,
65 VPCCMD_R_ODD, /* 0x21 */
66 VPCCMD_R_RF = 0x23,
67 VPCCMD_W_RF,
68 VPCCMD_W_BL_POWER = 0x33,
69};
70
45struct ideapad_private { 71struct ideapad_private {
46 struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; 72 struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
47 struct platform_device *platform_device; 73 struct platform_device *platform_device;
48 struct input_dev *inputdev; 74 struct input_dev *inputdev;
49 struct backlight_device *blightdev; 75 struct backlight_device *blightdev;
76 struct dentry *debug;
50 unsigned long cfg; 77 unsigned long cfg;
51}; 78};
52 79
53static acpi_handle ideapad_handle; 80static acpi_handle ideapad_handle;
81static struct ideapad_private *ideapad_priv;
54static bool no_bt_rfkill; 82static bool no_bt_rfkill;
55module_param(no_bt_rfkill, bool, 0444); 83module_param(no_bt_rfkill, bool, 0444);
56MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); 84MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
@@ -164,6 +192,146 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
164} 192}
165 193
166/* 194/*
195 * debugfs
196 */
197#define DEBUGFS_EVENT_LEN (4096)
198static int debugfs_status_show(struct seq_file *s, void *data)
199{
200 unsigned long value;
201
202 if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value))
203 seq_printf(s, "Backlight max:\t%lu\n", value);
204 if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value))
205 seq_printf(s, "Backlight now:\t%lu\n", value);
206 if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value))
207 seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
208 seq_printf(s, "=====================\n");
209
210 if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value))
211 seq_printf(s, "Radio status:\t%s(%lu)\n",
212 value ? "On" : "Off", value);
213 if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value))
214 seq_printf(s, "Wifi status:\t%s(%lu)\n",
215 value ? "On" : "Off", value);
216 if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value))
217 seq_printf(s, "BT status:\t%s(%lu)\n",
218 value ? "On" : "Off", value);
219 if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value))
220 seq_printf(s, "3G status:\t%s(%lu)\n",
221 value ? "On" : "Off", value);
222 seq_printf(s, "=====================\n");
223
224 if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value))
225 seq_printf(s, "Touchpad status:%s(%lu)\n",
226 value ? "On" : "Off", value);
227 if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value))
228 seq_printf(s, "Camera status:\t%s(%lu)\n",
229 value ? "On" : "Off", value);
230
231 return 0;
232}
233
234static int debugfs_status_open(struct inode *inode, struct file *file)
235{
236 return single_open(file, debugfs_status_show, NULL);
237}
238
239static const struct file_operations debugfs_status_fops = {
240 .owner = THIS_MODULE,
241 .open = debugfs_status_open,
242 .read = seq_read,
243 .llseek = seq_lseek,
244 .release = single_release,
245};
246
247static int debugfs_cfg_show(struct seq_file *s, void *data)
248{
249 if (!ideapad_priv) {
250 seq_printf(s, "cfg: N/A\n");
251 } else {
252 seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
253 ideapad_priv->cfg);
254 if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg))
255 seq_printf(s, "Bluetooth ");
256 if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg))
257 seq_printf(s, "3G ");
258 if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg))
259 seq_printf(s, "Wireless ");
260 if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg))
261 seq_printf(s, "Camera ");
262 seq_printf(s, "\nGraphic: ");
263 switch ((ideapad_priv->cfg)&0x700) {
264 case 0x100:
265 seq_printf(s, "Intel");
266 break;
267 case 0x200:
268 seq_printf(s, "ATI");
269 break;
270 case 0x300:
271 seq_printf(s, "Nvidia");
272 break;
273 case 0x400:
274 seq_printf(s, "Intel and ATI");
275 break;
276 case 0x500:
277 seq_printf(s, "Intel and Nvidia");
278 break;
279 }
280 seq_printf(s, "\n");
281 }
282 return 0;
283}
284
285static int debugfs_cfg_open(struct inode *inode, struct file *file)
286{
287 return single_open(file, debugfs_cfg_show, NULL);
288}
289
290static const struct file_operations debugfs_cfg_fops = {
291 .owner = THIS_MODULE,
292 .open = debugfs_cfg_open,
293 .read = seq_read,
294 .llseek = seq_lseek,
295 .release = single_release,
296};
297
298static int __devinit ideapad_debugfs_init(struct ideapad_private *priv)
299{
300 struct dentry *node;
301
302 priv->debug = debugfs_create_dir("ideapad", NULL);
303 if (priv->debug == NULL) {
304 pr_err("failed to create debugfs directory");
305 goto errout;
306 }
307
308 node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL,
309 &debugfs_cfg_fops);
310 if (!node) {
311 pr_err("failed to create cfg in debugfs");
312 goto errout;
313 }
314
315 node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL,
316 &debugfs_status_fops);
317 if (!node) {
318 pr_err("failed to create event in debugfs");
319 goto errout;
320 }
321
322 return 0;
323
324errout:
325 return -ENOMEM;
326}
327
328static void ideapad_debugfs_exit(struct ideapad_private *priv)
329{
330 debugfs_remove_recursive(priv->debug);
331 priv->debug = NULL;
332}
333
334/*
167 * sysfs 335 * sysfs
168 */ 336 */
169static ssize_t show_ideapad_cam(struct device *dev, 337static ssize_t show_ideapad_cam(struct device *dev,
@@ -172,7 +340,7 @@ static ssize_t show_ideapad_cam(struct device *dev,
172{ 340{
173 unsigned long result; 341 unsigned long result;
174 342
175 if (read_ec_data(ideapad_handle, 0x1D, &result)) 343 if (read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &result))
176 return sprintf(buf, "-1\n"); 344 return sprintf(buf, "-1\n");
177 return sprintf(buf, "%lu\n", result); 345 return sprintf(buf, "%lu\n", result);
178} 346}
@@ -187,7 +355,7 @@ static ssize_t store_ideapad_cam(struct device *dev,
187 return 0; 355 return 0;
188 if (sscanf(buf, "%i", &state) != 1) 356 if (sscanf(buf, "%i", &state) != 1)
189 return -EINVAL; 357 return -EINVAL;
190 ret = write_ec_cmd(ideapad_handle, 0x1E, state); 358 ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state);
191 if (ret < 0) 359 if (ret < 0)
192 return ret; 360 return ret;
193 return count; 361 return count;
@@ -195,20 +363,8 @@ static ssize_t store_ideapad_cam(struct device *dev,
195 363
196static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam); 364static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
197 365
198static ssize_t show_ideapad_cfg(struct device *dev,
199 struct device_attribute *attr,
200 char *buf)
201{
202 struct ideapad_private *priv = dev_get_drvdata(dev);
203
204 return sprintf(buf, "0x%.8lX\n", priv->cfg);
205}
206
207static DEVICE_ATTR(cfg, 0444, show_ideapad_cfg, NULL);
208
209static struct attribute *ideapad_attributes[] = { 366static struct attribute *ideapad_attributes[] = {
210 &dev_attr_camera_power.attr, 367 &dev_attr_camera_power.attr,
211 &dev_attr_cfg.attr,
212 NULL 368 NULL
213}; 369};
214 370
@@ -244,9 +400,9 @@ struct ideapad_rfk_data {
244}; 400};
245 401
246const struct ideapad_rfk_data ideapad_rfk_data[] = { 402const struct ideapad_rfk_data ideapad_rfk_data[] = {
247 { "ideapad_wlan", CFG_WIFI_BIT, 0x15, RFKILL_TYPE_WLAN }, 403 { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
248 { "ideapad_bluetooth", CFG_BT_BIT, 0x17, RFKILL_TYPE_BLUETOOTH }, 404 { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
249 { "ideapad_3g", CFG_3G_BIT, 0x20, RFKILL_TYPE_WWAN }, 405 { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
250}; 406};
251 407
252static int ideapad_rfk_set(void *data, bool blocked) 408static int ideapad_rfk_set(void *data, bool blocked)
@@ -260,13 +416,12 @@ static struct rfkill_ops ideapad_rfk_ops = {
260 .set_block = ideapad_rfk_set, 416 .set_block = ideapad_rfk_set,
261}; 417};
262 418
263static void ideapad_sync_rfk_state(struct acpi_device *adevice) 419static void ideapad_sync_rfk_state(struct ideapad_private *priv)
264{ 420{
265 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
266 unsigned long hw_blocked; 421 unsigned long hw_blocked;
267 int i; 422 int i;
268 423
269 if (read_ec_data(ideapad_handle, 0x23, &hw_blocked)) 424 if (read_ec_data(ideapad_handle, VPCCMD_R_RF, &hw_blocked))
270 return; 425 return;
271 hw_blocked = !hw_blocked; 426 hw_blocked = !hw_blocked;
272 427
@@ -363,8 +518,10 @@ static void ideapad_platform_exit(struct ideapad_private *priv)
363 * input device 518 * input device
364 */ 519 */
365static const struct key_entry ideapad_keymap[] = { 520static const struct key_entry ideapad_keymap[] = {
366 { KE_KEY, 0x06, { KEY_SWITCHVIDEOMODE } }, 521 { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } },
367 { KE_KEY, 0x0D, { KEY_WLAN } }, 522 { KE_KEY, 13, { KEY_WLAN } },
523 { KE_KEY, 16, { KEY_PROG1 } },
524 { KE_KEY, 17, { KEY_PROG2 } },
368 { KE_END, 0 }, 525 { KE_END, 0 },
369}; 526};
370 527
@@ -419,6 +576,18 @@ static void ideapad_input_report(struct ideapad_private *priv,
419 sparse_keymap_report_event(priv->inputdev, scancode, 1, true); 576 sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
420} 577}
421 578
579static void ideapad_input_novokey(struct ideapad_private *priv)
580{
581 unsigned long long_pressed;
582
583 if (read_ec_data(ideapad_handle, VPCCMD_R_NOVO, &long_pressed))
584 return;
585 if (long_pressed)
586 ideapad_input_report(priv, 17);
587 else
588 ideapad_input_report(priv, 16);
589}
590
422/* 591/*
423 * backlight 592 * backlight
424 */ 593 */
@@ -426,16 +595,17 @@ static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
426{ 595{
427 unsigned long now; 596 unsigned long now;
428 597
429 if (read_ec_data(ideapad_handle, 0x12, &now)) 598 if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
430 return -EIO; 599 return -EIO;
431 return now; 600 return now;
432} 601}
433 602
434static int ideapad_backlight_update_status(struct backlight_device *blightdev) 603static int ideapad_backlight_update_status(struct backlight_device *blightdev)
435{ 604{
436 if (write_ec_cmd(ideapad_handle, 0x13, blightdev->props.brightness)) 605 if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL,
606 blightdev->props.brightness))
437 return -EIO; 607 return -EIO;
438 if (write_ec_cmd(ideapad_handle, 0x33, 608 if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL_POWER,
439 blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1)) 609 blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
440 return -EIO; 610 return -EIO;
441 611
@@ -453,11 +623,11 @@ static int ideapad_backlight_init(struct ideapad_private *priv)
453 struct backlight_properties props; 623 struct backlight_properties props;
454 unsigned long max, now, power; 624 unsigned long max, now, power;
455 625
456 if (read_ec_data(ideapad_handle, 0x11, &max)) 626 if (read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &max))
457 return -EIO; 627 return -EIO;
458 if (read_ec_data(ideapad_handle, 0x12, &now)) 628 if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
459 return -EIO; 629 return -EIO;
460 if (read_ec_data(ideapad_handle, 0x18, &power)) 630 if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
461 return -EIO; 631 return -EIO;
462 632
463 memset(&props, 0, sizeof(struct backlight_properties)); 633 memset(&props, 0, sizeof(struct backlight_properties));
@@ -493,7 +663,9 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv)
493 unsigned long power; 663 unsigned long power;
494 struct backlight_device *blightdev = priv->blightdev; 664 struct backlight_device *blightdev = priv->blightdev;
495 665
496 if (read_ec_data(ideapad_handle, 0x18, &power)) 666 if (!blightdev)
667 return;
668 if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
497 return; 669 return;
498 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 670 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
499} 671}
@@ -504,7 +676,7 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
504 676
505 /* if we control brightness via acpi video driver */ 677 /* if we control brightness via acpi video driver */
506 if (priv->blightdev == NULL) { 678 if (priv->blightdev == NULL) {
507 read_ec_data(ideapad_handle, 0x12, &now); 679 read_ec_data(ideapad_handle, VPCCMD_R_BL, &now);
508 return; 680 return;
509 } 681 }
510 682
@@ -533,6 +705,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
533 if (!priv) 705 if (!priv)
534 return -ENOMEM; 706 return -ENOMEM;
535 dev_set_drvdata(&adevice->dev, priv); 707 dev_set_drvdata(&adevice->dev, priv);
708 ideapad_priv = priv;
536 ideapad_handle = adevice->handle; 709 ideapad_handle = adevice->handle;
537 priv->cfg = cfg; 710 priv->cfg = cfg;
538 711
@@ -540,6 +713,10 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
540 if (ret) 713 if (ret)
541 goto platform_failed; 714 goto platform_failed;
542 715
716 ret = ideapad_debugfs_init(priv);
717 if (ret)
718 goto debugfs_failed;
719
543 ret = ideapad_input_init(priv); 720 ret = ideapad_input_init(priv);
544 if (ret) 721 if (ret)
545 goto input_failed; 722 goto input_failed;
@@ -550,7 +727,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
550 else 727 else
551 priv->rfk[i] = NULL; 728 priv->rfk[i] = NULL;
552 } 729 }
553 ideapad_sync_rfk_state(adevice); 730 ideapad_sync_rfk_state(priv);
554 731
555 if (!acpi_video_backlight_support()) { 732 if (!acpi_video_backlight_support()) {
556 ret = ideapad_backlight_init(priv); 733 ret = ideapad_backlight_init(priv);
@@ -565,6 +742,8 @@ backlight_failed:
565 ideapad_unregister_rfkill(adevice, i); 742 ideapad_unregister_rfkill(adevice, i);
566 ideapad_input_exit(priv); 743 ideapad_input_exit(priv);
567input_failed: 744input_failed:
745 ideapad_debugfs_exit(priv);
746debugfs_failed:
568 ideapad_platform_exit(priv); 747 ideapad_platform_exit(priv);
569platform_failed: 748platform_failed:
570 kfree(priv); 749 kfree(priv);
@@ -580,6 +759,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
580 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 759 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
581 ideapad_unregister_rfkill(adevice, i); 760 ideapad_unregister_rfkill(adevice, i);
582 ideapad_input_exit(priv); 761 ideapad_input_exit(priv);
762 ideapad_debugfs_exit(priv);
583 ideapad_platform_exit(priv); 763 ideapad_platform_exit(priv);
584 dev_set_drvdata(&adevice->dev, NULL); 764 dev_set_drvdata(&adevice->dev, NULL);
585 kfree(priv); 765 kfree(priv);
@@ -593,9 +773,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
593 acpi_handle handle = adevice->handle; 773 acpi_handle handle = adevice->handle;
594 unsigned long vpc1, vpc2, vpc_bit; 774 unsigned long vpc1, vpc2, vpc_bit;
595 775
596 if (read_ec_data(handle, 0x10, &vpc1)) 776 if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
597 return; 777 return;
598 if (read_ec_data(handle, 0x1A, &vpc2)) 778 if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
599 return; 779 return;
600 780
601 vpc1 = (vpc2 << 8) | vpc1; 781 vpc1 = (vpc2 << 8) | vpc1;
@@ -603,11 +783,14 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
603 if (test_bit(vpc_bit, &vpc1)) { 783 if (test_bit(vpc_bit, &vpc1)) {
604 switch (vpc_bit) { 784 switch (vpc_bit) {
605 case 9: 785 case 9:
606 ideapad_sync_rfk_state(adevice); 786 ideapad_sync_rfk_state(priv);
607 break; 787 break;
608 case 4: 788 case 4:
609 ideapad_backlight_notify_brightness(priv); 789 ideapad_backlight_notify_brightness(priv);
610 break; 790 break;
791 case 3:
792 ideapad_input_novokey(priv);
793 break;
611 case 2: 794 case 2:
612 ideapad_backlight_notify_power(priv); 795 ideapad_backlight_notify_power(priv);
613 break; 796 break;
diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c
index b93a03259c16..2d0f9136ea9a 100644
--- a/drivers/platform/x86/intel_scu_ipcutil.c
+++ b/drivers/platform/x86/intel_scu_ipcutil.c
@@ -24,7 +24,7 @@
24#include <linux/init.h> 24#include <linux/init.h>
25#include <asm/intel_scu_ipc.h> 25#include <asm/intel_scu_ipc.h>
26 26
27static u32 major; 27static int major;
28 28
29#define MAX_FW_SIZE 264192 29#define MAX_FW_SIZE 264192
30 30
@@ -117,7 +117,11 @@ static const struct file_operations scu_ipc_fops = {
117 117
118static int __init ipc_module_init(void) 118static int __init ipc_module_init(void)
119{ 119{
120 return register_chrdev(0, "intel_mid_scu", &scu_ipc_fops); 120 major = register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
121 if (major < 0)
122 return major;
123
124 return 0;
121} 125}
122 126
123static void __exit ipc_module_exit(void) 127static void __exit ipc_module_exit(void)
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index 359163011044..09e26bfd4643 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -226,6 +226,7 @@ static struct backlight_device *backlight_device;
226static struct mutex sabi_mutex; 226static struct mutex sabi_mutex;
227static struct platform_device *sdev; 227static struct platform_device *sdev;
228static struct rfkill *rfk; 228static struct rfkill *rfk;
229static bool has_stepping_quirk;
229 230
230static int force; 231static int force;
231module_param(force, bool, 0); 232module_param(force, bool, 0);
@@ -370,15 +371,28 @@ static u8 read_brightness(void)
370 &sretval); 371 &sretval);
371 if (!retval) { 372 if (!retval) {
372 user_brightness = sretval.retval[0]; 373 user_brightness = sretval.retval[0];
373 if (user_brightness != 0) 374 if (user_brightness > sabi_config->min_brightness)
374 user_brightness -= sabi_config->min_brightness; 375 user_brightness -= sabi_config->min_brightness;
376 else
377 user_brightness = 0;
375 } 378 }
376 return user_brightness; 379 return user_brightness;
377} 380}
378 381
379static void set_brightness(u8 user_brightness) 382static void set_brightness(u8 user_brightness)
380{ 383{
381 u8 user_level = user_brightness - sabi_config->min_brightness; 384 u8 user_level = user_brightness + sabi_config->min_brightness;
385
386 if (has_stepping_quirk && user_level != 0) {
387 /*
388 * short circuit if the specified level is what's already set
389 * to prevent the screen from flickering needlessly
390 */
391 if (user_brightness == read_brightness())
392 return;
393
394 sabi_set_command(sabi_config->commands.set_brightness, 0);
395 }
382 396
383 sabi_set_command(sabi_config->commands.set_brightness, user_level); 397 sabi_set_command(sabi_config->commands.set_brightness, user_level);
384} 398}
@@ -388,6 +402,40 @@ static int get_brightness(struct backlight_device *bd)
388 return (int)read_brightness(); 402 return (int)read_brightness();
389} 403}
390 404
405static void check_for_stepping_quirk(void)
406{
407 u8 initial_level;
408 u8 check_level;
409 u8 orig_level = read_brightness();
410
411 /*
412 * Some laptops exhibit the strange behaviour of stepping toward
413 * (rather than setting) the brightness except when changing to/from
414 * brightness level 0. This behaviour is checked for here and worked
415 * around in set_brightness.
416 */
417
418 if (orig_level == 0)
419 set_brightness(1);
420
421 initial_level = read_brightness();
422
423 if (initial_level <= 2)
424 check_level = initial_level + 2;
425 else
426 check_level = initial_level - 2;
427
428 has_stepping_quirk = false;
429 set_brightness(check_level);
430
431 if (read_brightness() != check_level) {
432 has_stepping_quirk = true;
433 pr_info("enabled workaround for brightness stepping quirk\n");
434 }
435
436 set_brightness(orig_level);
437}
438
391static int update_status(struct backlight_device *bd) 439static int update_status(struct backlight_device *bd)
392{ 440{
393 set_brightness(bd->props.brightness); 441 set_brightness(bd->props.brightness);
@@ -621,6 +669,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
621 .callback = dmi_check_cb, 669 .callback = dmi_check_cb,
622 }, 670 },
623 { 671 {
672 .ident = "N220",
673 .matches = {
674 DMI_MATCH(DMI_SYS_VENDOR,
675 "SAMSUNG ELECTRONICS CO., LTD."),
676 DMI_MATCH(DMI_PRODUCT_NAME, "N220"),
677 DMI_MATCH(DMI_BOARD_NAME, "N220"),
678 },
679 .callback = dmi_check_cb,
680 },
681 {
624 .ident = "N150/N210/N220/N230", 682 .ident = "N150/N210/N220/N230",
625 .matches = { 683 .matches = {
626 DMI_MATCH(DMI_SYS_VENDOR, 684 DMI_MATCH(DMI_SYS_VENDOR,
@@ -641,6 +699,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
641 .callback = dmi_check_cb, 699 .callback = dmi_check_cb,
642 }, 700 },
643 { 701 {
702 .ident = "R700",
703 .matches = {
704 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
705 DMI_MATCH(DMI_PRODUCT_NAME, "SR700"),
706 DMI_MATCH(DMI_BOARD_NAME, "SR700"),
707 },
708 .callback = dmi_check_cb,
709 },
710 {
644 .ident = "R530/R730", 711 .ident = "R530/R730",
645 .matches = { 712 .matches = {
646 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 713 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
@@ -686,6 +753,33 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
686 }, 753 },
687 .callback = dmi_check_cb, 754 .callback = dmi_check_cb,
688 }, 755 },
756 {
757 .ident = "R528/R728",
758 .matches = {
759 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
760 DMI_MATCH(DMI_PRODUCT_NAME, "R528/R728"),
761 DMI_MATCH(DMI_BOARD_NAME, "R528/R728"),
762 },
763 .callback = dmi_check_cb,
764 },
765 {
766 .ident = "NC210/NC110",
767 .matches = {
768 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
769 DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
770 DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
771 },
772 .callback = dmi_check_cb,
773 },
774 {
775 .ident = "X520",
776 .matches = {
777 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
778 DMI_MATCH(DMI_PRODUCT_NAME, "X520"),
779 DMI_MATCH(DMI_BOARD_NAME, "X520"),
780 },
781 .callback = dmi_check_cb,
782 },
689 { }, 783 { },
690}; 784};
691MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); 785MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
@@ -770,7 +864,7 @@ static int __init samsung_init(void)
770 sabi_iface = ioremap_nocache(ifaceP, 16); 864 sabi_iface = ioremap_nocache(ifaceP, 16);
771 if (!sabi_iface) { 865 if (!sabi_iface) {
772 pr_err("Can't remap %x\n", ifaceP); 866 pr_err("Can't remap %x\n", ifaceP);
773 goto exit; 867 goto error_no_signature;
774 } 868 }
775 if (debug) { 869 if (debug) {
776 printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP); 870 printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
@@ -794,6 +888,9 @@ static int __init samsung_init(void)
794 } 888 }
795 } 889 }
796 890
891 /* Check for stepping quirk */
892 check_for_stepping_quirk();
893
797 /* knock up a platform device to hang stuff off of */ 894 /* knock up a platform device to hang stuff off of */
798 sdev = platform_device_register_simple("samsung", -1, NULL, 0); 895 sdev = platform_device_register_simple("samsung", -1, NULL, 0);
799 if (IS_ERR(sdev)) 896 if (IS_ERR(sdev))
@@ -802,7 +899,8 @@ static int __init samsung_init(void)
802 /* create a backlight device to talk to this one */ 899 /* create a backlight device to talk to this one */
803 memset(&props, 0, sizeof(struct backlight_properties)); 900 memset(&props, 0, sizeof(struct backlight_properties));
804 props.type = BACKLIGHT_PLATFORM; 901 props.type = BACKLIGHT_PLATFORM;
805 props.max_brightness = sabi_config->max_brightness; 902 props.max_brightness = sabi_config->max_brightness -
903 sabi_config->min_brightness;
806 backlight_device = backlight_device_register("samsung", &sdev->dev, 904 backlight_device = backlight_device_register("samsung", &sdev->dev,
807 NULL, &backlight_ops, 905 NULL, &backlight_ops,
808 &props); 906 &props);
@@ -821,7 +919,6 @@ static int __init samsung_init(void)
821 if (retval) 919 if (retval)
822 goto error_file_create; 920 goto error_file_create;
823 921
824exit:
825 return 0; 922 return 0;
826 923
827error_file_create: 924error_file_create:
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index bbd182e178cb..c006dee5ebfe 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -3281,7 +3281,7 @@ static int sony_pic_add(struct acpi_device *device)
3281 /* request IRQ */ 3281 /* request IRQ */
3282 list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) { 3282 list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
3283 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq, 3283 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
3284 IRQF_DISABLED, "sony-laptop", &spic_dev)) { 3284 0, "sony-laptop", &spic_dev)) {
3285 dprintk("IRQ: %d - triggering: %d - " 3285 dprintk("IRQ: %d - triggering: %d - "
3286 "polarity: %d - shr: %d\n", 3286 "polarity: %d - shr: %d\n",
3287 irq->irq.interrupts[0], 3287 irq->irq.interrupts[0],
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index 4c20447ddbb7..d528daa0e81c 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -41,6 +41,7 @@ static const struct key_entry topstar_keymap[] = {
41 { KE_KEY, 0x8c, { KEY_MEDIA } }, 41 { KE_KEY, 0x8c, { KEY_MEDIA } },
42 42
43 /* Known non hotkey events don't handled or that we don't care yet */ 43 /* Known non hotkey events don't handled or that we don't care yet */
44 { KE_IGNORE, 0x82, }, /* backlight event */
44 { KE_IGNORE, 0x8e, }, 45 { KE_IGNORE, 0x8e, },
45 { KE_IGNORE, 0x8f, }, 46 { KE_IGNORE, 0x8f, },
46 { KE_IGNORE, 0x90, }, 47 { KE_IGNORE, 0x90, },
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index cb009b2629ee..13ef8c37471d 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -47,7 +47,6 @@
47#include <linux/proc_fs.h> 47#include <linux/proc_fs.h>
48#include <linux/seq_file.h> 48#include <linux/seq_file.h>
49#include <linux/backlight.h> 49#include <linux/backlight.h>
50#include <linux/platform_device.h>
51#include <linux/rfkill.h> 50#include <linux/rfkill.h>
52#include <linux/input.h> 51#include <linux/input.h>
53#include <linux/input/sparse-keymap.h> 52#include <linux/input/sparse-keymap.h>
@@ -63,11 +62,7 @@ MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
63MODULE_LICENSE("GPL"); 62MODULE_LICENSE("GPL");
64 63
65/* Toshiba ACPI method paths */ 64/* Toshiba ACPI method paths */
66#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
67#define TOSH_INTERFACE_1 "\\_SB_.VALD"
68#define TOSH_INTERFACE_2 "\\_SB_.VALZ"
69#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX" 65#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
70#define GHCI_METHOD ".GHCI"
71 66
72/* Toshiba HCI interface definitions 67/* Toshiba HCI interface definitions
73 * 68 *
@@ -111,6 +106,25 @@ MODULE_LICENSE("GPL");
111#define HCI_WIRELESS_BT_ATTACH 0x40 106#define HCI_WIRELESS_BT_ATTACH 0x40
112#define HCI_WIRELESS_BT_POWER 0x80 107#define HCI_WIRELESS_BT_POWER 0x80
113 108
109struct toshiba_acpi_dev {
110 struct acpi_device *acpi_dev;
111 const char *method_hci;
112 struct rfkill *bt_rfk;
113 struct input_dev *hotkey_dev;
114 struct backlight_device *backlight_dev;
115 struct led_classdev led_dev;
116
117 int force_fan;
118 int last_key_event;
119 int key_event_valid;
120
121 int illumination_supported:1;
122 int video_supported:1;
123 int fan_supported:1;
124
125 struct mutex mutex;
126};
127
114static const struct acpi_device_id toshiba_device_ids[] = { 128static const struct acpi_device_id toshiba_device_ids[] = {
115 {"TOS6200", 0}, 129 {"TOS6200", 0},
116 {"TOS6208", 0}, 130 {"TOS6208", 0},
@@ -119,7 +133,7 @@ static const struct acpi_device_id toshiba_device_ids[] = {
119}; 133};
120MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); 134MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
121 135
122static const struct key_entry toshiba_acpi_keymap[] __initconst = { 136static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
123 { KE_KEY, 0x101, { KEY_MUTE } }, 137 { KE_KEY, 0x101, { KEY_MUTE } },
124 { KE_KEY, 0x102, { KEY_ZOOMOUT } }, 138 { KE_KEY, 0x102, { KEY_ZOOMOUT } },
125 { KE_KEY, 0x103, { KEY_ZOOMIN } }, 139 { KE_KEY, 0x103, { KEY_ZOOMIN } },
@@ -155,15 +169,6 @@ static __inline__ void _set_bit(u32 * word, u32 mask, int value)
155/* acpi interface wrappers 169/* acpi interface wrappers
156 */ 170 */
157 171
158static int is_valid_acpi_path(const char *methodName)
159{
160 acpi_handle handle;
161 acpi_status status;
162
163 status = acpi_get_handle(NULL, (char *)methodName, &handle);
164 return !ACPI_FAILURE(status);
165}
166
167static int write_acpi_int(const char *methodName, int val) 172static int write_acpi_int(const char *methodName, int val)
168{ 173{
169 struct acpi_object_list params; 174 struct acpi_object_list params;
@@ -176,32 +181,14 @@ static int write_acpi_int(const char *methodName, int val)
176 in_objs[0].integer.value = val; 181 in_objs[0].integer.value = val;
177 182
178 status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL); 183 status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
179 return (status == AE_OK); 184 return (status == AE_OK) ? 0 : -EIO;
180}
181
182#if 0
183static int read_acpi_int(const char *methodName, int *pVal)
184{
185 struct acpi_buffer results;
186 union acpi_object out_objs[1];
187 acpi_status status;
188
189 results.length = sizeof(out_objs);
190 results.pointer = out_objs;
191
192 status = acpi_evaluate_object(0, (char *)methodName, 0, &results);
193 *pVal = out_objs[0].integer.value;
194
195 return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER);
196} 185}
197#endif
198
199static const char *method_hci /*= 0*/ ;
200 186
201/* Perform a raw HCI call. Here we don't care about input or output buffer 187/* Perform a raw HCI call. Here we don't care about input or output buffer
202 * format. 188 * format.
203 */ 189 */
204static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS]) 190static acpi_status hci_raw(struct toshiba_acpi_dev *dev,
191 const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
205{ 192{
206 struct acpi_object_list params; 193 struct acpi_object_list params;
207 union acpi_object in_objs[HCI_WORDS]; 194 union acpi_object in_objs[HCI_WORDS];
@@ -220,7 +207,8 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
220 results.length = sizeof(out_objs); 207 results.length = sizeof(out_objs);
221 results.pointer = out_objs; 208 results.pointer = out_objs;
222 209
223 status = acpi_evaluate_object(NULL, (char *)method_hci, &params, 210 status = acpi_evaluate_object(dev->acpi_dev->handle,
211 (char *)dev->method_hci, &params,
224 &results); 212 &results);
225 if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) { 213 if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
226 for (i = 0; i < out_objs->package.count; ++i) { 214 for (i = 0; i < out_objs->package.count; ++i) {
@@ -237,85 +225,79 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
237 * may be useful (such as "not supported"). 225 * may be useful (such as "not supported").
238 */ 226 */
239 227
240static acpi_status hci_write1(u32 reg, u32 in1, u32 * result) 228static acpi_status hci_write1(struct toshiba_acpi_dev *dev, u32 reg,
229 u32 in1, u32 *result)
241{ 230{
242 u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 }; 231 u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
243 u32 out[HCI_WORDS]; 232 u32 out[HCI_WORDS];
244 acpi_status status = hci_raw(in, out); 233 acpi_status status = hci_raw(dev, in, out);
245 *result = (status == AE_OK) ? out[0] : HCI_FAILURE; 234 *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
246 return status; 235 return status;
247} 236}
248 237
249static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result) 238static acpi_status hci_read1(struct toshiba_acpi_dev *dev, u32 reg,
239 u32 *out1, u32 *result)
250{ 240{
251 u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 }; 241 u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
252 u32 out[HCI_WORDS]; 242 u32 out[HCI_WORDS];
253 acpi_status status = hci_raw(in, out); 243 acpi_status status = hci_raw(dev, in, out);
254 *out1 = out[2]; 244 *out1 = out[2];
255 *result = (status == AE_OK) ? out[0] : HCI_FAILURE; 245 *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
256 return status; 246 return status;
257} 247}
258 248
259static acpi_status hci_write2(u32 reg, u32 in1, u32 in2, u32 *result) 249static acpi_status hci_write2(struct toshiba_acpi_dev *dev, u32 reg,
250 u32 in1, u32 in2, u32 *result)
260{ 251{
261 u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 }; 252 u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 };
262 u32 out[HCI_WORDS]; 253 u32 out[HCI_WORDS];
263 acpi_status status = hci_raw(in, out); 254 acpi_status status = hci_raw(dev, in, out);
264 *result = (status == AE_OK) ? out[0] : HCI_FAILURE; 255 *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
265 return status; 256 return status;
266} 257}
267 258
268static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result) 259static acpi_status hci_read2(struct toshiba_acpi_dev *dev, u32 reg,
260 u32 *out1, u32 *out2, u32 *result)
269{ 261{
270 u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 }; 262 u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 };
271 u32 out[HCI_WORDS]; 263 u32 out[HCI_WORDS];
272 acpi_status status = hci_raw(in, out); 264 acpi_status status = hci_raw(dev, in, out);
273 *out1 = out[2]; 265 *out1 = out[2];
274 *out2 = out[3]; 266 *out2 = out[3];
275 *result = (status == AE_OK) ? out[0] : HCI_FAILURE; 267 *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
276 return status; 268 return status;
277} 269}
278 270
279struct toshiba_acpi_dev {
280 struct platform_device *p_dev;
281 struct rfkill *bt_rfk;
282 struct input_dev *hotkey_dev;
283 int illumination_installed;
284 acpi_handle handle;
285
286 const char *bt_name;
287
288 struct mutex mutex;
289};
290
291/* Illumination support */ 271/* Illumination support */
292static int toshiba_illumination_available(void) 272static int toshiba_illumination_available(struct toshiba_acpi_dev *dev)
293{ 273{
294 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; 274 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
295 u32 out[HCI_WORDS]; 275 u32 out[HCI_WORDS];
296 acpi_status status; 276 acpi_status status;
297 277
298 in[0] = 0xf100; 278 in[0] = 0xf100;
299 status = hci_raw(in, out); 279 status = hci_raw(dev, in, out);
300 if (ACPI_FAILURE(status)) { 280 if (ACPI_FAILURE(status)) {
301 pr_info("Illumination device not available\n"); 281 pr_info("Illumination device not available\n");
302 return 0; 282 return 0;
303 } 283 }
304 in[0] = 0xf400; 284 in[0] = 0xf400;
305 status = hci_raw(in, out); 285 status = hci_raw(dev, in, out);
306 return 1; 286 return 1;
307} 287}
308 288
309static void toshiba_illumination_set(struct led_classdev *cdev, 289static void toshiba_illumination_set(struct led_classdev *cdev,
310 enum led_brightness brightness) 290 enum led_brightness brightness)
311{ 291{
292 struct toshiba_acpi_dev *dev = container_of(cdev,
293 struct toshiba_acpi_dev, led_dev);
312 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; 294 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
313 u32 out[HCI_WORDS]; 295 u32 out[HCI_WORDS];
314 acpi_status status; 296 acpi_status status;
315 297
316 /* First request : initialize communication. */ 298 /* First request : initialize communication. */
317 in[0] = 0xf100; 299 in[0] = 0xf100;
318 status = hci_raw(in, out); 300 status = hci_raw(dev, in, out);
319 if (ACPI_FAILURE(status)) { 301 if (ACPI_FAILURE(status)) {
320 pr_info("Illumination device not available\n"); 302 pr_info("Illumination device not available\n");
321 return; 303 return;
@@ -326,7 +308,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
326 in[0] = 0xf400; 308 in[0] = 0xf400;
327 in[1] = 0x14e; 309 in[1] = 0x14e;
328 in[2] = 1; 310 in[2] = 1;
329 status = hci_raw(in, out); 311 status = hci_raw(dev, in, out);
330 if (ACPI_FAILURE(status)) { 312 if (ACPI_FAILURE(status)) {
331 pr_info("ACPI call for illumination failed\n"); 313 pr_info("ACPI call for illumination failed\n");
332 return; 314 return;
@@ -336,7 +318,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
336 in[0] = 0xf400; 318 in[0] = 0xf400;
337 in[1] = 0x14e; 319 in[1] = 0x14e;
338 in[2] = 0; 320 in[2] = 0;
339 status = hci_raw(in, out); 321 status = hci_raw(dev, in, out);
340 if (ACPI_FAILURE(status)) { 322 if (ACPI_FAILURE(status)) {
341 pr_info("ACPI call for illumination failed.\n"); 323 pr_info("ACPI call for illumination failed.\n");
342 return; 324 return;
@@ -347,11 +329,13 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
347 in[0] = 0xf200; 329 in[0] = 0xf200;
348 in[1] = 0; 330 in[1] = 0;
349 in[2] = 0; 331 in[2] = 0;
350 hci_raw(in, out); 332 hci_raw(dev, in, out);
351} 333}
352 334
353static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) 335static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
354{ 336{
337 struct toshiba_acpi_dev *dev = container_of(cdev,
338 struct toshiba_acpi_dev, led_dev);
355 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; 339 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
356 u32 out[HCI_WORDS]; 340 u32 out[HCI_WORDS];
357 acpi_status status; 341 acpi_status status;
@@ -359,7 +343,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
359 343
360 /* First request : initialize communication. */ 344 /* First request : initialize communication. */
361 in[0] = 0xf100; 345 in[0] = 0xf100;
362 status = hci_raw(in, out); 346 status = hci_raw(dev, in, out);
363 if (ACPI_FAILURE(status)) { 347 if (ACPI_FAILURE(status)) {
364 pr_info("Illumination device not available\n"); 348 pr_info("Illumination device not available\n");
365 return LED_OFF; 349 return LED_OFF;
@@ -368,7 +352,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
368 /* Check the illumination */ 352 /* Check the illumination */
369 in[0] = 0xf300; 353 in[0] = 0xf300;
370 in[1] = 0x14e; 354 in[1] = 0x14e;
371 status = hci_raw(in, out); 355 status = hci_raw(dev, in, out);
372 if (ACPI_FAILURE(status)) { 356 if (ACPI_FAILURE(status)) {
373 pr_info("ACPI call for illumination failed.\n"); 357 pr_info("ACPI call for illumination failed.\n");
374 return LED_OFF; 358 return LED_OFF;
@@ -380,46 +364,35 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
380 in[0] = 0xf200; 364 in[0] = 0xf200;
381 in[1] = 0; 365 in[1] = 0;
382 in[2] = 0; 366 in[2] = 0;
383 hci_raw(in, out); 367 hci_raw(dev, in, out);
384 368
385 return result; 369 return result;
386} 370}
387 371
388static struct led_classdev toshiba_led = {
389 .name = "toshiba::illumination",
390 .max_brightness = 1,
391 .brightness_set = toshiba_illumination_set,
392 .brightness_get = toshiba_illumination_get,
393};
394
395static struct toshiba_acpi_dev toshiba_acpi = {
396 .bt_name = "Toshiba Bluetooth",
397};
398
399/* Bluetooth rfkill handlers */ 372/* Bluetooth rfkill handlers */
400 373
401static u32 hci_get_bt_present(bool *present) 374static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
402{ 375{
403 u32 hci_result; 376 u32 hci_result;
404 u32 value, value2; 377 u32 value, value2;
405 378
406 value = 0; 379 value = 0;
407 value2 = 0; 380 value2 = 0;
408 hci_read2(HCI_WIRELESS, &value, &value2, &hci_result); 381 hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result);
409 if (hci_result == HCI_SUCCESS) 382 if (hci_result == HCI_SUCCESS)
410 *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false; 383 *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
411 384
412 return hci_result; 385 return hci_result;
413} 386}
414 387
415static u32 hci_get_radio_state(bool *radio_state) 388static u32 hci_get_radio_state(struct toshiba_acpi_dev *dev, bool *radio_state)
416{ 389{
417 u32 hci_result; 390 u32 hci_result;
418 u32 value, value2; 391 u32 value, value2;
419 392
420 value = 0; 393 value = 0;
421 value2 = 0x0001; 394 value2 = 0x0001;
422 hci_read2(HCI_WIRELESS, &value, &value2, &hci_result); 395 hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result);
423 396
424 *radio_state = value & HCI_WIRELESS_KILL_SWITCH; 397 *radio_state = value & HCI_WIRELESS_KILL_SWITCH;
425 return hci_result; 398 return hci_result;
@@ -436,8 +409,8 @@ static int bt_rfkill_set_block(void *data, bool blocked)
436 value = (blocked == false); 409 value = (blocked == false);
437 410
438 mutex_lock(&dev->mutex); 411 mutex_lock(&dev->mutex);
439 if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) { 412 if (hci_get_radio_state(dev, &radio_state) != HCI_SUCCESS) {
440 err = -EBUSY; 413 err = -EIO;
441 goto out; 414 goto out;
442 } 415 }
443 416
@@ -446,11 +419,11 @@ static int bt_rfkill_set_block(void *data, bool blocked)
446 goto out; 419 goto out;
447 } 420 }
448 421
449 hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1); 422 hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
450 hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2); 423 hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
451 424
452 if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS) 425 if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS)
453 err = -EBUSY; 426 err = -EIO;
454 else 427 else
455 err = 0; 428 err = 0;
456 out: 429 out:
@@ -467,7 +440,7 @@ static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
467 440
468 mutex_lock(&dev->mutex); 441 mutex_lock(&dev->mutex);
469 442
470 hci_result = hci_get_radio_state(&value); 443 hci_result = hci_get_radio_state(dev, &value);
471 if (hci_result != HCI_SUCCESS) { 444 if (hci_result != HCI_SUCCESS) {
472 /* Can't do anything useful */ 445 /* Can't do anything useful */
473 mutex_unlock(&dev->mutex); 446 mutex_unlock(&dev->mutex);
@@ -488,63 +461,64 @@ static const struct rfkill_ops toshiba_rfk_ops = {
488}; 461};
489 462
490static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; 463static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
491static struct backlight_device *toshiba_backlight_device;
492static int force_fan;
493static int last_key_event;
494static int key_event_valid;
495 464
496static int get_lcd(struct backlight_device *bd) 465static int get_lcd(struct backlight_device *bd)
497{ 466{
467 struct toshiba_acpi_dev *dev = bl_get_data(bd);
498 u32 hci_result; 468 u32 hci_result;
499 u32 value; 469 u32 value;
500 470
501 hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result); 471 hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result);
502 if (hci_result == HCI_SUCCESS) { 472 if (hci_result == HCI_SUCCESS)
503 return (value >> HCI_LCD_BRIGHTNESS_SHIFT); 473 return (value >> HCI_LCD_BRIGHTNESS_SHIFT);
504 } else 474
505 return -EFAULT; 475 return -EIO;
506} 476}
507 477
508static int lcd_proc_show(struct seq_file *m, void *v) 478static int lcd_proc_show(struct seq_file *m, void *v)
509{ 479{
510 int value = get_lcd(NULL); 480 struct toshiba_acpi_dev *dev = m->private;
481 int value;
482
483 if (!dev->backlight_dev)
484 return -ENODEV;
511 485
486 value = get_lcd(dev->backlight_dev);
512 if (value >= 0) { 487 if (value >= 0) {
513 seq_printf(m, "brightness: %d\n", value); 488 seq_printf(m, "brightness: %d\n", value);
514 seq_printf(m, "brightness_levels: %d\n", 489 seq_printf(m, "brightness_levels: %d\n",
515 HCI_LCD_BRIGHTNESS_LEVELS); 490 HCI_LCD_BRIGHTNESS_LEVELS);
516 } else { 491 return 0;
517 pr_err("Error reading LCD brightness\n");
518 } 492 }
519 493
520 return 0; 494 pr_err("Error reading LCD brightness\n");
495 return -EIO;
521} 496}
522 497
523static int lcd_proc_open(struct inode *inode, struct file *file) 498static int lcd_proc_open(struct inode *inode, struct file *file)
524{ 499{
525 return single_open(file, lcd_proc_show, NULL); 500 return single_open(file, lcd_proc_show, PDE(inode)->data);
526} 501}
527 502
528static int set_lcd(int value) 503static int set_lcd(struct toshiba_acpi_dev *dev, int value)
529{ 504{
530 u32 hci_result; 505 u32 hci_result;
531 506
532 value = value << HCI_LCD_BRIGHTNESS_SHIFT; 507 value = value << HCI_LCD_BRIGHTNESS_SHIFT;
533 hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result); 508 hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result);
534 if (hci_result != HCI_SUCCESS) 509 return hci_result == HCI_SUCCESS ? 0 : -EIO;
535 return -EFAULT;
536
537 return 0;
538} 510}
539 511
540static int set_lcd_status(struct backlight_device *bd) 512static int set_lcd_status(struct backlight_device *bd)
541{ 513{
542 return set_lcd(bd->props.brightness); 514 struct toshiba_acpi_dev *dev = bl_get_data(bd);
515 return set_lcd(dev, bd->props.brightness);
543} 516}
544 517
545static ssize_t lcd_proc_write(struct file *file, const char __user *buf, 518static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
546 size_t count, loff_t *pos) 519 size_t count, loff_t *pos)
547{ 520{
521 struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
548 char cmd[42]; 522 char cmd[42];
549 size_t len; 523 size_t len;
550 int value; 524 int value;
@@ -557,7 +531,7 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
557 531
558 if (sscanf(cmd, " brightness : %i", &value) == 1 && 532 if (sscanf(cmd, " brightness : %i", &value) == 1 &&
559 value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { 533 value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
560 ret = set_lcd(value); 534 ret = set_lcd(dev, value);
561 if (ret == 0) 535 if (ret == 0)
562 ret = count; 536 ret = count;
563 } else { 537 } else {
@@ -575,41 +549,49 @@ static const struct file_operations lcd_proc_fops = {
575 .write = lcd_proc_write, 549 .write = lcd_proc_write,
576}; 550};
577 551
578static int video_proc_show(struct seq_file *m, void *v) 552static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status)
579{ 553{
580 u32 hci_result; 554 u32 hci_result;
555
556 hci_read1(dev, HCI_VIDEO_OUT, status, &hci_result);
557 return hci_result == HCI_SUCCESS ? 0 : -EIO;
558}
559
560static int video_proc_show(struct seq_file *m, void *v)
561{
562 struct toshiba_acpi_dev *dev = m->private;
581 u32 value; 563 u32 value;
564 int ret;
582 565
583 hci_read1(HCI_VIDEO_OUT, &value, &hci_result); 566 ret = get_video_status(dev, &value);
584 if (hci_result == HCI_SUCCESS) { 567 if (!ret) {
585 int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; 568 int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
586 int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; 569 int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
587 int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0; 570 int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
588 seq_printf(m, "lcd_out: %d\n", is_lcd); 571 seq_printf(m, "lcd_out: %d\n", is_lcd);
589 seq_printf(m, "crt_out: %d\n", is_crt); 572 seq_printf(m, "crt_out: %d\n", is_crt);
590 seq_printf(m, "tv_out: %d\n", is_tv); 573 seq_printf(m, "tv_out: %d\n", is_tv);
591 } else {
592 pr_err("Error reading video out status\n");
593 } 574 }
594 575
595 return 0; 576 return ret;
596} 577}
597 578
598static int video_proc_open(struct inode *inode, struct file *file) 579static int video_proc_open(struct inode *inode, struct file *file)
599{ 580{
600 return single_open(file, video_proc_show, NULL); 581 return single_open(file, video_proc_show, PDE(inode)->data);
601} 582}
602 583
603static ssize_t video_proc_write(struct file *file, const char __user *buf, 584static ssize_t video_proc_write(struct file *file, const char __user *buf,
604 size_t count, loff_t *pos) 585 size_t count, loff_t *pos)
605{ 586{
587 struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
606 char *cmd, *buffer; 588 char *cmd, *buffer;
589 int ret;
607 int value; 590 int value;
608 int remain = count; 591 int remain = count;
609 int lcd_out = -1; 592 int lcd_out = -1;
610 int crt_out = -1; 593 int crt_out = -1;
611 int tv_out = -1; 594 int tv_out = -1;
612 u32 hci_result;
613 u32 video_out; 595 u32 video_out;
614 596
615 cmd = kmalloc(count + 1, GFP_KERNEL); 597 cmd = kmalloc(count + 1, GFP_KERNEL);
@@ -644,8 +626,8 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
644 626
645 kfree(cmd); 627 kfree(cmd);
646 628
647 hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result); 629 ret = get_video_status(dev, &video_out);
648 if (hci_result == HCI_SUCCESS) { 630 if (!ret) {
649 unsigned int new_video_out = video_out; 631 unsigned int new_video_out = video_out;
650 if (lcd_out != -1) 632 if (lcd_out != -1)
651 _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out); 633 _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
@@ -656,12 +638,10 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
656 /* To avoid unnecessary video disruption, only write the new 638 /* To avoid unnecessary video disruption, only write the new
657 * video setting if something changed. */ 639 * video setting if something changed. */
658 if (new_video_out != video_out) 640 if (new_video_out != video_out)
659 write_acpi_int(METHOD_VIDEO_OUT, new_video_out); 641 ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
660 } else {
661 return -EFAULT;
662 } 642 }
663 643
664 return count; 644 return ret ? ret : count;
665} 645}
666 646
667static const struct file_operations video_proc_fops = { 647static const struct file_operations video_proc_fops = {
@@ -673,30 +653,38 @@ static const struct file_operations video_proc_fops = {
673 .write = video_proc_write, 653 .write = video_proc_write,
674}; 654};
675 655
676static int fan_proc_show(struct seq_file *m, void *v) 656static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status)
677{ 657{
678 u32 hci_result; 658 u32 hci_result;
659
660 hci_read1(dev, HCI_FAN, status, &hci_result);
661 return hci_result == HCI_SUCCESS ? 0 : -EIO;
662}
663
664static int fan_proc_show(struct seq_file *m, void *v)
665{
666 struct toshiba_acpi_dev *dev = m->private;
667 int ret;
679 u32 value; 668 u32 value;
680 669
681 hci_read1(HCI_FAN, &value, &hci_result); 670 ret = get_fan_status(dev, &value);
682 if (hci_result == HCI_SUCCESS) { 671 if (!ret) {
683 seq_printf(m, "running: %d\n", (value > 0)); 672 seq_printf(m, "running: %d\n", (value > 0));
684 seq_printf(m, "force_on: %d\n", force_fan); 673 seq_printf(m, "force_on: %d\n", dev->force_fan);
685 } else {
686 pr_err("Error reading fan status\n");
687 } 674 }
688 675
689 return 0; 676 return ret;
690} 677}
691 678
692static int fan_proc_open(struct inode *inode, struct file *file) 679static int fan_proc_open(struct inode *inode, struct file *file)
693{ 680{
694 return single_open(file, fan_proc_show, NULL); 681 return single_open(file, fan_proc_show, PDE(inode)->data);
695} 682}
696 683
697static ssize_t fan_proc_write(struct file *file, const char __user *buf, 684static ssize_t fan_proc_write(struct file *file, const char __user *buf,
698 size_t count, loff_t *pos) 685 size_t count, loff_t *pos)
699{ 686{
687 struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
700 char cmd[42]; 688 char cmd[42];
701 size_t len; 689 size_t len;
702 int value; 690 int value;
@@ -709,11 +697,11 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf,
709 697
710 if (sscanf(cmd, " force_on : %i", &value) == 1 && 698 if (sscanf(cmd, " force_on : %i", &value) == 1 &&
711 value >= 0 && value <= 1) { 699 value >= 0 && value <= 1) {
712 hci_write1(HCI_FAN, value, &hci_result); 700 hci_write1(dev, HCI_FAN, value, &hci_result);
713 if (hci_result != HCI_SUCCESS) 701 if (hci_result != HCI_SUCCESS)
714 return -EFAULT; 702 return -EIO;
715 else 703 else
716 force_fan = value; 704 dev->force_fan = value;
717 } else { 705 } else {
718 return -EINVAL; 706 return -EINVAL;
719 } 707 }
@@ -732,42 +720,43 @@ static const struct file_operations fan_proc_fops = {
732 720
733static int keys_proc_show(struct seq_file *m, void *v) 721static int keys_proc_show(struct seq_file *m, void *v)
734{ 722{
723 struct toshiba_acpi_dev *dev = m->private;
735 u32 hci_result; 724 u32 hci_result;
736 u32 value; 725 u32 value;
737 726
738 if (!key_event_valid) { 727 if (!dev->key_event_valid) {
739 hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result); 728 hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
740 if (hci_result == HCI_SUCCESS) { 729 if (hci_result == HCI_SUCCESS) {
741 key_event_valid = 1; 730 dev->key_event_valid = 1;
742 last_key_event = value; 731 dev->last_key_event = value;
743 } else if (hci_result == HCI_EMPTY) { 732 } else if (hci_result == HCI_EMPTY) {
744 /* better luck next time */ 733 /* better luck next time */
745 } else if (hci_result == HCI_NOT_SUPPORTED) { 734 } else if (hci_result == HCI_NOT_SUPPORTED) {
746 /* This is a workaround for an unresolved issue on 735 /* This is a workaround for an unresolved issue on
747 * some machines where system events sporadically 736 * some machines where system events sporadically
748 * become disabled. */ 737 * become disabled. */
749 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); 738 hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
750 pr_notice("Re-enabled hotkeys\n"); 739 pr_notice("Re-enabled hotkeys\n");
751 } else { 740 } else {
752 pr_err("Error reading hotkey status\n"); 741 pr_err("Error reading hotkey status\n");
753 goto end; 742 return -EIO;
754 } 743 }
755 } 744 }
756 745
757 seq_printf(m, "hotkey_ready: %d\n", key_event_valid); 746 seq_printf(m, "hotkey_ready: %d\n", dev->key_event_valid);
758 seq_printf(m, "hotkey: 0x%04x\n", last_key_event); 747 seq_printf(m, "hotkey: 0x%04x\n", dev->last_key_event);
759end:
760 return 0; 748 return 0;
761} 749}
762 750
763static int keys_proc_open(struct inode *inode, struct file *file) 751static int keys_proc_open(struct inode *inode, struct file *file)
764{ 752{
765 return single_open(file, keys_proc_show, NULL); 753 return single_open(file, keys_proc_show, PDE(inode)->data);
766} 754}
767 755
768static ssize_t keys_proc_write(struct file *file, const char __user *buf, 756static ssize_t keys_proc_write(struct file *file, const char __user *buf,
769 size_t count, loff_t *pos) 757 size_t count, loff_t *pos)
770{ 758{
759 struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
771 char cmd[42]; 760 char cmd[42];
772 size_t len; 761 size_t len;
773 int value; 762 int value;
@@ -778,7 +767,7 @@ static ssize_t keys_proc_write(struct file *file, const char __user *buf,
778 cmd[len] = '\0'; 767 cmd[len] = '\0';
779 768
780 if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) { 769 if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) {
781 key_event_valid = 0; 770 dev->key_event_valid = 0;
782 } else { 771 } else {
783 return -EINVAL; 772 return -EINVAL;
784 } 773 }
@@ -820,21 +809,35 @@ static const struct file_operations version_proc_fops = {
820 809
821#define PROC_TOSHIBA "toshiba" 810#define PROC_TOSHIBA "toshiba"
822 811
823static void __init create_toshiba_proc_entries(void) 812static void __devinit
813create_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
824{ 814{
825 proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops); 815 if (dev->backlight_dev)
826 proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops); 816 proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir,
827 proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops); 817 &lcd_proc_fops, dev);
828 proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops); 818 if (dev->video_supported)
829 proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops); 819 proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir,
820 &video_proc_fops, dev);
821 if (dev->fan_supported)
822 proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir,
823 &fan_proc_fops, dev);
824 if (dev->hotkey_dev)
825 proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir,
826 &keys_proc_fops, dev);
827 proc_create_data("version", S_IRUGO, toshiba_proc_dir,
828 &version_proc_fops, dev);
830} 829}
831 830
832static void remove_toshiba_proc_entries(void) 831static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
833{ 832{
834 remove_proc_entry("lcd", toshiba_proc_dir); 833 if (dev->backlight_dev)
835 remove_proc_entry("video", toshiba_proc_dir); 834 remove_proc_entry("lcd", toshiba_proc_dir);
836 remove_proc_entry("fan", toshiba_proc_dir); 835 if (dev->video_supported)
837 remove_proc_entry("keys", toshiba_proc_dir); 836 remove_proc_entry("video", toshiba_proc_dir);
837 if (dev->fan_supported)
838 remove_proc_entry("fan", toshiba_proc_dir);
839 if (dev->hotkey_dev)
840 remove_proc_entry("keys", toshiba_proc_dir);
838 remove_proc_entry("version", toshiba_proc_dir); 841 remove_proc_entry("version", toshiba_proc_dir);
839} 842}
840 843
@@ -843,224 +846,256 @@ static const struct backlight_ops toshiba_backlight_data = {
843 .update_status = set_lcd_status, 846 .update_status = set_lcd_status,
844}; 847};
845 848
846static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context) 849static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
847{
848 u32 hci_result, value;
849
850 if (event != 0x80)
851 return;
852 do {
853 hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
854 if (hci_result == HCI_SUCCESS) {
855 if (value == 0x100)
856 continue;
857 /* act on key press; ignore key release */
858 if (value & 0x80)
859 continue;
860
861 if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev,
862 value, 1, true)) {
863 pr_info("Unknown key %x\n",
864 value);
865 }
866 } else if (hci_result == HCI_NOT_SUPPORTED) {
867 /* This is a workaround for an unresolved issue on
868 * some machines where system events sporadically
869 * become disabled. */
870 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
871 pr_notice("Re-enabled hotkeys\n");
872 }
873 } while (hci_result != HCI_EMPTY);
874}
875
876static int __init toshiba_acpi_setup_keyboard(char *device)
877{ 850{
878 acpi_status status; 851 acpi_status status;
879 int error; 852 int error;
880 853
881 status = acpi_get_handle(NULL, device, &toshiba_acpi.handle); 854 dev->hotkey_dev = input_allocate_device();
882 if (ACPI_FAILURE(status)) { 855 if (!dev->hotkey_dev) {
883 pr_info("Unable to get notification device\n");
884 return -ENODEV;
885 }
886
887 toshiba_acpi.hotkey_dev = input_allocate_device();
888 if (!toshiba_acpi.hotkey_dev) {
889 pr_info("Unable to register input device\n"); 856 pr_info("Unable to register input device\n");
890 return -ENOMEM; 857 return -ENOMEM;
891 } 858 }
892 859
893 toshiba_acpi.hotkey_dev->name = "Toshiba input device"; 860 dev->hotkey_dev->name = "Toshiba input device";
894 toshiba_acpi.hotkey_dev->phys = device; 861 dev->hotkey_dev->phys = "toshiba_acpi/input0";
895 toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST; 862 dev->hotkey_dev->id.bustype = BUS_HOST;
896 863
897 error = sparse_keymap_setup(toshiba_acpi.hotkey_dev, 864 error = sparse_keymap_setup(dev->hotkey_dev, toshiba_acpi_keymap, NULL);
898 toshiba_acpi_keymap, NULL);
899 if (error) 865 if (error)
900 goto err_free_dev; 866 goto err_free_dev;
901 867
902 status = acpi_install_notify_handler(toshiba_acpi.handle, 868 status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", NULL, NULL);
903 ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL);
904 if (ACPI_FAILURE(status)) {
905 pr_info("Unable to install hotkey notification\n");
906 error = -ENODEV;
907 goto err_free_keymap;
908 }
909
910 status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL);
911 if (ACPI_FAILURE(status)) { 869 if (ACPI_FAILURE(status)) {
912 pr_info("Unable to enable hotkeys\n"); 870 pr_info("Unable to enable hotkeys\n");
913 error = -ENODEV; 871 error = -ENODEV;
914 goto err_remove_notify; 872 goto err_free_keymap;
915 } 873 }
916 874
917 error = input_register_device(toshiba_acpi.hotkey_dev); 875 error = input_register_device(dev->hotkey_dev);
918 if (error) { 876 if (error) {
919 pr_info("Unable to register input device\n"); 877 pr_info("Unable to register input device\n");
920 goto err_remove_notify; 878 goto err_free_keymap;
921 } 879 }
922 880
923 return 0; 881 return 0;
924 882
925 err_remove_notify:
926 acpi_remove_notify_handler(toshiba_acpi.handle,
927 ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
928 err_free_keymap: 883 err_free_keymap:
929 sparse_keymap_free(toshiba_acpi.hotkey_dev); 884 sparse_keymap_free(dev->hotkey_dev);
930 err_free_dev: 885 err_free_dev:
931 input_free_device(toshiba_acpi.hotkey_dev); 886 input_free_device(dev->hotkey_dev);
932 toshiba_acpi.hotkey_dev = NULL; 887 dev->hotkey_dev = NULL;
933 return error; 888 return error;
934} 889}
935 890
936static void toshiba_acpi_exit(void) 891static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
937{ 892{
938 if (toshiba_acpi.hotkey_dev) { 893 struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
939 acpi_remove_notify_handler(toshiba_acpi.handle, 894
940 ACPI_DEVICE_NOTIFY, toshiba_acpi_notify); 895 remove_toshiba_proc_entries(dev);
941 sparse_keymap_free(toshiba_acpi.hotkey_dev); 896
942 input_unregister_device(toshiba_acpi.hotkey_dev); 897 if (dev->hotkey_dev) {
898 input_unregister_device(dev->hotkey_dev);
899 sparse_keymap_free(dev->hotkey_dev);
943 } 900 }
944 901
945 if (toshiba_acpi.bt_rfk) { 902 if (dev->bt_rfk) {
946 rfkill_unregister(toshiba_acpi.bt_rfk); 903 rfkill_unregister(dev->bt_rfk);
947 rfkill_destroy(toshiba_acpi.bt_rfk); 904 rfkill_destroy(dev->bt_rfk);
948 } 905 }
949 906
950 if (toshiba_backlight_device) 907 if (dev->backlight_dev)
951 backlight_device_unregister(toshiba_backlight_device); 908 backlight_device_unregister(dev->backlight_dev);
952 909
953 remove_toshiba_proc_entries(); 910 if (dev->illumination_supported)
911 led_classdev_unregister(&dev->led_dev);
954 912
955 if (toshiba_proc_dir) 913 kfree(dev);
956 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); 914
915 return 0;
916}
917
918static const char * __devinit find_hci_method(acpi_handle handle)
919{
920 acpi_status status;
921 acpi_handle hci_handle;
957 922
958 if (toshiba_acpi.illumination_installed) 923 status = acpi_get_handle(handle, "GHCI", &hci_handle);
959 led_classdev_unregister(&toshiba_led); 924 if (ACPI_SUCCESS(status))
925 return "GHCI";
960 926
961 platform_device_unregister(toshiba_acpi.p_dev); 927 status = acpi_get_handle(handle, "SPFC", &hci_handle);
928 if (ACPI_SUCCESS(status))
929 return "SPFC";
962 930
963 return; 931 return NULL;
964} 932}
965 933
966static int __init toshiba_acpi_init(void) 934static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
967{ 935{
936 struct toshiba_acpi_dev *dev;
937 const char *hci_method;
968 u32 hci_result; 938 u32 hci_result;
939 u32 dummy;
969 bool bt_present; 940 bool bt_present;
970 int ret = 0; 941 int ret = 0;
971 struct backlight_properties props; 942 struct backlight_properties props;
972 943
973 if (acpi_disabled)
974 return -ENODEV;
975
976 /* simple device detection: look for HCI method */
977 if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
978 method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
979 if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
980 pr_info("Unable to activate hotkeys\n");
981 } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
982 method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
983 if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
984 pr_info("Unable to activate hotkeys\n");
985 } else
986 return -ENODEV;
987
988 pr_info("Toshiba Laptop ACPI Extras version %s\n", 944 pr_info("Toshiba Laptop ACPI Extras version %s\n",
989 TOSHIBA_ACPI_VERSION); 945 TOSHIBA_ACPI_VERSION);
990 pr_info(" HCI method: %s\n", method_hci); 946
991 947 hci_method = find_hci_method(acpi_dev->handle);
992 mutex_init(&toshiba_acpi.mutex); 948 if (!hci_method) {
993 949 pr_err("HCI interface not found\n");
994 toshiba_acpi.p_dev = platform_device_register_simple("toshiba_acpi", 950 return -ENODEV;
995 -1, NULL, 0);
996 if (IS_ERR(toshiba_acpi.p_dev)) {
997 ret = PTR_ERR(toshiba_acpi.p_dev);
998 pr_err("unable to register platform device\n");
999 toshiba_acpi.p_dev = NULL;
1000 toshiba_acpi_exit();
1001 return ret;
1002 } 951 }
1003 952
1004 force_fan = 0; 953 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1005 key_event_valid = 0; 954 if (!dev)
955 return -ENOMEM;
956 dev->acpi_dev = acpi_dev;
957 dev->method_hci = hci_method;
958 acpi_dev->driver_data = dev;
1006 959
1007 /* enable event fifo */ 960 if (toshiba_acpi_setup_keyboard(dev))
1008 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); 961 pr_info("Unable to activate hotkeys\n");
1009 962
1010 toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir); 963 mutex_init(&dev->mutex);
1011 if (!toshiba_proc_dir) { 964
1012 toshiba_acpi_exit(); 965 /* enable event fifo */
1013 return -ENODEV; 966 hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
1014 } else {
1015 create_toshiba_proc_entries();
1016 }
1017 967
1018 props.type = BACKLIGHT_PLATFORM; 968 props.type = BACKLIGHT_PLATFORM;
1019 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; 969 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
1020 toshiba_backlight_device = backlight_device_register("toshiba", 970 dev->backlight_dev = backlight_device_register("toshiba",
1021 &toshiba_acpi.p_dev->dev, 971 &acpi_dev->dev,
1022 NULL, 972 dev,
1023 &toshiba_backlight_data, 973 &toshiba_backlight_data,
1024 &props); 974 &props);
1025 if (IS_ERR(toshiba_backlight_device)) { 975 if (IS_ERR(dev->backlight_dev)) {
1026 ret = PTR_ERR(toshiba_backlight_device); 976 ret = PTR_ERR(dev->backlight_dev);
1027 977
1028 pr_err("Could not register toshiba backlight device\n"); 978 pr_err("Could not register toshiba backlight device\n");
1029 toshiba_backlight_device = NULL; 979 dev->backlight_dev = NULL;
1030 toshiba_acpi_exit(); 980 goto error;
1031 return ret;
1032 } 981 }
982 dev->backlight_dev->props.brightness = get_lcd(dev->backlight_dev);
1033 983
1034 /* Register rfkill switch for Bluetooth */ 984 /* Register rfkill switch for Bluetooth */
1035 if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) { 985 if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) {
1036 toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name, 986 dev->bt_rfk = rfkill_alloc("Toshiba Bluetooth",
1037 &toshiba_acpi.p_dev->dev, 987 &acpi_dev->dev,
1038 RFKILL_TYPE_BLUETOOTH, 988 RFKILL_TYPE_BLUETOOTH,
1039 &toshiba_rfk_ops, 989 &toshiba_rfk_ops,
1040 &toshiba_acpi); 990 dev);
1041 if (!toshiba_acpi.bt_rfk) { 991 if (!dev->bt_rfk) {
1042 pr_err("unable to allocate rfkill device\n"); 992 pr_err("unable to allocate rfkill device\n");
1043 toshiba_acpi_exit(); 993 ret = -ENOMEM;
1044 return -ENOMEM; 994 goto error;
1045 } 995 }
1046 996
1047 ret = rfkill_register(toshiba_acpi.bt_rfk); 997 ret = rfkill_register(dev->bt_rfk);
1048 if (ret) { 998 if (ret) {
1049 pr_err("unable to register rfkill device\n"); 999 pr_err("unable to register rfkill device\n");
1050 rfkill_destroy(toshiba_acpi.bt_rfk); 1000 rfkill_destroy(dev->bt_rfk);
1051 toshiba_acpi_exit(); 1001 goto error;
1052 return ret;
1053 } 1002 }
1054 } 1003 }
1055 1004
1056 toshiba_acpi.illumination_installed = 0; 1005 if (toshiba_illumination_available(dev)) {
1057 if (toshiba_illumination_available()) { 1006 dev->led_dev.name = "toshiba::illumination";
1058 if (!led_classdev_register(&(toshiba_acpi.p_dev->dev), 1007 dev->led_dev.max_brightness = 1;
1059 &toshiba_led)) 1008 dev->led_dev.brightness_set = toshiba_illumination_set;
1060 toshiba_acpi.illumination_installed = 1; 1009 dev->led_dev.brightness_get = toshiba_illumination_get;
1010 if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev))
1011 dev->illumination_supported = 1;
1061 } 1012 }
1062 1013
1014 /* Determine whether or not BIOS supports fan and video interfaces */
1015
1016 ret = get_video_status(dev, &dummy);
1017 dev->video_supported = !ret;
1018
1019 ret = get_fan_status(dev, &dummy);
1020 dev->fan_supported = !ret;
1021
1022 create_toshiba_proc_entries(dev);
1023
1063 return 0; 1024 return 0;
1025
1026error:
1027 toshiba_acpi_remove(acpi_dev, 0);
1028 return ret;
1029}
1030
1031static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
1032{
1033 struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
1034 u32 hci_result, value;
1035
1036 if (event != 0x80)
1037 return;
1038 do {
1039 hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
1040 if (hci_result == HCI_SUCCESS) {
1041 if (value == 0x100)
1042 continue;
1043 /* act on key press; ignore key release */
1044 if (value & 0x80)
1045 continue;
1046
1047 if (!sparse_keymap_report_event(dev->hotkey_dev,
1048 value, 1, true)) {
1049 pr_info("Unknown key %x\n",
1050 value);
1051 }
1052 } else if (hci_result == HCI_NOT_SUPPORTED) {
1053 /* This is a workaround for an unresolved issue on
1054 * some machines where system events sporadically
1055 * become disabled. */
1056 hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
1057 pr_notice("Re-enabled hotkeys\n");
1058 }
1059 } while (hci_result != HCI_EMPTY);
1060}
1061
1062
1063static struct acpi_driver toshiba_acpi_driver = {
1064 .name = "Toshiba ACPI driver",
1065 .owner = THIS_MODULE,
1066 .ids = toshiba_device_ids,
1067 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1068 .ops = {
1069 .add = toshiba_acpi_add,
1070 .remove = toshiba_acpi_remove,
1071 .notify = toshiba_acpi_notify,
1072 },
1073};
1074
1075static int __init toshiba_acpi_init(void)
1076{
1077 int ret;
1078
1079 toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
1080 if (!toshiba_proc_dir) {
1081 pr_err("Unable to create proc dir " PROC_TOSHIBA "\n");
1082 return -ENODEV;
1083 }
1084
1085 ret = acpi_bus_register_driver(&toshiba_acpi_driver);
1086 if (ret) {
1087 pr_err("Failed to register ACPI driver: %d\n", ret);
1088 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
1089 }
1090
1091 return ret;
1092}
1093
1094static void __exit toshiba_acpi_exit(void)
1095{
1096 acpi_bus_unregister_driver(&toshiba_acpi_driver);
1097 if (toshiba_proc_dir)
1098 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
1064} 1099}
1065 1100
1066module_init(toshiba_acpi_init); 1101module_init(toshiba_acpi_init);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index f23d5a84e7b1..9b88be42b6cd 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -754,9 +754,13 @@ static void wmi_free_devices(void)
754 struct wmi_block *wblock, *next; 754 struct wmi_block *wblock, *next;
755 755
756 /* Delete devices for all the GUIDs */ 756 /* Delete devices for all the GUIDs */
757 list_for_each_entry_safe(wblock, next, &wmi_block_list, list) 757 list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
758 list_del(&wblock->list);
758 if (wblock->dev.class) 759 if (wblock->dev.class)
759 device_unregister(&wblock->dev); 760 device_unregister(&wblock->dev);
761 else
762 kfree(wblock);
763 }
760} 764}
761 765
762static bool guid_already_parsed(const char *guid_string) 766static bool guid_already_parsed(const char *guid_string)