aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarren Hart <dvhart@linux.intel.com>2014-12-10 23:49:57 -0500
committerDarren Hart <dvhart@linux.intel.com>2014-12-10 23:53:08 -0500
commitcc888de2c3939e6bdeca35b85d0d60302ee64c4f (patch)
tree2cd64845669f70d446b04616112811854a345145
parentf587f07fef33319a32dde533a23bb3974d30bf5a (diff)
parenta707c27cee56bfb234be6d3acbcc7928760f99be (diff)
Merge branch 'thinkpad-acpi' into for-next
thinkpad-acpi: acpi: Remove _OSI(Linux) for ThinkPads thinkpad-acpi: Try to use full software mute control Signed-off-by: Darren Hart <dvhart@linux.intel.com>
-rw-r--r--drivers/acpi/blacklist.c54
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c116
2 files changed, 106 insertions, 64 deletions
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 7556e7c4a055..9b693d54c743 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -305,60 +305,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
305 */ 305 */
306 306
307 /* 307 /*
308 * Lenovo has a mix of systems OSI(Linux) situations
309 * and thus we can not wildcard the vendor.
310 *
311 * _OSI(Linux) helps sound
312 * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
313 * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
314 * T400, T500
315 * _OSI(Linux) has Linux specific hooks
316 * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
317 * _OSI(Linux) is a NOP:
318 * DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
319 * DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"),
320 */
321 {
322 .callback = dmi_enable_osi_linux,
323 .ident = "Lenovo ThinkPad R61",
324 .matches = {
325 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
326 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
327 },
328 },
329 {
330 .callback = dmi_enable_osi_linux,
331 .ident = "Lenovo ThinkPad T61",
332 .matches = {
333 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
334 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
335 },
336 },
337 {
338 .callback = dmi_enable_osi_linux,
339 .ident = "Lenovo ThinkPad X61",
340 .matches = {
341 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
342 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
343 },
344 },
345 {
346 .callback = dmi_enable_osi_linux,
347 .ident = "Lenovo ThinkPad T400",
348 .matches = {
349 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
350 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T400"),
351 },
352 },
353 {
354 .callback = dmi_enable_osi_linux,
355 .ident = "Lenovo ThinkPad T500",
356 .matches = {
357 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
358 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T500"),
359 },
360 },
361 /*
362 * Without this this EEEpc exports a non working WMI interface, with 308 * Without this this EEEpc exports a non working WMI interface, with
363 * this it exports a working "good old" eeepc_laptop interface, fixing 309 * this it exports a working "good old" eeepc_laptop interface, fixing
364 * both brightness control, and rfkill not working. 310 * both brightness control, and rfkill not working.
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index cf0f89364d44..bdabd3fd844c 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -6559,6 +6559,17 @@ static struct ibm_struct brightness_driver_data = {
6559 * bits 3-0 (volume). Other bits in NVRAM may have other functions, 6559 * bits 3-0 (volume). Other bits in NVRAM may have other functions,
6560 * such as bit 7 which is used to detect repeated presses of MUTE, 6560 * such as bit 7 which is used to detect repeated presses of MUTE,
6561 * and we leave them unchanged. 6561 * and we leave them unchanged.
6562 *
6563 * On newer Lenovo ThinkPads, the EC can automatically change the volume
6564 * in response to user input. Unfortunately, this rarely works well.
6565 * The laptop changes the state of its internal MUTE gate and, on some
6566 * models, sends KEY_MUTE, causing any user code that responds to the
6567 * mute button to get confused. The hardware MUTE gate is also
6568 * unnecessary, since user code can handle the mute button without
6569 * kernel or EC help.
6570 *
6571 * To avoid confusing userspace, we simply disable all EC-based mute
6572 * and volume controls when possible.
6562 */ 6573 */
6563 6574
6564#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT 6575#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
@@ -6613,11 +6624,21 @@ enum tpacpi_volume_capabilities {
6613 TPACPI_VOL_CAP_MAX 6624 TPACPI_VOL_CAP_MAX
6614}; 6625};
6615 6626
6627enum tpacpi_mute_btn_mode {
6628 TP_EC_MUTE_BTN_LATCH = 0, /* Mute mutes; up/down unmutes */
6629 /* We don't know what mode 1 is. */
6630 TP_EC_MUTE_BTN_NONE = 2, /* Mute and up/down are just keys */
6631 TP_EC_MUTE_BTN_TOGGLE = 3, /* Mute toggles; up/down unmutes */
6632};
6633
6616static enum tpacpi_volume_access_mode volume_mode = 6634static enum tpacpi_volume_access_mode volume_mode =
6617 TPACPI_VOL_MODE_MAX; 6635 TPACPI_VOL_MODE_MAX;
6618 6636
6619static enum tpacpi_volume_capabilities volume_capabilities; 6637static enum tpacpi_volume_capabilities volume_capabilities;
6620static bool volume_control_allowed; 6638static bool volume_control_allowed;
6639static bool software_mute_requested = true;
6640static bool software_mute_active;
6641static int software_mute_orig_mode;
6621 6642
6622/* 6643/*
6623 * Used to syncronize writers to TP_EC_AUDIO and 6644 * Used to syncronize writers to TP_EC_AUDIO and
@@ -6635,6 +6656,8 @@ static void tpacpi_volume_checkpoint_nvram(void)
6635 return; 6656 return;
6636 if (!volume_control_allowed) 6657 if (!volume_control_allowed)
6637 return; 6658 return;
6659 if (software_mute_active)
6660 return;
6638 6661
6639 vdbg_printk(TPACPI_DBG_MIXER, 6662 vdbg_printk(TPACPI_DBG_MIXER,
6640 "trying to checkpoint mixer state to NVRAM...\n"); 6663 "trying to checkpoint mixer state to NVRAM...\n");
@@ -6696,6 +6719,12 @@ static int volume_set_status_ec(const u8 status)
6696 6719
6697 dbg_printk(TPACPI_DBG_MIXER, "set EC mixer to 0x%02x\n", status); 6720 dbg_printk(TPACPI_DBG_MIXER, "set EC mixer to 0x%02x\n", status);
6698 6721
6722 /*
6723 * On X200s, and possibly on others, it can take a while for
6724 * reads to become correct.
6725 */
6726 msleep(1);
6727
6699 return 0; 6728 return 0;
6700} 6729}
6701 6730
@@ -6778,6 +6807,57 @@ unlock:
6778 return rc; 6807 return rc;
6779} 6808}
6780 6809
6810static int volume_set_software_mute(bool startup)
6811{
6812 int result;
6813
6814 if (!tpacpi_is_lenovo())
6815 return -ENODEV;
6816
6817 if (startup) {
6818 if (!acpi_evalf(ec_handle, &software_mute_orig_mode,
6819 "HAUM", "qd"))
6820 return -EIO;
6821
6822 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6823 "Initial HAUM setting was %d\n",
6824 software_mute_orig_mode);
6825 }
6826
6827 if (!acpi_evalf(ec_handle, &result, "SAUM", "qdd",
6828 (int)TP_EC_MUTE_BTN_NONE))
6829 return -EIO;
6830
6831 if (result != TP_EC_MUTE_BTN_NONE)
6832 pr_warn("Unexpected SAUM result %d\n",
6833 result);
6834
6835 /*
6836 * In software mute mode, the standard codec controls take
6837 * precendence, so we unmute the ThinkPad HW switch at
6838 * startup. Just on case there are SAUM-capable ThinkPads
6839 * with level controls, set max HW volume as well.
6840 */
6841 if (tp_features.mixer_no_level_control)
6842 result = volume_set_mute(false);
6843 else
6844 result = volume_set_status(TP_EC_VOLUME_MAX);
6845
6846 if (result != 0)
6847 pr_warn("Failed to unmute the HW mute switch\n");
6848
6849 return 0;
6850}
6851
6852static void volume_exit_software_mute(void)
6853{
6854 int r;
6855
6856 if (!acpi_evalf(ec_handle, &r, "SAUM", "qdd", software_mute_orig_mode)
6857 || r != software_mute_orig_mode)
6858 pr_warn("Failed to restore mute mode\n");
6859}
6860
6781static int volume_alsa_set_volume(const u8 vol) 6861static int volume_alsa_set_volume(const u8 vol)
6782{ 6862{
6783 dbg_printk(TPACPI_DBG_MIXER, 6863 dbg_printk(TPACPI_DBG_MIXER,
@@ -6885,7 +6965,12 @@ static void volume_suspend(void)
6885 6965
6886static void volume_resume(void) 6966static void volume_resume(void)
6887{ 6967{
6888 volume_alsa_notify_change(); 6968 if (software_mute_active) {
6969 if (volume_set_software_mute(false) < 0)
6970 pr_warn("Failed to restore software mute\n");
6971 } else {
6972 volume_alsa_notify_change();
6973 }
6889} 6974}
6890 6975
6891static void volume_shutdown(void) 6976static void volume_shutdown(void)
@@ -6901,6 +6986,9 @@ static void volume_exit(void)
6901 } 6986 }
6902 6987
6903 tpacpi_volume_checkpoint_nvram(); 6988 tpacpi_volume_checkpoint_nvram();
6989
6990 if (software_mute_active)
6991 volume_exit_software_mute();
6904} 6992}
6905 6993
6906static int __init volume_create_alsa_mixer(void) 6994static int __init volume_create_alsa_mixer(void)
@@ -7085,16 +7173,20 @@ static int __init volume_init(struct ibm_init_struct *iibm)
7085 "mute is supported, volume control is %s\n", 7173 "mute is supported, volume control is %s\n",
7086 str_supported(!tp_features.mixer_no_level_control)); 7174 str_supported(!tp_features.mixer_no_level_control));
7087 7175
7088 rc = volume_create_alsa_mixer(); 7176 if (software_mute_requested && volume_set_software_mute(true) == 0) {
7089 if (rc) { 7177 software_mute_active = true;
7090 pr_err("Could not create the ALSA mixer interface\n"); 7178 } else {
7091 return rc; 7179 rc = volume_create_alsa_mixer();
7092 } 7180 if (rc) {
7181 pr_err("Could not create the ALSA mixer interface\n");
7182 return rc;
7183 }
7093 7184
7094 pr_info("Console audio control enabled, mode: %s\n", 7185 pr_info("Console audio control enabled, mode: %s\n",
7095 (volume_control_allowed) ? 7186 (volume_control_allowed) ?
7096 "override (read/write)" : 7187 "override (read/write)" :
7097 "monitor (read only)"); 7188 "monitor (read only)");
7189 }
7098 7190
7099 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER, 7191 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
7100 "registering volume hotkeys as change notification\n"); 7192 "registering volume hotkeys as change notification\n");
@@ -9091,6 +9183,10 @@ MODULE_PARM_DESC(volume_control,
9091 "Enables software override for the console audio " 9183 "Enables software override for the console audio "
9092 "control when true"); 9184 "control when true");
9093 9185
9186module_param_named(software_mute, software_mute_requested, bool, 0444);
9187MODULE_PARM_DESC(software_mute,
9188 "Request full software mute control");
9189
9094/* ALSA module API parameters */ 9190/* ALSA module API parameters */
9095module_param_named(index, alsa_index, int, 0444); 9191module_param_named(index, alsa_index, int, 0444);
9096MODULE_PARM_DESC(index, "ALSA index for the ACPI EC Mixer"); 9192MODULE_PARM_DESC(index, "ALSA index for the ACPI EC Mixer");