diff options
-rw-r--r-- | Documentation/laptops/thinkpad-acpi.txt | 13 | ||||
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 47 |
2 files changed, 55 insertions, 5 deletions
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index bd87682103c1..6a5814330e51 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt | |||
@@ -1097,6 +1097,18 @@ Volume control | |||
1097 | 1097 | ||
1098 | procfs: /proc/acpi/ibm/volume | 1098 | procfs: /proc/acpi/ibm/volume |
1099 | 1099 | ||
1100 | NOTE: by default, the volume control interface operates in read-only | ||
1101 | mode, as it is supposed to be used for on-screen-display purposes. | ||
1102 | The read/write mode can be enabled through the use of the | ||
1103 | "volume_control=1" module parameter. | ||
1104 | |||
1105 | NOTE: distros are urged to not enable volume_control by default, this | ||
1106 | should be done by the local admin only. The ThinkPad UI is for the | ||
1107 | console audio control to be done through the volume keys only, and for | ||
1108 | the desktop environment to just provide on-screen-display feedback. | ||
1109 | Software volume control should be done only in the main AC97/HDA | ||
1110 | mixer. | ||
1111 | |||
1100 | This feature allows volume control on ThinkPad models with a digital | 1112 | This feature allows volume control on ThinkPad models with a digital |
1101 | volume knob (when available, not all models have it), as well as | 1113 | volume knob (when available, not all models have it), as well as |
1102 | mute/unmute control. The available commands are: | 1114 | mute/unmute control. The available commands are: |
@@ -1465,3 +1477,4 @@ Sysfs interface changelog: | |||
1465 | 0x020600: Marker for backlight change event support. | 1477 | 0x020600: Marker for backlight change event support. |
1466 | 1478 | ||
1467 | 0x020700: Support for mute-only mixers. | 1479 | 0x020700: Support for mute-only mixers. |
1480 | Volume control in read-only mode by default. | ||
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 4d909d5a0340..2d74926913d2 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -311,6 +311,7 @@ static struct { | |||
311 | 311 | ||
312 | static struct { | 312 | static struct { |
313 | u16 hotkey_mask_ff:1; | 313 | u16 hotkey_mask_ff:1; |
314 | u16 volume_ctrl_forbidden:1; | ||
314 | } tp_warned; | 315 | } tp_warned; |
315 | 316 | ||
316 | struct thinkpad_id_data { | 317 | struct thinkpad_id_data { |
@@ -6434,6 +6435,7 @@ static enum tpacpi_volume_access_mode volume_mode = | |||
6434 | TPACPI_VOL_MODE_MAX; | 6435 | TPACPI_VOL_MODE_MAX; |
6435 | 6436 | ||
6436 | static enum tpacpi_volume_capabilities volume_capabilities; | 6437 | static enum tpacpi_volume_capabilities volume_capabilities; |
6438 | static int volume_control_allowed; | ||
6437 | 6439 | ||
6438 | /* | 6440 | /* |
6439 | * Used to syncronize writers to TP_EC_AUDIO and | 6441 | * Used to syncronize writers to TP_EC_AUDIO and |
@@ -6449,6 +6451,8 @@ static void tpacpi_volume_checkpoint_nvram(void) | |||
6449 | 6451 | ||
6450 | if (volume_mode != TPACPI_VOL_MODE_ECNVRAM) | 6452 | if (volume_mode != TPACPI_VOL_MODE_ECNVRAM) |
6451 | return; | 6453 | return; |
6454 | if (!volume_control_allowed) | ||
6455 | return; | ||
6452 | 6456 | ||
6453 | vdbg_printk(TPACPI_DBG_MIXER, | 6457 | vdbg_printk(TPACPI_DBG_MIXER, |
6454 | "trying to checkpoint mixer state to NVRAM...\n"); | 6458 | "trying to checkpoint mixer state to NVRAM...\n"); |
@@ -6691,6 +6695,12 @@ static int __init volume_init(struct ibm_init_struct *iibm) | |||
6691 | "mute is supported, volume control is %s\n", | 6695 | "mute is supported, volume control is %s\n", |
6692 | str_supported(!tp_features.mixer_no_level_control)); | 6696 | str_supported(!tp_features.mixer_no_level_control)); |
6693 | 6697 | ||
6698 | printk(TPACPI_INFO | ||
6699 | "Console audio control enabled, mode: %s\n", | ||
6700 | (volume_control_allowed) ? | ||
6701 | "override (read/write)" : | ||
6702 | "monitor (read only)"); | ||
6703 | |||
6694 | return 0; | 6704 | return 0; |
6695 | } | 6705 | } |
6696 | 6706 | ||
@@ -6711,11 +6721,16 @@ static int volume_read(char *p) | |||
6711 | len += sprintf(p + len, "mute:\t\t%s\n", | 6721 | len += sprintf(p + len, "mute:\t\t%s\n", |
6712 | onoff(status, TP_EC_AUDIO_MUTESW)); | 6722 | onoff(status, TP_EC_AUDIO_MUTESW)); |
6713 | 6723 | ||
6714 | len += sprintf(p + len, "commands:\tunmute, mute\n"); | 6724 | if (volume_control_allowed) { |
6715 | if (!tp_features.mixer_no_level_control) { | 6725 | len += sprintf(p + len, "commands:\tunmute, mute\n"); |
6716 | len += sprintf(p + len, "commands:\tup, down\n"); | 6726 | if (!tp_features.mixer_no_level_control) { |
6717 | len += sprintf(p + len, "commands:\tlevel <level>" | 6727 | len += sprintf(p + len, |
6718 | " (<level> is 0-%d)\n", TP_EC_VOLUME_MAX); | 6728 | "commands:\tup, down\n"); |
6729 | len += sprintf(p + len, | ||
6730 | "commands:\tlevel <level>" | ||
6731 | " (<level> is 0-%d)\n", | ||
6732 | TP_EC_VOLUME_MAX); | ||
6733 | } | ||
6719 | } | 6734 | } |
6720 | } | 6735 | } |
6721 | 6736 | ||
@@ -6730,6 +6745,23 @@ static int volume_write(char *buf) | |||
6730 | char *cmd; | 6745 | char *cmd; |
6731 | int rc; | 6746 | int rc; |
6732 | 6747 | ||
6748 | /* | ||
6749 | * We do allow volume control at driver startup, so that the | ||
6750 | * user can set initial state through the volume=... parameter hack. | ||
6751 | */ | ||
6752 | if (!volume_control_allowed && tpacpi_lifecycle != TPACPI_LIFE_INIT) { | ||
6753 | if (unlikely(!tp_warned.volume_ctrl_forbidden)) { | ||
6754 | tp_warned.volume_ctrl_forbidden = 1; | ||
6755 | printk(TPACPI_NOTICE | ||
6756 | "Console audio control in monitor mode, " | ||
6757 | "changes are not allowed.\n"); | ||
6758 | printk(TPACPI_NOTICE | ||
6759 | "Use the volume_control=1 module parameter " | ||
6760 | "to enable volume control\n"); | ||
6761 | } | ||
6762 | return -EPERM; | ||
6763 | } | ||
6764 | |||
6733 | rc = volume_get_status(&s); | 6765 | rc = volume_get_status(&s); |
6734 | if (rc < 0) | 6766 | if (rc < 0) |
6735 | return rc; | 6767 | return rc; |
@@ -8515,6 +8547,11 @@ MODULE_PARM_DESC(volume_capabilities, | |||
8515 | "Selects the mixer capabilites: " | 8547 | "Selects the mixer capabilites: " |
8516 | "0=auto, 1=volume and mute, 2=mute only"); | 8548 | "0=auto, 1=volume and mute, 2=mute only"); |
8517 | 8549 | ||
8550 | module_param_named(volume_control, volume_control_allowed, bool, 0444); | ||
8551 | MODULE_PARM_DESC(volume_control, | ||
8552 | "Enables software override for the console audio " | ||
8553 | "control when true"); | ||
8554 | |||
8518 | #define TPACPI_PARAM(feature) \ | 8555 | #define TPACPI_PARAM(feature) \ |
8519 | module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ | 8556 | module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ |
8520 | MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \ | 8557 | MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \ |