* [PATCH] thinkpad_acpi: added BIOS mute interfaces for volume @ 2012-04-11 10:15 Alex Hung 2012-04-11 10:17 ` Alex Hung 0 siblings, 1 reply; 5+ messages in thread From: Alex Hung @ 2012-04-11 10:15 UTC (permalink / raw) To: ibm-acpi, mjg, ibm-acpi-devel, platform-driver-x86, linux-kernel, alex.hung Signed-off-by: Alex Hung <alex.hung@canonical.com> --- drivers/platform/x86/thinkpad_acpi.c | 115 +++++++++++++++++++++++++++++++--- 1 files changed, 106 insertions(+), 9 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 7b82868..dc22a4c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6486,12 +6486,86 @@ enum tpacpi_volume_capabilities { TPACPI_VOL_CAP_MAX }; +enum { + TPACPI_AML_MUTE_GET_FUNC = 0x01, + TPACPI_AML_MUTE_SET_FUNC = 0x02, + TPACPI_AML_MUTE_SUPPORT_FUNC = 0x04, + TPACPI_AML_MUTE_READ_MASK = 0x01, + TPACPI_AML_MUTE_ERROR_STATE_MASK = 0x80000000, +}; + static enum tpacpi_volume_access_mode volume_mode = TPACPI_VOL_MODE_MAX; static enum tpacpi_volume_capabilities volume_capabilities; static int volume_control_allowed; + +static bool volume_bios_support(int func) +{ + acpi_handle temp; + + if ((func | TPACPI_AML_MUTE_GET_FUNC) && + !ACPI_SUCCESS(acpi_get_handle(hkey_handle, "GSMS", &temp))) + return false; + + if ((func | TPACPI_AML_MUTE_SET_FUNC) && + !ACPI_SUCCESS(acpi_get_handle(hkey_handle, "SSMS", &temp))) + return false; + + if ((func | TPACPI_AML_MUTE_SUPPORT_FUNC) && + !ACPI_SUCCESS(acpi_get_handle(hkey_handle, "SHDA", &temp))) + return false; + + return true; +} + +static int hotkey_get_mute_state(int *state) +{ + if (!acpi_evalf(hkey_handle, state, "GSMS", "dd")) + return -EIO; + + if (*state & TPACPI_AML_MUTE_ERROR_STATE_MASK) + pr_warning("getting mute state failed.\n"); + + *state &= TPACPI_AML_MUTE_READ_MASK; + pr_info("get mute state = %s.\n", *state ? "muted" : "unmuted"); + + return 0; +} + +static int hotkey_set_mute_state(int state) +{ + int output; + + if (!acpi_evalf(hkey_handle, &output, "SSMS", "dd", state)) + return -EIO; + + if (output & TPACPI_AML_MUTE_ERROR_STATE_MASK) { + pr_warning("setting mute state failed.\n"); + return -EIO; + } + pr_info("set to mute led state to %s.\n", state ? "on" : "off"); + + return 0; +} + +static int hotkey_set_mute_support(int support) +{ + int output; + + if (!acpi_evalf(hkey_handle, &output, "SHDA", "dd", support)) + return -EIO; + + if (output & TPACPI_AML_MUTE_ERROR_STATE_MASK) { + pr_warning("setting mute support failed.\n"); + return -EIO; + } + pr_info("%s mute led support.\n", support ? "disable" : "enable"); + + return 0; +} + /* * Used to syncronize writers to TP_EC_AUDIO and * TP_NVRAM_ADDR_MIXER, as we need to do read-modify-write @@ -6982,6 +7056,7 @@ static int __init volume_init(struct ibm_init_struct *iibm) static int volume_read(struct seq_file *m) { u8 status; + int mute; if (volume_get_status(&status) < 0) { seq_printf(m, "level:\t\tunreadable\n"); @@ -6991,8 +7066,12 @@ static int volume_read(struct seq_file *m) else seq_printf(m, "level:\t\t%d\n", status & TP_EC_AUDIO_LVL_MSK); - - seq_printf(m, "mute:\t\t%s\n", + if (volume_bios_support(TPACPI_AML_MUTE_GET_FUNC) && + !hotkey_get_mute_state(&mute)) + seq_printf(m, "mute:\t\t%s\n", + mute ? "muted" : "unmuted"); + else + seq_printf(m, "mute:\t\t%s\n", onoff(status, TP_EC_AUDIO_MUTESW)); if (volume_control_allowed) { @@ -7005,7 +7084,8 @@ static int volume_read(struct seq_file *m) " (<level> is 0-%d)\n", TP_EC_VOLUME_MAX); } - } + } else if (volume_bios_support(TPACPI_AML_MUTE_SET_FUNC)) + seq_printf(m, "commands:\tunmute, mute\n"); } return 0; @@ -7019,6 +7099,21 @@ static int volume_write(char *buf) char *cmd; int rc; + if (volume_bios_support( + TPACPI_AML_MUTE_SET_FUNC | TPACPI_AML_MUTE_SUPPORT_FUNC)) { + while ((cmd = next_cmd(&buf))) { + if (strlencmp(cmd, "mute") == 0) + hotkey_set_mute_state(1); + else if (strlencmp(cmd, "unmute") == 0) + hotkey_set_mute_state(0); + else if (strlencmp(cmd, "disable") == 0) + hotkey_set_mute_support(1); + else if (strlencmp(cmd, "enable") == 0) + hotkey_set_mute_support(0); + } + return -EINVAL; + } + /* * We do allow volume control at driver startup, so that the * user can set initial state through the volume=... parameter hack. @@ -7061,12 +7156,14 @@ static int volume_write(char *buf) continue; } } - if (strlencmp(cmd, "mute") == 0) - new_mute = TP_EC_AUDIO_MUTESW_MSK; - else if (strlencmp(cmd, "unmute") == 0) - new_mute = 0; - else - return -EINVAL; + if (!volume_bios_support(TPACPI_AML_MUTE_SET_FUNC)) { + if (strlencmp(cmd, "mute") == 0) + new_mute = TP_EC_AUDIO_MUTESW_MSK; + else if (strlencmp(cmd, "unmute") == 0) + new_mute = 0; + else + return -EINVAL; + } } if (tp_features.mixer_no_level_control) { -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] thinkpad_acpi: added BIOS mute interfaces for volume 2012-04-11 10:15 [PATCH] thinkpad_acpi: added BIOS mute interfaces for volume Alex Hung @ 2012-04-11 10:17 ` Alex Hung 2012-04-11 11:42 ` Henrique de Moraes Holschuh 0 siblings, 1 reply; 5+ messages in thread From: Alex Hung @ 2012-04-11 10:17 UTC (permalink / raw) To: Alex Hung Cc: ibm-acpi, mjg, ibm-acpi-devel, platform-driver-x86, linux-kernel Hi, I am modifying thinkpad_acpi so it can support the mute led, and I am looking for suggestions and feedbacks. For newer BIOS, it includes three aml methods that can be used to get, set and enable the mute led. In *volume_read* function, I modify it to call BIOS GSMS method when it is presented in AML. This is more straight-forward. However, I had debated with myself whether it should be included inside the if-else statement. The reason is that the new function is not necessarily dependent on volume_get_status, but including it in if-else statement works perfectly and it has minimal impacts on the original behaviors and therefore I decide to put my patch there. I implemented as it is now to demonstrate what I am intending to do; however, deciding where to add changes to *volume_write* is much more difficult to decide for the following reasons: 1. The new mute functions (calling to AML's SSMS and SHDA) are dependents on BIOS and they can be called when SSMS and SHDA are supported. 2. If the new functions are included in the original cmd handler (the while-loop), they will be blocked by the first if-statement *if (!volume_control_allowed && tpacpi_lifecycle != TPACPI_LIFE_INIT)*. 3. However, the changes now will changes the original behaviors (i.e. "up", "down" and so on) if BIOS supports new SSMS and SHDA methods. Any feedbacks and suggestions are most appreciated. Best Regards, Alex Hung On 04/11/2012 06:15 PM, Alex Hung wrote: > Signed-off-by: Alex Hung<alex.hung@canonical.com> > --- > drivers/platform/x86/thinkpad_acpi.c | 115 +++++++++++++++++++++++++++++++--- > 1 files changed, 106 insertions(+), 9 deletions(-) > > diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c > index 7b82868..dc22a4c 100644 > --- a/drivers/platform/x86/thinkpad_acpi.c > +++ b/drivers/platform/x86/thinkpad_acpi.c > @@ -6486,12 +6486,86 @@ enum tpacpi_volume_capabilities { > TPACPI_VOL_CAP_MAX > }; > > +enum { > + TPACPI_AML_MUTE_GET_FUNC = 0x01, > + TPACPI_AML_MUTE_SET_FUNC = 0x02, > + TPACPI_AML_MUTE_SUPPORT_FUNC = 0x04, > + TPACPI_AML_MUTE_READ_MASK = 0x01, > + TPACPI_AML_MUTE_ERROR_STATE_MASK = 0x80000000, > +}; > + > static enum tpacpi_volume_access_mode volume_mode = > TPACPI_VOL_MODE_MAX; > > static enum tpacpi_volume_capabilities volume_capabilities; > static int volume_control_allowed; > > + > +static bool volume_bios_support(int func) > +{ > + acpi_handle temp; > + > + if ((func | TPACPI_AML_MUTE_GET_FUNC)&& > + !ACPI_SUCCESS(acpi_get_handle(hkey_handle, "GSMS",&temp))) > + return false; > + > + if ((func | TPACPI_AML_MUTE_SET_FUNC)&& > + !ACPI_SUCCESS(acpi_get_handle(hkey_handle, "SSMS",&temp))) > + return false; > + > + if ((func | TPACPI_AML_MUTE_SUPPORT_FUNC)&& > + !ACPI_SUCCESS(acpi_get_handle(hkey_handle, "SHDA",&temp))) > + return false; > + > + return true; > +} > + > +static int hotkey_get_mute_state(int *state) > +{ > + if (!acpi_evalf(hkey_handle, state, "GSMS", "dd")) > + return -EIO; > + > + if (*state& TPACPI_AML_MUTE_ERROR_STATE_MASK) > + pr_warning("getting mute state failed.\n"); > + > + *state&= TPACPI_AML_MUTE_READ_MASK; > + pr_info("get mute state = %s.\n", *state ? "muted" : "unmuted"); > + > + return 0; > +} > + > +static int hotkey_set_mute_state(int state) > +{ > + int output; > + > + if (!acpi_evalf(hkey_handle,&output, "SSMS", "dd", state)) > + return -EIO; > + > + if (output& TPACPI_AML_MUTE_ERROR_STATE_MASK) { > + pr_warning("setting mute state failed.\n"); > + return -EIO; > + } > + pr_info("set to mute led state to %s.\n", state ? "on" : "off"); > + > + return 0; > +} > + > +static int hotkey_set_mute_support(int support) > +{ > + int output; > + > + if (!acpi_evalf(hkey_handle,&output, "SHDA", "dd", support)) > + return -EIO; > + > + if (output& TPACPI_AML_MUTE_ERROR_STATE_MASK) { > + pr_warning("setting mute support failed.\n"); > + return -EIO; > + } > + pr_info("%s mute led support.\n", support ? "disable" : "enable"); > + > + return 0; > +} > + > /* > * Used to syncronize writers to TP_EC_AUDIO and > * TP_NVRAM_ADDR_MIXER, as we need to do read-modify-write > @@ -6982,6 +7056,7 @@ static int __init volume_init(struct ibm_init_struct *iibm) > static int volume_read(struct seq_file *m) > { > u8 status; > + int mute; > > if (volume_get_status(&status)< 0) { > seq_printf(m, "level:\t\tunreadable\n"); > @@ -6991,8 +7066,12 @@ static int volume_read(struct seq_file *m) > else > seq_printf(m, "level:\t\t%d\n", > status& TP_EC_AUDIO_LVL_MSK); > - > - seq_printf(m, "mute:\t\t%s\n", > + if (volume_bios_support(TPACPI_AML_MUTE_GET_FUNC)&& > + !hotkey_get_mute_state(&mute)) > + seq_printf(m, "mute:\t\t%s\n", > + mute ? "muted" : "unmuted"); > + else > + seq_printf(m, "mute:\t\t%s\n", > onoff(status, TP_EC_AUDIO_MUTESW)); > > if (volume_control_allowed) { > @@ -7005,7 +7084,8 @@ static int volume_read(struct seq_file *m) > " (<level> is 0-%d)\n", > TP_EC_VOLUME_MAX); > } > - } > + } else if (volume_bios_support(TPACPI_AML_MUTE_SET_FUNC)) > + seq_printf(m, "commands:\tunmute, mute\n"); > } > > return 0; > @@ -7019,6 +7099,21 @@ static int volume_write(char *buf) > char *cmd; > int rc; > > + if (volume_bios_support( > + TPACPI_AML_MUTE_SET_FUNC | TPACPI_AML_MUTE_SUPPORT_FUNC)) { > + while ((cmd = next_cmd(&buf))) { > + if (strlencmp(cmd, "mute") == 0) > + hotkey_set_mute_state(1); > + else if (strlencmp(cmd, "unmute") == 0) > + hotkey_set_mute_state(0); > + else if (strlencmp(cmd, "disable") == 0) > + hotkey_set_mute_support(1); > + else if (strlencmp(cmd, "enable") == 0) > + hotkey_set_mute_support(0); > + } > + return -EINVAL; > + } > + > /* > * We do allow volume control at driver startup, so that the > * user can set initial state through the volume=... parameter hack. > @@ -7061,12 +7156,14 @@ static int volume_write(char *buf) > continue; > } > } > - if (strlencmp(cmd, "mute") == 0) > - new_mute = TP_EC_AUDIO_MUTESW_MSK; > - else if (strlencmp(cmd, "unmute") == 0) > - new_mute = 0; > - else > - return -EINVAL; > + if (!volume_bios_support(TPACPI_AML_MUTE_SET_FUNC)) { > + if (strlencmp(cmd, "mute") == 0) > + new_mute = TP_EC_AUDIO_MUTESW_MSK; > + else if (strlencmp(cmd, "unmute") == 0) > + new_mute = 0; > + else > + return -EINVAL; > + } > } > > if (tp_features.mixer_no_level_control) { ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] thinkpad_acpi: added BIOS mute interfaces for volume 2012-04-11 10:17 ` Alex Hung @ 2012-04-11 11:42 ` Henrique de Moraes Holschuh [not found] ` <20120411114211.GA11445-ZGHd14iZgfaRjzvQDGKj+xxZW9W5cXbT@public.gmane.org> 0 siblings, 1 reply; 5+ messages in thread From: Henrique de Moraes Holschuh @ 2012-04-11 11:42 UTC (permalink / raw) To: Alex Hung Cc: ibm-acpi, mjg, ibm-acpi-devel, platform-driver-x86, linux-kernel On Wed, 11 Apr 2012, Alex Hung wrote: > I am modifying thinkpad_acpi so it can support the mute led, and I > am looking for suggestions and feedbacks. > > For newer BIOS, it includes three aml methods that can be used to > get, set and enable the mute led. Aha! THANK YOU. I will look at the patches this week. Please send me (directly) a full dmidecode and ACPI table dump. -- "One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh ^ permalink raw reply [flat|nested] 5+ messages in thread
[parent not found: <20120411114211.GA11445-ZGHd14iZgfaRjzvQDGKj+xxZW9W5cXbT@public.gmane.org>]
* Re: [PATCH] thinkpad_acpi: added BIOS mute interfaces for volume [not found] ` <20120411114211.GA11445-ZGHd14iZgfaRjzvQDGKj+xxZW9W5cXbT@public.gmane.org> @ 2012-07-08 15:29 ` Alex Hung [not found] ` <4FF9A76C.7030308-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org> 0 siblings, 1 reply; 5+ messages in thread From: Alex Hung @ 2012-07-08 15:29 UTC (permalink / raw) To: Henrique de Moraes Holschuh Cc: ibm-acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, platform-driver-x86-u79uwXL29TY76Z2rM5mHXA, ibm-acpi-N3TV7GIv+o9fyO9Q7EP/yw, mjg-H+wXaHxf7aLQT0dZR+AlfA Hi, I saw a number of discussion on new thinkpad led and caused me to re-think about my previous patch. The previous patches add interfaces to control hardware mute via BIOS functions; however there are nobody to control it and the problem of out-of-sync between hardware mute and software mute will still exist. Will it be a better idea to disable hardware mute? The hardware mute will still send a scancode to mute the volue when thinkpad-acpi is loaded, though the led will still not work. More specifically, a patch that only calls with hoteky_set_mute_support(1) that works as below: +static int hotkey_set_mute_support(int support) +{ + int output; + + if (!acpi_evalf(hkey_handle, &output, "SHDA", "dd", support)) + return -EIO; + + if (output & TPACPI_AML_MUTE_ERROR_STATE_MASK) { + pr_warning("setting mute support failed.\n"); + return -EIO; + } + pr_info("%s mute led support.\n", support ? "disable" : "enable"); + + return 0; +} This can solve the problems that unmute from desktop will not unmute the hardware mute until someone including myself works out a more comprehensive solution. Best Regards, Alex Hung On 04/11/2012 07:42 PM, Henrique de Moraes Holschuh wrote: > On Wed, 11 Apr 2012, Alex Hung wrote: >> I am modifying thinkpad_acpi so it can support the mute led, and I >> am looking for suggestions and feedbacks. >> >> For newer BIOS, it includes three aml methods that can be used to >> get, set and enable the mute led. > > Aha! THANK YOU. > > I will look at the patches this week. Please send me (directly) a full > dmidecode and ACPI table dump. > ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ^ permalink raw reply [flat|nested] 5+ messages in thread
[parent not found: <4FF9A76C.7030308-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>]
* Re: [PATCH] thinkpad_acpi: added BIOS mute interfaces for volume [not found] ` <4FF9A76C.7030308-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org> @ 2012-07-08 15:43 ` Henrique de Moraes Holschuh 0 siblings, 0 replies; 5+ messages in thread From: Henrique de Moraes Holschuh @ 2012-07-08 15:43 UTC (permalink / raw) To: Alex Hung Cc: ibm-acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, platform-driver-x86-u79uwXL29TY76Z2rM5mHXA, ibm-acpi-N3TV7GIv+o9fyO9Q7EP/yw, mjg-H+wXaHxf7aLQT0dZR+AlfA On Sun, 08 Jul 2012, Alex Hung wrote: > Will it be a better idea to disable hardware mute? The hardware mute > will still send a scancode to mute the volue when thinkpad-acpi is > loaded, though the led will still not work. More specifically, a > patch that only calls with hoteky_set_mute_support(1) that works as > below: I don't mind adding that as a module paramenter and a sysfs control, but make it a multi-value integer as follows: -1: auto (right now that means don't touch it. We can change its meaning after some testing) 0 : disable hw mute 1 : enable hw mute All other values must return -EINVAL (reserved, to be implemented later). On thinkpads where no SHDA functionality is supported, do not publish the sysfs node. I can test in the T43 if it is EC-supported but not published in the DSDT, please send me the relevant acpidump of a thinkpad that implements SHDA, please. Relevant documentation patch for Documentation/laptops/thinkpad-acpi.txt is required for an Ack, of course :-) > This can solve the problems that unmute from desktop will not unmute > the hardware mute until someone including myself works out a more > comprehensive solution. Agreed. -- "One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-07-08 15:43 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-11 10:15 [PATCH] thinkpad_acpi: added BIOS mute interfaces for volume Alex Hung
2012-04-11 10:17 ` Alex Hung
2012-04-11 11:42 ` Henrique de Moraes Holschuh
[not found] ` <20120411114211.GA11445-ZGHd14iZgfaRjzvQDGKj+xxZW9W5cXbT@public.gmane.org>
2012-07-08 15:29 ` Alex Hung
[not found] ` <4FF9A76C.7030308-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
2012-07-08 15:43 ` Henrique de Moraes Holschuh
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.