diff options
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index b2c5913ff72e..27d709bac98f 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -222,6 +222,7 @@ struct ibm_struct { | |||
222 | void (*exit) (void); | 222 | void (*exit) (void); |
223 | void (*resume) (void); | 223 | void (*resume) (void); |
224 | void (*suspend) (pm_message_t state); | 224 | void (*suspend) (pm_message_t state); |
225 | void (*shutdown) (void); | ||
225 | 226 | ||
226 | struct list_head all_drivers; | 227 | struct list_head all_drivers; |
227 | 228 | ||
@@ -759,6 +760,18 @@ static int tpacpi_resume_handler(struct platform_device *pdev) | |||
759 | return 0; | 760 | return 0; |
760 | } | 761 | } |
761 | 762 | ||
763 | static void tpacpi_shutdown_handler(struct platform_device *pdev) | ||
764 | { | ||
765 | struct ibm_struct *ibm, *itmp; | ||
766 | |||
767 | list_for_each_entry_safe(ibm, itmp, | ||
768 | &tpacpi_all_drivers, | ||
769 | all_drivers) { | ||
770 | if (ibm->shutdown) | ||
771 | (ibm->shutdown)(); | ||
772 | } | ||
773 | } | ||
774 | |||
762 | static struct platform_driver tpacpi_pdriver = { | 775 | static struct platform_driver tpacpi_pdriver = { |
763 | .driver = { | 776 | .driver = { |
764 | .name = TPACPI_DRVR_NAME, | 777 | .name = TPACPI_DRVR_NAME, |
@@ -766,6 +779,7 @@ static struct platform_driver tpacpi_pdriver = { | |||
766 | }, | 779 | }, |
767 | .suspend = tpacpi_suspend_handler, | 780 | .suspend = tpacpi_suspend_handler, |
768 | .resume = tpacpi_resume_handler, | 781 | .resume = tpacpi_resume_handler, |
782 | .shutdown = tpacpi_shutdown_handler, | ||
769 | }; | 783 | }; |
770 | 784 | ||
771 | static struct platform_driver tpacpi_hwmon_pdriver = { | 785 | static struct platform_driver tpacpi_hwmon_pdriver = { |
@@ -957,7 +971,22 @@ static int __init tpacpi_new_rfkill(const unsigned int id, | |||
957 | int (*get_state)(void *, enum rfkill_state *)) | 971 | int (*get_state)(void *, enum rfkill_state *)) |
958 | { | 972 | { |
959 | int res; | 973 | int res; |
960 | enum rfkill_state initial_state; | 974 | enum rfkill_state initial_state = RFKILL_STATE_SOFT_BLOCKED; |
975 | |||
976 | res = get_state(NULL, &initial_state); | ||
977 | if (res < 0) { | ||
978 | printk(TPACPI_ERR | ||
979 | "failed to read initial state for %s, error %d; " | ||
980 | "will turn radio off\n", name, res); | ||
981 | } else { | ||
982 | /* try to set the initial state as the default for the rfkill | ||
983 | * type, since we ask the firmware to preserve it across S5 in | ||
984 | * NVRAM */ | ||
985 | rfkill_set_default(rfktype, | ||
986 | (initial_state == RFKILL_STATE_UNBLOCKED) ? | ||
987 | RFKILL_STATE_UNBLOCKED : | ||
988 | RFKILL_STATE_SOFT_BLOCKED); | ||
989 | } | ||
961 | 990 | ||
962 | *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); | 991 | *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); |
963 | if (!*rfk) { | 992 | if (!*rfk) { |
@@ -969,9 +998,7 @@ static int __init tpacpi_new_rfkill(const unsigned int id, | |||
969 | (*rfk)->name = name; | 998 | (*rfk)->name = name; |
970 | (*rfk)->get_state = get_state; | 999 | (*rfk)->get_state = get_state; |
971 | (*rfk)->toggle_radio = toggle_radio; | 1000 | (*rfk)->toggle_radio = toggle_radio; |
972 | 1001 | (*rfk)->state = initial_state; | |
973 | if (!get_state(NULL, &initial_state)) | ||
974 | (*rfk)->state = initial_state; | ||
975 | 1002 | ||
976 | res = rfkill_register(*rfk); | 1003 | res = rfkill_register(*rfk); |
977 | if (res < 0) { | 1004 | if (res < 0) { |
@@ -2943,8 +2970,19 @@ static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state) | |||
2943 | return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); | 2970 | return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); |
2944 | } | 2971 | } |
2945 | 2972 | ||
2973 | static void bluetooth_shutdown(void) | ||
2974 | { | ||
2975 | /* Order firmware to save current state to NVRAM */ | ||
2976 | if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd", | ||
2977 | TP_ACPI_BLTH_SAVE_STATE)) | ||
2978 | printk(TPACPI_NOTICE | ||
2979 | "failed to save bluetooth state to NVRAM\n"); | ||
2980 | } | ||
2981 | |||
2946 | static void bluetooth_exit(void) | 2982 | static void bluetooth_exit(void) |
2947 | { | 2983 | { |
2984 | bluetooth_shutdown(); | ||
2985 | |||
2948 | if (tpacpi_bluetooth_rfkill) | 2986 | if (tpacpi_bluetooth_rfkill) |
2949 | rfkill_unregister(tpacpi_bluetooth_rfkill); | 2987 | rfkill_unregister(tpacpi_bluetooth_rfkill); |
2950 | 2988 | ||
@@ -3050,6 +3088,7 @@ static struct ibm_struct bluetooth_driver_data = { | |||
3050 | .write = bluetooth_write, | 3088 | .write = bluetooth_write, |
3051 | .exit = bluetooth_exit, | 3089 | .exit = bluetooth_exit, |
3052 | .suspend = bluetooth_suspend, | 3090 | .suspend = bluetooth_suspend, |
3091 | .shutdown = bluetooth_shutdown, | ||
3053 | }; | 3092 | }; |
3054 | 3093 | ||
3055 | /************************************************************************* | 3094 | /************************************************************************* |
@@ -3207,8 +3246,19 @@ static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state) | |||
3207 | return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); | 3246 | return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); |
3208 | } | 3247 | } |
3209 | 3248 | ||
3249 | static void wan_shutdown(void) | ||
3250 | { | ||
3251 | /* Order firmware to save current state to NVRAM */ | ||
3252 | if (!acpi_evalf(NULL, NULL, "\\WGSV", "vd", | ||
3253 | TP_ACPI_WGSV_SAVE_STATE)) | ||
3254 | printk(TPACPI_NOTICE | ||
3255 | "failed to save WWAN state to NVRAM\n"); | ||
3256 | } | ||
3257 | |||
3210 | static void wan_exit(void) | 3258 | static void wan_exit(void) |
3211 | { | 3259 | { |
3260 | wan_shutdown(); | ||
3261 | |||
3212 | if (tpacpi_wan_rfkill) | 3262 | if (tpacpi_wan_rfkill) |
3213 | rfkill_unregister(tpacpi_wan_rfkill); | 3263 | rfkill_unregister(tpacpi_wan_rfkill); |
3214 | 3264 | ||
@@ -3312,6 +3362,7 @@ static struct ibm_struct wan_driver_data = { | |||
3312 | .write = wan_write, | 3362 | .write = wan_write, |
3313 | .exit = wan_exit, | 3363 | .exit = wan_exit, |
3314 | .suspend = wan_suspend, | 3364 | .suspend = wan_suspend, |
3365 | .shutdown = wan_shutdown, | ||
3315 | }; | 3366 | }; |
3316 | 3367 | ||
3317 | /************************************************************************* | 3368 | /************************************************************************* |