aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2009-01-11 00:01:02 -0500
committerLen Brown <len.brown@intel.com>2009-01-15 13:36:25 -0500
commit90d9d3c79c44bcf95bc487e9bbceaff2de370310 (patch)
tree3cb097801f97c106bef5cc743db86bc665a15ccb
parent153f82207c51193e4d6a7e6f0e3f9442eabeba1c (diff)
ACPI: thinkpad-acpi: preserve radio state across shutdown
Store in firmware NVRAM the radio state on machine shutdown for WWAN and bluetooth. Also, try to set the initial boot state of these radios as the rfkill default state for their respective classes. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Cc: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c59
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
763static 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
762static struct platform_driver tpacpi_pdriver = { 775static 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
771static struct platform_driver tpacpi_hwmon_pdriver = { 785static 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
2973static 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
2946static void bluetooth_exit(void) 2982static 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
3249static 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
3210static void wan_exit(void) 3258static 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/*************************************************************************