diff options
| -rw-r--r-- | drivers/platform/x86/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 190 |
2 files changed, 201 insertions, 0 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index e65448e99b48..431772b8a1d0 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -192,6 +192,17 @@ config THINKPAD_ACPI | |||
| 192 | 192 | ||
| 193 | If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. | 193 | If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. |
| 194 | 194 | ||
| 195 | config THINKPAD_ACPI_DEBUGFACILITIES | ||
| 196 | bool "Maintainer debug facilities" | ||
| 197 | depends on THINKPAD_ACPI | ||
| 198 | default n | ||
| 199 | ---help--- | ||
| 200 | Enables extra stuff in the thinkpad-acpi which is completely useless | ||
| 201 | for normal use. Read the driver source to find out what it does. | ||
| 202 | |||
| 203 | Say N here, unless you were told by a kernel maintainer to do | ||
| 204 | otherwise. | ||
| 205 | |||
| 195 | config THINKPAD_ACPI_DEBUG | 206 | config THINKPAD_ACPI_DEBUG |
| 196 | bool "Verbose debug mode" | 207 | bool "Verbose debug mode" |
| 197 | depends on THINKPAD_ACPI | 208 | depends on THINKPAD_ACPI |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index ee3fa007f312..a086ce8ed4eb 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -288,6 +288,16 @@ struct tpacpi_led_classdev { | |||
| 288 | unsigned int led; | 288 | unsigned int led; |
| 289 | }; | 289 | }; |
| 290 | 290 | ||
| 291 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 292 | static int dbg_wlswemul; | ||
| 293 | static int tpacpi_wlsw_emulstate; | ||
| 294 | static int dbg_bluetoothemul; | ||
| 295 | static int tpacpi_bluetooth_emulstate; | ||
| 296 | static int dbg_wwanemul; | ||
| 297 | static int tpacpi_wwan_emulstate; | ||
| 298 | #endif | ||
| 299 | |||
| 300 | |||
| 291 | /**************************************************************************** | 301 | /**************************************************************************** |
| 292 | **************************************************************************** | 302 | **************************************************************************** |
| 293 | * | 303 | * |
| @@ -1006,6 +1016,94 @@ static DRIVER_ATTR(version, S_IRUGO, | |||
| 1006 | 1016 | ||
| 1007 | /* --------------------------------------------------------------------- */ | 1017 | /* --------------------------------------------------------------------- */ |
| 1008 | 1018 | ||
| 1019 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 1020 | |||
| 1021 | static void tpacpi_send_radiosw_update(void); | ||
| 1022 | |||
| 1023 | /* wlsw_emulstate ------------------------------------------------------ */ | ||
| 1024 | static ssize_t tpacpi_driver_wlsw_emulstate_show(struct device_driver *drv, | ||
| 1025 | char *buf) | ||
| 1026 | { | ||
| 1027 | return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wlsw_emulstate); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | static ssize_t tpacpi_driver_wlsw_emulstate_store(struct device_driver *drv, | ||
| 1031 | const char *buf, size_t count) | ||
| 1032 | { | ||
| 1033 | unsigned long t; | ||
| 1034 | |||
| 1035 | if (parse_strtoul(buf, 1, &t)) | ||
| 1036 | return -EINVAL; | ||
| 1037 | |||
| 1038 | if (tpacpi_wlsw_emulstate != t) { | ||
| 1039 | tpacpi_wlsw_emulstate = !!t; | ||
| 1040 | tpacpi_send_radiosw_update(); | ||
| 1041 | } else | ||
| 1042 | tpacpi_wlsw_emulstate = !!t; | ||
| 1043 | |||
| 1044 | return count; | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | static DRIVER_ATTR(wlsw_emulstate, S_IWUSR | S_IRUGO, | ||
| 1048 | tpacpi_driver_wlsw_emulstate_show, | ||
| 1049 | tpacpi_driver_wlsw_emulstate_store); | ||
| 1050 | |||
| 1051 | /* bluetooth_emulstate ------------------------------------------------- */ | ||
| 1052 | static ssize_t tpacpi_driver_bluetooth_emulstate_show( | ||
| 1053 | struct device_driver *drv, | ||
| 1054 | char *buf) | ||
| 1055 | { | ||
| 1056 | return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_bluetooth_emulstate); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | static ssize_t tpacpi_driver_bluetooth_emulstate_store( | ||
| 1060 | struct device_driver *drv, | ||
| 1061 | const char *buf, size_t count) | ||
| 1062 | { | ||
| 1063 | unsigned long t; | ||
| 1064 | |||
| 1065 | if (parse_strtoul(buf, 1, &t)) | ||
| 1066 | return -EINVAL; | ||
| 1067 | |||
| 1068 | tpacpi_bluetooth_emulstate = !!t; | ||
| 1069 | |||
| 1070 | return count; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | static DRIVER_ATTR(bluetooth_emulstate, S_IWUSR | S_IRUGO, | ||
| 1074 | tpacpi_driver_bluetooth_emulstate_show, | ||
| 1075 | tpacpi_driver_bluetooth_emulstate_store); | ||
| 1076 | |||
| 1077 | /* wwan_emulstate ------------------------------------------------- */ | ||
| 1078 | static ssize_t tpacpi_driver_wwan_emulstate_show( | ||
| 1079 | struct device_driver *drv, | ||
| 1080 | char *buf) | ||
| 1081 | { | ||
| 1082 | return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wwan_emulstate); | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | static ssize_t tpacpi_driver_wwan_emulstate_store( | ||
| 1086 | struct device_driver *drv, | ||
| 1087 | const char *buf, size_t count) | ||
| 1088 | { | ||
| 1089 | unsigned long t; | ||
| 1090 | |||
| 1091 | if (parse_strtoul(buf, 1, &t)) | ||
| 1092 | return -EINVAL; | ||
| 1093 | |||
| 1094 | tpacpi_wwan_emulstate = !!t; | ||
| 1095 | |||
| 1096 | return count; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | static DRIVER_ATTR(wwan_emulstate, S_IWUSR | S_IRUGO, | ||
| 1100 | tpacpi_driver_wwan_emulstate_show, | ||
| 1101 | tpacpi_driver_wwan_emulstate_store); | ||
| 1102 | |||
| 1103 | #endif | ||
| 1104 | |||
| 1105 | /* --------------------------------------------------------------------- */ | ||
| 1106 | |||
| 1009 | static struct driver_attribute *tpacpi_driver_attributes[] = { | 1107 | static struct driver_attribute *tpacpi_driver_attributes[] = { |
| 1010 | &driver_attr_debug_level, &driver_attr_version, | 1108 | &driver_attr_debug_level, &driver_attr_version, |
| 1011 | &driver_attr_interface_version, | 1109 | &driver_attr_interface_version, |
| @@ -1022,6 +1120,15 @@ static int __init tpacpi_create_driver_attributes(struct device_driver *drv) | |||
| 1022 | i++; | 1120 | i++; |
| 1023 | } | 1121 | } |
| 1024 | 1122 | ||
| 1123 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 1124 | if (!res && dbg_wlswemul) | ||
| 1125 | res = driver_create_file(drv, &driver_attr_wlsw_emulstate); | ||
| 1126 | if (!res && dbg_bluetoothemul) | ||
| 1127 | res = driver_create_file(drv, &driver_attr_bluetooth_emulstate); | ||
| 1128 | if (!res && dbg_wwanemul) | ||
| 1129 | res = driver_create_file(drv, &driver_attr_wwan_emulstate); | ||
| 1130 | #endif | ||
| 1131 | |||
| 1025 | return res; | 1132 | return res; |
| 1026 | } | 1133 | } |
| 1027 | 1134 | ||
| @@ -1031,6 +1138,12 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv) | |||
| 1031 | 1138 | ||
| 1032 | for (i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++) | 1139 | for (i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++) |
| 1033 | driver_remove_file(drv, tpacpi_driver_attributes[i]); | 1140 | driver_remove_file(drv, tpacpi_driver_attributes[i]); |
| 1141 | |||
| 1142 | #ifdef THINKPAD_ACPI_DEBUGFACILITIES | ||
| 1143 | driver_remove_file(drv, &driver_attr_wlsw_emulstate); | ||
| 1144 | driver_remove_file(drv, &driver_attr_bluetooth_emulstate); | ||
| 1145 | driver_remove_file(drv, &driver_attr_wwan_emulstate); | ||
| 1146 | #endif | ||
| 1034 | } | 1147 | } |
| 1035 | 1148 | ||
| 1036 | /**************************************************************************** | 1149 | /**************************************************************************** |
| @@ -1216,6 +1329,12 @@ static struct attribute_set *hotkey_dev_attributes; | |||
| 1216 | 1329 | ||
| 1217 | static int hotkey_get_wlsw(int *status) | 1330 | static int hotkey_get_wlsw(int *status) |
| 1218 | { | 1331 | { |
| 1332 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 1333 | if (dbg_wlswemul) { | ||
| 1334 | *status = !!tpacpi_wlsw_emulstate; | ||
| 1335 | return 0; | ||
| 1336 | } | ||
| 1337 | #endif | ||
| 1219 | if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) | 1338 | if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) |
| 1220 | return -EIO; | 1339 | return -EIO; |
| 1221 | return 0; | 1340 | return 0; |
| @@ -2222,6 +2341,13 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 2222 | hotkey_source_mask, hotkey_poll_freq); | 2341 | hotkey_source_mask, hotkey_poll_freq); |
| 2223 | #endif | 2342 | #endif |
| 2224 | 2343 | ||
| 2344 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 2345 | if (dbg_wlswemul) { | ||
| 2346 | tp_features.hotkey_wlsw = 1; | ||
| 2347 | printk(TPACPI_INFO | ||
| 2348 | "radio switch emulation enabled\n"); | ||
| 2349 | } else | ||
| 2350 | #endif | ||
| 2225 | /* Not all thinkpads have a hardware radio switch */ | 2351 | /* Not all thinkpads have a hardware radio switch */ |
| 2226 | if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { | 2352 | if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { |
| 2227 | tp_features.hotkey_wlsw = 1; | 2353 | tp_features.hotkey_wlsw = 1; |
| @@ -2656,6 +2782,12 @@ static int bluetooth_get_radiosw(void) | |||
| 2656 | if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) | 2782 | if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) |
| 2657 | return RFKILL_STATE_HARD_BLOCKED; | 2783 | return RFKILL_STATE_HARD_BLOCKED; |
| 2658 | 2784 | ||
| 2785 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 2786 | if (dbg_bluetoothemul) | ||
| 2787 | return (tpacpi_bluetooth_emulstate) ? | ||
| 2788 | RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; | ||
| 2789 | #endif | ||
| 2790 | |||
| 2659 | if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) | 2791 | if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) |
| 2660 | return -EIO; | 2792 | return -EIO; |
| 2661 | 2793 | ||
| @@ -2689,6 +2821,15 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk) | |||
| 2689 | && radio_on) | 2821 | && radio_on) |
| 2690 | return -EPERM; | 2822 | return -EPERM; |
| 2691 | 2823 | ||
| 2824 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 2825 | if (dbg_bluetoothemul) { | ||
| 2826 | tpacpi_bluetooth_emulstate = !!radio_on; | ||
| 2827 | if (update_rfk) | ||
| 2828 | bluetooth_update_rfk(); | ||
| 2829 | return 0; | ||
| 2830 | } | ||
| 2831 | #endif | ||
| 2832 | |||
| 2692 | if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) | 2833 | if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) |
| 2693 | return -EIO; | 2834 | return -EIO; |
| 2694 | if (radio_on) | 2835 | if (radio_on) |
| @@ -2792,6 +2933,13 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) | |||
| 2792 | str_supported(tp_features.bluetooth), | 2933 | str_supported(tp_features.bluetooth), |
| 2793 | status); | 2934 | status); |
| 2794 | 2935 | ||
| 2936 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 2937 | if (dbg_bluetoothemul) { | ||
| 2938 | tp_features.bluetooth = 1; | ||
| 2939 | printk(TPACPI_INFO | ||
| 2940 | "bluetooth switch emulation enabled\n"); | ||
| 2941 | } else | ||
| 2942 | #endif | ||
| 2795 | if (tp_features.bluetooth && | 2943 | if (tp_features.bluetooth && |
| 2796 | !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { | 2944 | !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { |
| 2797 | /* no bluetooth hardware present in system */ | 2945 | /* no bluetooth hardware present in system */ |
| @@ -2890,6 +3038,12 @@ static int wan_get_radiosw(void) | |||
| 2890 | if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) | 3038 | if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) |
| 2891 | return RFKILL_STATE_HARD_BLOCKED; | 3039 | return RFKILL_STATE_HARD_BLOCKED; |
| 2892 | 3040 | ||
| 3041 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 3042 | if (dbg_wwanemul) | ||
| 3043 | return (tpacpi_wwan_emulstate) ? | ||
| 3044 | RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; | ||
| 3045 | #endif | ||
| 3046 | |||
| 2893 | if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) | 3047 | if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) |
| 2894 | return -EIO; | 3048 | return -EIO; |
| 2895 | 3049 | ||
| @@ -2923,6 +3077,15 @@ static int wan_set_radiosw(int radio_on, int update_rfk) | |||
| 2923 | && radio_on) | 3077 | && radio_on) |
| 2924 | return -EPERM; | 3078 | return -EPERM; |
| 2925 | 3079 | ||
| 3080 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 3081 | if (dbg_wwanemul) { | ||
| 3082 | tpacpi_wwan_emulstate = !!radio_on; | ||
| 3083 | if (update_rfk) | ||
| 3084 | wan_update_rfk(); | ||
| 3085 | return 0; | ||
| 3086 | } | ||
| 3087 | #endif | ||
| 3088 | |||
| 2926 | if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) | 3089 | if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) |
| 2927 | return -EIO; | 3090 | return -EIO; |
| 2928 | if (radio_on) | 3091 | if (radio_on) |
| @@ -3024,6 +3187,13 @@ static int __init wan_init(struct ibm_init_struct *iibm) | |||
| 3024 | str_supported(tp_features.wan), | 3187 | str_supported(tp_features.wan), |
| 3025 | status); | 3188 | status); |
| 3026 | 3189 | ||
| 3190 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 3191 | if (dbg_wwanemul) { | ||
| 3192 | tp_features.wan = 1; | ||
| 3193 | printk(TPACPI_INFO | ||
| 3194 | "wwan switch emulation enabled\n"); | ||
| 3195 | } else | ||
| 3196 | #endif | ||
| 3027 | if (tp_features.wan && | 3197 | if (tp_features.wan && |
| 3028 | !(status & TP_ACPI_WANCARD_HWPRESENT)) { | 3198 | !(status & TP_ACPI_WANCARD_HWPRESENT)) { |
| 3029 | /* no wan hardware present in system */ | 3199 | /* no wan hardware present in system */ |
| @@ -6701,6 +6871,26 @@ TPACPI_PARAM(brightness); | |||
| 6701 | TPACPI_PARAM(volume); | 6871 | TPACPI_PARAM(volume); |
| 6702 | TPACPI_PARAM(fan); | 6872 | TPACPI_PARAM(fan); |
| 6703 | 6873 | ||
| 6874 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | ||
| 6875 | module_param(dbg_wlswemul, uint, 0); | ||
| 6876 | MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation"); | ||
| 6877 | module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0); | ||
| 6878 | MODULE_PARM_DESC(wlsw_state, | ||
| 6879 | "Initial state of the emulated WLSW switch"); | ||
| 6880 | |||
| 6881 | module_param(dbg_bluetoothemul, uint, 0); | ||
| 6882 | MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation"); | ||
| 6883 | module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0); | ||
| 6884 | MODULE_PARM_DESC(bluetooth_state, | ||
| 6885 | "Initial state of the emulated bluetooth switch"); | ||
| 6886 | |||
| 6887 | module_param(dbg_wwanemul, uint, 0); | ||
| 6888 | MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation"); | ||
| 6889 | module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0); | ||
| 6890 | MODULE_PARM_DESC(wwan_state, | ||
| 6891 | "Initial state of the emulated WWAN switch"); | ||
| 6892 | #endif | ||
| 6893 | |||
| 6704 | static void thinkpad_acpi_module_exit(void) | 6894 | static void thinkpad_acpi_module_exit(void) |
| 6705 | { | 6895 | { |
| 6706 | struct ibm_struct *ibm, *itmp; | 6896 | struct ibm_struct *ibm, *itmp; |
