mirror of
https://github.com/torvalds/linux.git
synced 2024-12-02 17:11:33 +00:00
Merge branch 'for-upstream/platform-x86_tpacpi' of git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6 into x86-platform
This commit is contained in:
commit
a58db59a26
@ -650,6 +650,10 @@ LCD, CRT or DVI (if available). The following commands are available:
|
||||
echo expand_toggle > /proc/acpi/ibm/video
|
||||
echo video_switch > /proc/acpi/ibm/video
|
||||
|
||||
NOTE: Access to this feature is restricted to processes owning the
|
||||
CAP_SYS_ADMIN capability for safety reasons, as it can interact badly
|
||||
enough with some versions of X.org to crash it.
|
||||
|
||||
Each video output device can be enabled or disabled individually.
|
||||
Reading /proc/acpi/ibm/video shows the status of each device.
|
||||
|
||||
|
@ -322,9 +322,15 @@ config THINKPAD_ACPI_VIDEO
|
||||
server running, phase of the moon, and the current mood of
|
||||
Schroedinger's cat. If you can use X.org's RandR to control
|
||||
your ThinkPad's video output ports instead of this feature,
|
||||
don't think twice: do it and say N here to save some memory.
|
||||
don't think twice: do it and say N here to save memory and avoid
|
||||
bad interactions with X.org.
|
||||
|
||||
If you are not sure, say Y here.
|
||||
NOTE: access to this feature is limited to processes with the
|
||||
CAP_SYS_ADMIN capability, to avoid local DoS issues in platforms
|
||||
where it interacts badly with X.org.
|
||||
|
||||
If you are not sure, say Y here but do try to check if you could
|
||||
be using X.org RandR instead.
|
||||
|
||||
config THINKPAD_ACPI_HOTKEY_POLL
|
||||
bool "Support NVRAM polling for hot keys"
|
||||
|
@ -286,6 +286,7 @@ struct ibm_init_struct {
|
||||
char param[32];
|
||||
|
||||
int (*init) (struct ibm_init_struct *);
|
||||
mode_t base_procfs_mode;
|
||||
struct ibm_struct *data;
|
||||
};
|
||||
|
||||
@ -2082,6 +2083,7 @@ static struct attribute_set *hotkey_dev_attributes;
|
||||
|
||||
static void tpacpi_driver_event(const unsigned int hkey_event);
|
||||
static void hotkey_driver_event(const unsigned int scancode);
|
||||
static void hotkey_poll_setup(const bool may_warn);
|
||||
|
||||
/* HKEY.MHKG() return bits */
|
||||
#define TP_HOTKEY_TABLET_MASK (1 << 3)
|
||||
@ -2264,6 +2266,8 @@ static int tpacpi_hotkey_driver_mask_set(const u32 mask)
|
||||
|
||||
rc = hotkey_mask_set((hotkey_acpi_mask | hotkey_driver_mask) &
|
||||
~hotkey_source_mask);
|
||||
hotkey_poll_setup(true);
|
||||
|
||||
mutex_unlock(&hotkey_mutex);
|
||||
|
||||
return rc;
|
||||
@ -2548,7 +2552,7 @@ static void hotkey_poll_stop_sync(void)
|
||||
}
|
||||
|
||||
/* call with hotkey_mutex held */
|
||||
static void hotkey_poll_setup(bool may_warn)
|
||||
static void hotkey_poll_setup(const bool may_warn)
|
||||
{
|
||||
const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask;
|
||||
const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask;
|
||||
@ -2579,7 +2583,7 @@ static void hotkey_poll_setup(bool may_warn)
|
||||
}
|
||||
}
|
||||
|
||||
static void hotkey_poll_setup_safe(bool may_warn)
|
||||
static void hotkey_poll_setup_safe(const bool may_warn)
|
||||
{
|
||||
mutex_lock(&hotkey_mutex);
|
||||
hotkey_poll_setup(may_warn);
|
||||
@ -2597,7 +2601,11 @@ static void hotkey_poll_set_freq(unsigned int freq)
|
||||
|
||||
#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
|
||||
|
||||
static void hotkey_poll_setup_safe(bool __unused)
|
||||
static void hotkey_poll_setup(const bool __unused)
|
||||
{
|
||||
}
|
||||
|
||||
static void hotkey_poll_setup_safe(const bool __unused)
|
||||
{
|
||||
}
|
||||
|
||||
@ -2607,16 +2615,11 @@ static int hotkey_inputdev_open(struct input_dev *dev)
|
||||
{
|
||||
switch (tpacpi_lifecycle) {
|
||||
case TPACPI_LIFE_INIT:
|
||||
/*
|
||||
* hotkey_init will call hotkey_poll_setup_safe
|
||||
* at the appropriate moment
|
||||
*/
|
||||
return 0;
|
||||
case TPACPI_LIFE_EXITING:
|
||||
return -EBUSY;
|
||||
case TPACPI_LIFE_RUNNING:
|
||||
hotkey_poll_setup_safe(false);
|
||||
return 0;
|
||||
case TPACPI_LIFE_EXITING:
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Should only happen if tpacpi_lifecycle is corrupt */
|
||||
@ -2627,7 +2630,7 @@ static int hotkey_inputdev_open(struct input_dev *dev)
|
||||
static void hotkey_inputdev_close(struct input_dev *dev)
|
||||
{
|
||||
/* disable hotkey polling when possible */
|
||||
if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING &&
|
||||
if (tpacpi_lifecycle != TPACPI_LIFE_EXITING &&
|
||||
!(hotkey_source_mask & hotkey_driver_mask))
|
||||
hotkey_poll_setup_safe(false);
|
||||
}
|
||||
@ -3655,13 +3658,19 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
|
||||
break;
|
||||
case 3:
|
||||
/* 0x3000-0x3FFF: bay-related wakeups */
|
||||
if (hkey == TP_HKEY_EV_BAYEJ_ACK) {
|
||||
switch (hkey) {
|
||||
case TP_HKEY_EV_BAYEJ_ACK:
|
||||
hotkey_autosleep_ack = 1;
|
||||
printk(TPACPI_INFO
|
||||
"bay ejected\n");
|
||||
hotkey_wakeup_hotunplug_complete_notify_change();
|
||||
known_ev = true;
|
||||
} else {
|
||||
break;
|
||||
case TP_HKEY_EV_OPTDRV_EJ:
|
||||
/* FIXME: kick libata if SATA link offline */
|
||||
known_ev = true;
|
||||
break;
|
||||
default:
|
||||
known_ev = false;
|
||||
}
|
||||
break;
|
||||
@ -3870,7 +3879,7 @@ enum {
|
||||
TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */
|
||||
TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */
|
||||
TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume:
|
||||
off / last state */
|
||||
0 = disable, 1 = enable */
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -3916,10 +3925,11 @@ static int bluetooth_set_status(enum tpacpi_rfkill_state state)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
|
||||
status = TP_ACPI_BLUETOOTH_RESUMECTRL;
|
||||
if (state == TPACPI_RFK_RADIO_ON)
|
||||
status |= TP_ACPI_BLUETOOTH_RADIOSSW;
|
||||
status = TP_ACPI_BLUETOOTH_RADIOSSW
|
||||
| TP_ACPI_BLUETOOTH_RESUMECTRL;
|
||||
else
|
||||
status = 0;
|
||||
|
||||
if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
|
||||
return -EIO;
|
||||
@ -4070,7 +4080,7 @@ enum {
|
||||
TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */
|
||||
TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */
|
||||
TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume:
|
||||
off / last state */
|
||||
0 = disable, 1 = enable */
|
||||
};
|
||||
|
||||
#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
|
||||
@ -4107,10 +4117,11 @@ static int wan_set_status(enum tpacpi_rfkill_state state)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */
|
||||
status = TP_ACPI_WANCARD_RESUMECTRL;
|
||||
if (state == TPACPI_RFK_RADIO_ON)
|
||||
status |= TP_ACPI_WANCARD_RADIOSSW;
|
||||
status = TP_ACPI_WANCARD_RADIOSSW
|
||||
| TP_ACPI_WANCARD_RESUMECTRL;
|
||||
else
|
||||
status = 0;
|
||||
|
||||
if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
|
||||
return -EIO;
|
||||
@ -4619,6 +4630,10 @@ static int video_read(struct seq_file *m)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Even reads can crash X.org, so... */
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
status = video_outputsw_get();
|
||||
if (status < 0)
|
||||
return status;
|
||||
@ -4652,6 +4667,10 @@ static int video_write(char *buf)
|
||||
if (video_supported == TPACPI_VIDEO_NONE)
|
||||
return -ENODEV;
|
||||
|
||||
/* Even reads can crash X.org, let alone writes... */
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
enable = 0;
|
||||
disable = 0;
|
||||
|
||||
@ -6133,13 +6152,13 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
|
||||
TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */
|
||||
|
||||
/* Models with ATI GPUs that can use ECNVRAM */
|
||||
TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),
|
||||
TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC), /* R50,51 T40-42 */
|
||||
TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
|
||||
TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
|
||||
TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_EC), /* R52 */
|
||||
TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
|
||||
|
||||
/* Models with Intel Extreme Graphics 2 */
|
||||
TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
|
||||
TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), /* X40 */
|
||||
TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
|
||||
TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
|
||||
|
||||
@ -6522,7 +6541,8 @@ static int volume_set_status(const u8 status)
|
||||
return volume_set_status_ec(status);
|
||||
}
|
||||
|
||||
static int volume_set_mute_ec(const bool mute)
|
||||
/* returns < 0 on error, 0 on no change, 1 on change */
|
||||
static int __volume_set_mute_ec(const bool mute)
|
||||
{
|
||||
int rc;
|
||||
u8 s, n;
|
||||
@ -6537,22 +6557,37 @@ static int volume_set_mute_ec(const bool mute)
|
||||
n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
|
||||
s & ~TP_EC_AUDIO_MUTESW_MSK;
|
||||
|
||||
if (n != s)
|
||||
if (n != s) {
|
||||
rc = volume_set_status_ec(n);
|
||||
if (!rc)
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&volume_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int volume_set_mute(const bool mute)
|
||||
static int volume_alsa_set_mute(const bool mute)
|
||||
{
|
||||
dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
|
||||
dbg_printk(TPACPI_DBG_MIXER, "ALSA: trying to %smute\n",
|
||||
(mute) ? "" : "un");
|
||||
return volume_set_mute_ec(mute);
|
||||
return __volume_set_mute_ec(mute);
|
||||
}
|
||||
|
||||
static int volume_set_volume_ec(const u8 vol)
|
||||
static int volume_set_mute(const bool mute)
|
||||
{
|
||||
int rc;
|
||||
|
||||
dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
|
||||
(mute) ? "" : "un");
|
||||
|
||||
rc = __volume_set_mute_ec(mute);
|
||||
return (rc < 0) ? rc : 0;
|
||||
}
|
||||
|
||||
/* returns < 0 on error, 0 on no change, 1 on change */
|
||||
static int __volume_set_volume_ec(const u8 vol)
|
||||
{
|
||||
int rc;
|
||||
u8 s, n;
|
||||
@ -6569,19 +6604,22 @@ static int volume_set_volume_ec(const u8 vol)
|
||||
|
||||
n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
|
||||
|
||||
if (n != s)
|
||||
if (n != s) {
|
||||
rc = volume_set_status_ec(n);
|
||||
if (!rc)
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&volume_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int volume_set_volume(const u8 vol)
|
||||
static int volume_alsa_set_volume(const u8 vol)
|
||||
{
|
||||
dbg_printk(TPACPI_DBG_MIXER,
|
||||
"trying to set volume level to %hu\n", vol);
|
||||
return volume_set_volume_ec(vol);
|
||||
"ALSA: trying to set volume level to %hu\n", vol);
|
||||
return __volume_set_volume_ec(vol);
|
||||
}
|
||||
|
||||
static void volume_alsa_notify_change(void)
|
||||
@ -6628,7 +6666,7 @@ static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
|
||||
static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
return volume_set_volume(ucontrol->value.integer.value[0]);
|
||||
return volume_alsa_set_volume(ucontrol->value.integer.value[0]);
|
||||
}
|
||||
|
||||
#define volume_alsa_mute_info snd_ctl_boolean_mono_info
|
||||
@ -6651,7 +6689,7 @@ static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
|
||||
static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
return volume_set_mute(!ucontrol->value.integer.value[0]);
|
||||
return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
|
||||
@ -8477,9 +8515,10 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
|
||||
"%s installed\n", ibm->name);
|
||||
|
||||
if (ibm->read) {
|
||||
mode_t mode;
|
||||
mode_t mode = iibm->base_procfs_mode;
|
||||
|
||||
mode = S_IRUGO;
|
||||
if (!mode)
|
||||
mode = S_IRUGO;
|
||||
if (ibm->write)
|
||||
mode |= S_IWUSR;
|
||||
entry = proc_create_data(ibm->name, mode, proc_dir,
|
||||
@ -8670,6 +8709,7 @@ static struct ibm_init_struct ibms_init[] __initdata = {
|
||||
#ifdef CONFIG_THINKPAD_ACPI_VIDEO
|
||||
{
|
||||
.init = video_init,
|
||||
.base_procfs_mode = S_IRUSR,
|
||||
.data = &video_driver_data,
|
||||
},
|
||||
#endif
|
||||
@ -9032,6 +9072,9 @@ static int __init thinkpad_acpi_module_init(void)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
|
||||
|
||||
ret = input_register_device(tpacpi_inputdev);
|
||||
if (ret < 0) {
|
||||
printk(TPACPI_ERR "unable to register input device\n");
|
||||
@ -9041,7 +9084,6 @@ static int __init thinkpad_acpi_module_init(void)
|
||||
tp_features.input_device_registered = 1;
|
||||
}
|
||||
|
||||
tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user