aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c66
1 files changed, 56 insertions, 10 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index a086ce8ed4eb..b2c5913ff72e 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -122,6 +122,27 @@ enum {
122#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */ 122#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */
123#define TPACPI_HKEY_INPUT_VERSION 0x4101 123#define TPACPI_HKEY_INPUT_VERSION 0x4101
124 124
125/* ACPI \WGSV commands */
126enum {
127 TP_ACPI_WGSV_GET_STATE = 0x01, /* Get state information */
128 TP_ACPI_WGSV_PWR_ON_ON_RESUME = 0x02, /* Resume WWAN powered on */
129 TP_ACPI_WGSV_PWR_OFF_ON_RESUME = 0x03, /* Resume WWAN powered off */
130 TP_ACPI_WGSV_SAVE_STATE = 0x04, /* Save state for S4/S5 */
131};
132
133/* TP_ACPI_WGSV_GET_STATE bits */
134enum {
135 TP_ACPI_WGSV_STATE_WWANEXIST = 0x0001, /* WWAN hw available */
136 TP_ACPI_WGSV_STATE_WWANPWR = 0x0002, /* WWAN radio enabled */
137 TP_ACPI_WGSV_STATE_WWANPWRRES = 0x0004, /* WWAN state at resume */
138 TP_ACPI_WGSV_STATE_WWANBIOSOFF = 0x0008, /* WWAN disabled in BIOS */
139 TP_ACPI_WGSV_STATE_BLTHEXIST = 0x0001, /* BLTH hw available */
140 TP_ACPI_WGSV_STATE_BLTHPWR = 0x0002, /* BLTH radio enabled */
141 TP_ACPI_WGSV_STATE_BLTHPWRRES = 0x0004, /* BLTH state at resume */
142 TP_ACPI_WGSV_STATE_BLTHBIOSOFF = 0x0008, /* BLTH disabled in BIOS */
143 TP_ACPI_WGSV_STATE_UWBEXIST = 0x0010, /* UWB hw available */
144 TP_ACPI_WGSV_STATE_UWBPWR = 0x0020, /* UWB radio enabled */
145};
125 146
126/**************************************************************************** 147/****************************************************************************
127 * Main driver 148 * Main driver
@@ -2766,11 +2787,28 @@ enum {
2766 /* ACPI GBDC/SBDC bits */ 2787 /* ACPI GBDC/SBDC bits */
2767 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ 2788 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */
2768 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */ 2789 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */
2769 TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */ 2790 TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume:
2791 off / last state */
2792};
2793
2794enum {
2795 /* ACPI \BLTH commands */
2796 TP_ACPI_BLTH_GET_ULTRAPORT_ID = 0x00, /* Get Ultraport BT ID */
2797 TP_ACPI_BLTH_GET_PWR_ON_RESUME = 0x01, /* Get power-on-resume state */
2798 TP_ACPI_BLTH_PWR_ON_ON_RESUME = 0x02, /* Resume powered on */
2799 TP_ACPI_BLTH_PWR_OFF_ON_RESUME = 0x03, /* Resume powered off */
2800 TP_ACPI_BLTH_SAVE_STATE = 0x05, /* Save state for S4/S5 */
2770}; 2801};
2771 2802
2772static struct rfkill *tpacpi_bluetooth_rfkill; 2803static struct rfkill *tpacpi_bluetooth_rfkill;
2773 2804
2805static void bluetooth_suspend(pm_message_t state)
2806{
2807 /* Try to make sure radio will resume powered off */
2808 acpi_evalf(NULL, NULL, "\\BLTH", "vd",
2809 TP_ACPI_BLTH_PWR_OFF_ON_RESUME);
2810}
2811
2774static int bluetooth_get_radiosw(void) 2812static int bluetooth_get_radiosw(void)
2775{ 2813{
2776 int status; 2814 int status;
@@ -2830,12 +2868,11 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk)
2830 } 2868 }
2831#endif 2869#endif
2832 2870
2833 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) 2871 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
2834 return -EIO;
2835 if (radio_on) 2872 if (radio_on)
2836 status |= TP_ACPI_BLUETOOTH_RADIOSSW; 2873 status = TP_ACPI_BLUETOOTH_RADIOSSW;
2837 else 2874 else
2838 status &= ~TP_ACPI_BLUETOOTH_RADIOSSW; 2875 status = 0;
2839 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 2876 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
2840 return -EIO; 2877 return -EIO;
2841 2878
@@ -3012,6 +3049,7 @@ static struct ibm_struct bluetooth_driver_data = {
3012 .read = bluetooth_read, 3049 .read = bluetooth_read,
3013 .write = bluetooth_write, 3050 .write = bluetooth_write,
3014 .exit = bluetooth_exit, 3051 .exit = bluetooth_exit,
3052 .suspend = bluetooth_suspend,
3015}; 3053};
3016 3054
3017/************************************************************************* 3055/*************************************************************************
@@ -3022,11 +3060,19 @@ enum {
3022 /* ACPI GWAN/SWAN bits */ 3060 /* ACPI GWAN/SWAN bits */
3023 TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */ 3061 TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */
3024 TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */ 3062 TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */
3025 TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */ 3063 TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume:
3064 off / last state */
3026}; 3065};
3027 3066
3028static struct rfkill *tpacpi_wan_rfkill; 3067static struct rfkill *tpacpi_wan_rfkill;
3029 3068
3069static void wan_suspend(pm_message_t state)
3070{
3071 /* Try to make sure radio will resume powered off */
3072 acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
3073 TP_ACPI_WGSV_PWR_OFF_ON_RESUME);
3074}
3075
3030static int wan_get_radiosw(void) 3076static int wan_get_radiosw(void)
3031{ 3077{
3032 int status; 3078 int status;
@@ -3086,12 +3132,11 @@ static int wan_set_radiosw(int radio_on, int update_rfk)
3086 } 3132 }
3087#endif 3133#endif
3088 3134
3089 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) 3135 /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */
3090 return -EIO;
3091 if (radio_on) 3136 if (radio_on)
3092 status |= TP_ACPI_WANCARD_RADIOSSW; 3137 status = TP_ACPI_WANCARD_RADIOSSW;
3093 else 3138 else
3094 status &= ~TP_ACPI_WANCARD_RADIOSSW; 3139 status = 0;
3095 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 3140 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
3096 return -EIO; 3141 return -EIO;
3097 3142
@@ -3266,6 +3311,7 @@ static struct ibm_struct wan_driver_data = {
3266 .read = wan_read, 3311 .read = wan_read,
3267 .write = wan_write, 3312 .write = wan_write,
3268 .exit = wan_exit, 3313 .exit = wan_exit,
3314 .suspend = wan_suspend,
3269}; 3315};
3270 3316
3271/************************************************************************* 3317/*************************************************************************