aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2010-02-27 16:45:29 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-15 12:06:21 -0400
commitd707522d421d10bb56c5054812eb1f53a39a5c08 (patch)
treeba7197c1602bffd9136fc93d3a3e2c60d7fc72e3
parentf4d574122bc35f8c90effac2e3a2af2889e9ba81 (diff)
thinkpad-acpi: fix ALSA callback return status
commit 88cc83772a3c7756b9f2b4ba835545ad90a08409 upstream. Clemens Ladisch reports that thinkpad-acpi improperly implements the ALSA API, and always returns 0 for success for the "put" callbacks while the API requires it to return "1" when the control value has been changed in the hardware/firmware. Rework the volume subdriver to be able to properly implement the ALSA API. Based on a patch by Clemens Ladisch <clemens@ladisch.de>. This fix is also needed on 2.6.33. Reported-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index eb603f1d55ca..159a1f877d91 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -6522,7 +6522,8 @@ static int volume_set_status(const u8 status)
6522 return volume_set_status_ec(status); 6522 return volume_set_status_ec(status);
6523} 6523}
6524 6524
6525static int volume_set_mute_ec(const bool mute) 6525/* returns < 0 on error, 0 on no change, 1 on change */
6526static int __volume_set_mute_ec(const bool mute)
6526{ 6527{
6527 int rc; 6528 int rc;
6528 u8 s, n; 6529 u8 s, n;
@@ -6537,22 +6538,37 @@ static int volume_set_mute_ec(const bool mute)
6537 n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK : 6538 n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
6538 s & ~TP_EC_AUDIO_MUTESW_MSK; 6539 s & ~TP_EC_AUDIO_MUTESW_MSK;
6539 6540
6540 if (n != s) 6541 if (n != s) {
6541 rc = volume_set_status_ec(n); 6542 rc = volume_set_status_ec(n);
6543 if (!rc)
6544 rc = 1;
6545 }
6542 6546
6543unlock: 6547unlock:
6544 mutex_unlock(&volume_mutex); 6548 mutex_unlock(&volume_mutex);
6545 return rc; 6549 return rc;
6546} 6550}
6547 6551
6552static int volume_alsa_set_mute(const bool mute)
6553{
6554 dbg_printk(TPACPI_DBG_MIXER, "ALSA: trying to %smute\n",
6555 (mute) ? "" : "un");
6556 return __volume_set_mute_ec(mute);
6557}
6558
6548static int volume_set_mute(const bool mute) 6559static int volume_set_mute(const bool mute)
6549{ 6560{
6561 int rc;
6562
6550 dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n", 6563 dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
6551 (mute) ? "" : "un"); 6564 (mute) ? "" : "un");
6552 return volume_set_mute_ec(mute); 6565
6566 rc = __volume_set_mute_ec(mute);
6567 return (rc < 0) ? rc : 0;
6553} 6568}
6554 6569
6555static int volume_set_volume_ec(const u8 vol) 6570/* returns < 0 on error, 0 on no change, 1 on change */
6571static int __volume_set_volume_ec(const u8 vol)
6556{ 6572{
6557 int rc; 6573 int rc;
6558 u8 s, n; 6574 u8 s, n;
@@ -6569,19 +6585,22 @@ static int volume_set_volume_ec(const u8 vol)
6569 6585
6570 n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol; 6586 n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
6571 6587
6572 if (n != s) 6588 if (n != s) {
6573 rc = volume_set_status_ec(n); 6589 rc = volume_set_status_ec(n);
6590 if (!rc)
6591 rc = 1;
6592 }
6574 6593
6575unlock: 6594unlock:
6576 mutex_unlock(&volume_mutex); 6595 mutex_unlock(&volume_mutex);
6577 return rc; 6596 return rc;
6578} 6597}
6579 6598
6580static int volume_set_volume(const u8 vol) 6599static int volume_alsa_set_volume(const u8 vol)
6581{ 6600{
6582 dbg_printk(TPACPI_DBG_MIXER, 6601 dbg_printk(TPACPI_DBG_MIXER,
6583 "trying to set volume level to %hu\n", vol); 6602 "ALSA: trying to set volume level to %hu\n", vol);
6584 return volume_set_volume_ec(vol); 6603 return __volume_set_volume_ec(vol);
6585} 6604}
6586 6605
6587static void volume_alsa_notify_change(void) 6606static void volume_alsa_notify_change(void)
@@ -6628,7 +6647,7 @@ static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
6628static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol, 6647static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
6629 struct snd_ctl_elem_value *ucontrol) 6648 struct snd_ctl_elem_value *ucontrol)
6630{ 6649{
6631 return volume_set_volume(ucontrol->value.integer.value[0]); 6650 return volume_alsa_set_volume(ucontrol->value.integer.value[0]);
6632} 6651}
6633 6652
6634#define volume_alsa_mute_info snd_ctl_boolean_mono_info 6653#define volume_alsa_mute_info snd_ctl_boolean_mono_info
@@ -6651,7 +6670,7 @@ static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
6651static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol, 6670static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
6652 struct snd_ctl_elem_value *ucontrol) 6671 struct snd_ctl_elem_value *ucontrol)
6653{ 6672{
6654 return volume_set_mute(!ucontrol->value.integer.value[0]); 6673 return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
6655} 6674}
6656 6675
6657static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = { 6676static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {