aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/thinkpad_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/thinkpad_acpi.c')
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c116
1 files changed, 79 insertions, 37 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index eb603f1d55ca..e7b0c3bcef89 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -286,6 +286,7 @@ struct ibm_init_struct {
286 char param[32]; 286 char param[32];
287 287
288 int (*init) (struct ibm_init_struct *); 288 int (*init) (struct ibm_init_struct *);
289 mode_t base_procfs_mode;
289 struct ibm_struct *data; 290 struct ibm_struct *data;
290}; 291};
291 292
@@ -2082,6 +2083,7 @@ static struct attribute_set *hotkey_dev_attributes;
2082 2083
2083static void tpacpi_driver_event(const unsigned int hkey_event); 2084static void tpacpi_driver_event(const unsigned int hkey_event);
2084static void hotkey_driver_event(const unsigned int scancode); 2085static void hotkey_driver_event(const unsigned int scancode);
2086static void hotkey_poll_setup(const bool may_warn);
2085 2087
2086/* HKEY.MHKG() return bits */ 2088/* HKEY.MHKG() return bits */
2087#define TP_HOTKEY_TABLET_MASK (1 << 3) 2089#define TP_HOTKEY_TABLET_MASK (1 << 3)
@@ -2264,6 +2266,8 @@ static int tpacpi_hotkey_driver_mask_set(const u32 mask)
2264 2266
2265 rc = hotkey_mask_set((hotkey_acpi_mask | hotkey_driver_mask) & 2267 rc = hotkey_mask_set((hotkey_acpi_mask | hotkey_driver_mask) &
2266 ~hotkey_source_mask); 2268 ~hotkey_source_mask);
2269 hotkey_poll_setup(true);
2270
2267 mutex_unlock(&hotkey_mutex); 2271 mutex_unlock(&hotkey_mutex);
2268 2272
2269 return rc; 2273 return rc;
@@ -2548,7 +2552,7 @@ static void hotkey_poll_stop_sync(void)
2548} 2552}
2549 2553
2550/* call with hotkey_mutex held */ 2554/* call with hotkey_mutex held */
2551static void hotkey_poll_setup(bool may_warn) 2555static void hotkey_poll_setup(const bool may_warn)
2552{ 2556{
2553 const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask; 2557 const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask;
2554 const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask; 2558 const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask;
@@ -2579,7 +2583,7 @@ static void hotkey_poll_setup(bool may_warn)
2579 } 2583 }
2580} 2584}
2581 2585
2582static void hotkey_poll_setup_safe(bool may_warn) 2586static void hotkey_poll_setup_safe(const bool may_warn)
2583{ 2587{
2584 mutex_lock(&hotkey_mutex); 2588 mutex_lock(&hotkey_mutex);
2585 hotkey_poll_setup(may_warn); 2589 hotkey_poll_setup(may_warn);
@@ -2597,7 +2601,11 @@ static void hotkey_poll_set_freq(unsigned int freq)
2597 2601
2598#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ 2602#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
2599 2603
2600static void hotkey_poll_setup_safe(bool __unused) 2604static void hotkey_poll_setup(const bool __unused)
2605{
2606}
2607
2608static void hotkey_poll_setup_safe(const bool __unused)
2601{ 2609{
2602} 2610}
2603 2611
@@ -2607,16 +2615,11 @@ static int hotkey_inputdev_open(struct input_dev *dev)
2607{ 2615{
2608 switch (tpacpi_lifecycle) { 2616 switch (tpacpi_lifecycle) {
2609 case TPACPI_LIFE_INIT: 2617 case TPACPI_LIFE_INIT:
2610 /*
2611 * hotkey_init will call hotkey_poll_setup_safe
2612 * at the appropriate moment
2613 */
2614 return 0;
2615 case TPACPI_LIFE_EXITING:
2616 return -EBUSY;
2617 case TPACPI_LIFE_RUNNING: 2618 case TPACPI_LIFE_RUNNING:
2618 hotkey_poll_setup_safe(false); 2619 hotkey_poll_setup_safe(false);
2619 return 0; 2620 return 0;
2621 case TPACPI_LIFE_EXITING:
2622 return -EBUSY;
2620 } 2623 }
2621 2624
2622 /* Should only happen if tpacpi_lifecycle is corrupt */ 2625 /* Should only happen if tpacpi_lifecycle is corrupt */
@@ -2627,7 +2630,7 @@ static int hotkey_inputdev_open(struct input_dev *dev)
2627static void hotkey_inputdev_close(struct input_dev *dev) 2630static void hotkey_inputdev_close(struct input_dev *dev)
2628{ 2631{
2629 /* disable hotkey polling when possible */ 2632 /* disable hotkey polling when possible */
2630 if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING && 2633 if (tpacpi_lifecycle != TPACPI_LIFE_EXITING &&
2631 !(hotkey_source_mask & hotkey_driver_mask)) 2634 !(hotkey_source_mask & hotkey_driver_mask))
2632 hotkey_poll_setup_safe(false); 2635 hotkey_poll_setup_safe(false);
2633} 2636}
@@ -3655,13 +3658,19 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
3655 break; 3658 break;
3656 case 3: 3659 case 3:
3657 /* 0x3000-0x3FFF: bay-related wakeups */ 3660 /* 0x3000-0x3FFF: bay-related wakeups */
3658 if (hkey == TP_HKEY_EV_BAYEJ_ACK) { 3661 switch (hkey) {
3662 case TP_HKEY_EV_BAYEJ_ACK:
3659 hotkey_autosleep_ack = 1; 3663 hotkey_autosleep_ack = 1;
3660 printk(TPACPI_INFO 3664 printk(TPACPI_INFO
3661 "bay ejected\n"); 3665 "bay ejected\n");
3662 hotkey_wakeup_hotunplug_complete_notify_change(); 3666 hotkey_wakeup_hotunplug_complete_notify_change();
3663 known_ev = true; 3667 known_ev = true;
3664 } else { 3668 break;
3669 case TP_HKEY_EV_OPTDRV_EJ:
3670 /* FIXME: kick libata if SATA link offline */
3671 known_ev = true;
3672 break;
3673 default:
3665 known_ev = false; 3674 known_ev = false;
3666 } 3675 }
3667 break; 3676 break;
@@ -3870,7 +3879,7 @@ enum {
3870 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ 3879 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */
3871 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */ 3880 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */
3872 TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume: 3881 TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume:
3873 off / last state */ 3882 0 = disable, 1 = enable */
3874}; 3883};
3875 3884
3876enum { 3885enum {
@@ -3916,10 +3925,11 @@ static int bluetooth_set_status(enum tpacpi_rfkill_state state)
3916 } 3925 }
3917#endif 3926#endif
3918 3927
3919 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
3920 status = TP_ACPI_BLUETOOTH_RESUMECTRL;
3921 if (state == TPACPI_RFK_RADIO_ON) 3928 if (state == TPACPI_RFK_RADIO_ON)
3922 status |= TP_ACPI_BLUETOOTH_RADIOSSW; 3929 status = TP_ACPI_BLUETOOTH_RADIOSSW
3930 | TP_ACPI_BLUETOOTH_RESUMECTRL;
3931 else
3932 status = 0;
3923 3933
3924 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 3934 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
3925 return -EIO; 3935 return -EIO;
@@ -4070,7 +4080,7 @@ enum {
4070 TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */ 4080 TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */
4071 TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */ 4081 TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */
4072 TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume: 4082 TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume:
4073 off / last state */ 4083 0 = disable, 1 = enable */
4074}; 4084};
4075 4085
4076#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" 4086#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
@@ -4107,10 +4117,11 @@ static int wan_set_status(enum tpacpi_rfkill_state state)
4107 } 4117 }
4108#endif 4118#endif
4109 4119
4110 /* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */
4111 status = TP_ACPI_WANCARD_RESUMECTRL;
4112 if (state == TPACPI_RFK_RADIO_ON) 4120 if (state == TPACPI_RFK_RADIO_ON)
4113 status |= TP_ACPI_WANCARD_RADIOSSW; 4121 status = TP_ACPI_WANCARD_RADIOSSW
4122 | TP_ACPI_WANCARD_RESUMECTRL;
4123 else
4124 status = 0;
4114 4125
4115 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 4126 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
4116 return -EIO; 4127 return -EIO;
@@ -4619,6 +4630,10 @@ static int video_read(struct seq_file *m)
4619 return 0; 4630 return 0;
4620 } 4631 }
4621 4632
4633 /* Even reads can crash X.org, so... */
4634 if (!capable(CAP_SYS_ADMIN))
4635 return -EPERM;
4636
4622 status = video_outputsw_get(); 4637 status = video_outputsw_get();
4623 if (status < 0) 4638 if (status < 0)
4624 return status; 4639 return status;
@@ -4652,6 +4667,10 @@ static int video_write(char *buf)
4652 if (video_supported == TPACPI_VIDEO_NONE) 4667 if (video_supported == TPACPI_VIDEO_NONE)
4653 return -ENODEV; 4668 return -ENODEV;
4654 4669
4670 /* Even reads can crash X.org, let alone writes... */
4671 if (!capable(CAP_SYS_ADMIN))
4672 return -EPERM;
4673
4655 enable = 0; 4674 enable = 0;
4656 disable = 0; 4675 disable = 0;
4657 4676
@@ -6133,13 +6152,13 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
6133 TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ 6152 TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */
6134 6153
6135 /* Models with ATI GPUs that can use ECNVRAM */ 6154 /* Models with ATI GPUs that can use ECNVRAM */
6136 TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC), 6155 TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC), /* R50,51 T40-42 */
6137 TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6156 TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6138 TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6157 TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_EC), /* R52 */
6139 TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6158 TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6140 6159
6141 /* Models with Intel Extreme Graphics 2 */ 6160 /* Models with Intel Extreme Graphics 2 */
6142 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), 6161 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), /* X40 */
6143 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6162 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6144 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6163 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6145 6164
@@ -6522,7 +6541,8 @@ static int volume_set_status(const u8 status)
6522 return volume_set_status_ec(status); 6541 return volume_set_status_ec(status);
6523} 6542}
6524 6543
6525static int volume_set_mute_ec(const bool mute) 6544/* returns < 0 on error, 0 on no change, 1 on change */
6545static int __volume_set_mute_ec(const bool mute)
6526{ 6546{
6527 int rc; 6547 int rc;
6528 u8 s, n; 6548 u8 s, n;
@@ -6537,22 +6557,37 @@ static int volume_set_mute_ec(const bool mute)
6537 n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK : 6557 n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
6538 s & ~TP_EC_AUDIO_MUTESW_MSK; 6558 s & ~TP_EC_AUDIO_MUTESW_MSK;
6539 6559
6540 if (n != s) 6560 if (n != s) {
6541 rc = volume_set_status_ec(n); 6561 rc = volume_set_status_ec(n);
6562 if (!rc)
6563 rc = 1;
6564 }
6542 6565
6543unlock: 6566unlock:
6544 mutex_unlock(&volume_mutex); 6567 mutex_unlock(&volume_mutex);
6545 return rc; 6568 return rc;
6546} 6569}
6547 6570
6571static int volume_alsa_set_mute(const bool mute)
6572{
6573 dbg_printk(TPACPI_DBG_MIXER, "ALSA: trying to %smute\n",
6574 (mute) ? "" : "un");
6575 return __volume_set_mute_ec(mute);
6576}
6577
6548static int volume_set_mute(const bool mute) 6578static int volume_set_mute(const bool mute)
6549{ 6579{
6580 int rc;
6581
6550 dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n", 6582 dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
6551 (mute) ? "" : "un"); 6583 (mute) ? "" : "un");
6552 return volume_set_mute_ec(mute); 6584
6585 rc = __volume_set_mute_ec(mute);
6586 return (rc < 0) ? rc : 0;
6553} 6587}
6554 6588
6555static int volume_set_volume_ec(const u8 vol) 6589/* returns < 0 on error, 0 on no change, 1 on change */
6590static int __volume_set_volume_ec(const u8 vol)
6556{ 6591{
6557 int rc; 6592 int rc;
6558 u8 s, n; 6593 u8 s, n;
@@ -6569,19 +6604,22 @@ static int volume_set_volume_ec(const u8 vol)
6569 6604
6570 n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol; 6605 n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
6571 6606
6572 if (n != s) 6607 if (n != s) {
6573 rc = volume_set_status_ec(n); 6608 rc = volume_set_status_ec(n);
6609 if (!rc)
6610 rc = 1;
6611 }
6574 6612
6575unlock: 6613unlock:
6576 mutex_unlock(&volume_mutex); 6614 mutex_unlock(&volume_mutex);
6577 return rc; 6615 return rc;
6578} 6616}
6579 6617
6580static int volume_set_volume(const u8 vol) 6618static int volume_alsa_set_volume(const u8 vol)
6581{ 6619{
6582 dbg_printk(TPACPI_DBG_MIXER, 6620 dbg_printk(TPACPI_DBG_MIXER,
6583 "trying to set volume level to %hu\n", vol); 6621 "ALSA: trying to set volume level to %hu\n", vol);
6584 return volume_set_volume_ec(vol); 6622 return __volume_set_volume_ec(vol);
6585} 6623}
6586 6624
6587static void volume_alsa_notify_change(void) 6625static void volume_alsa_notify_change(void)
@@ -6628,7 +6666,7 @@ static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
6628static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol, 6666static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
6629 struct snd_ctl_elem_value *ucontrol) 6667 struct snd_ctl_elem_value *ucontrol)
6630{ 6668{
6631 return volume_set_volume(ucontrol->value.integer.value[0]); 6669 return volume_alsa_set_volume(ucontrol->value.integer.value[0]);
6632} 6670}
6633 6671
6634#define volume_alsa_mute_info snd_ctl_boolean_mono_info 6672#define volume_alsa_mute_info snd_ctl_boolean_mono_info
@@ -6651,7 +6689,7 @@ static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
6651static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol, 6689static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
6652 struct snd_ctl_elem_value *ucontrol) 6690 struct snd_ctl_elem_value *ucontrol)
6653{ 6691{
6654 return volume_set_mute(!ucontrol->value.integer.value[0]); 6692 return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
6655} 6693}
6656 6694
6657static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = { 6695static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
@@ -8477,9 +8515,10 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
8477 "%s installed\n", ibm->name); 8515 "%s installed\n", ibm->name);
8478 8516
8479 if (ibm->read) { 8517 if (ibm->read) {
8480 mode_t mode; 8518 mode_t mode = iibm->base_procfs_mode;
8481 8519
8482 mode = S_IRUGO; 8520 if (!mode)
8521 mode = S_IRUGO;
8483 if (ibm->write) 8522 if (ibm->write)
8484 mode |= S_IWUSR; 8523 mode |= S_IWUSR;
8485 entry = proc_create_data(ibm->name, mode, proc_dir, 8524 entry = proc_create_data(ibm->name, mode, proc_dir,
@@ -8670,6 +8709,7 @@ static struct ibm_init_struct ibms_init[] __initdata = {
8670#ifdef CONFIG_THINKPAD_ACPI_VIDEO 8709#ifdef CONFIG_THINKPAD_ACPI_VIDEO
8671 { 8710 {
8672 .init = video_init, 8711 .init = video_init,
8712 .base_procfs_mode = S_IRUSR,
8673 .data = &video_driver_data, 8713 .data = &video_driver_data,
8674 }, 8714 },
8675#endif 8715#endif
@@ -9032,6 +9072,9 @@ static int __init thinkpad_acpi_module_init(void)
9032 return ret; 9072 return ret;
9033 } 9073 }
9034 } 9074 }
9075
9076 tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
9077
9035 ret = input_register_device(tpacpi_inputdev); 9078 ret = input_register_device(tpacpi_inputdev);
9036 if (ret < 0) { 9079 if (ret < 0) {
9037 printk(TPACPI_ERR "unable to register input device\n"); 9080 printk(TPACPI_ERR "unable to register input device\n");
@@ -9041,7 +9084,6 @@ static int __init thinkpad_acpi_module_init(void)
9041 tp_features.input_device_registered = 1; 9084 tp_features.input_device_registered = 1;
9042 } 9085 }
9043 9086
9044 tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
9045 return 0; 9087 return 0;
9046} 9088}
9047 9089