aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/thinkpad_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/thinkpad_acpi.c')
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c71
1 files changed, 57 insertions, 14 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 7817cef6aae1..1f27b350ae01 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -122,6 +122,11 @@ enum {
122 TP_NVRAM_POS_LEVEL_VOLUME = 0, 122 TP_NVRAM_POS_LEVEL_VOLUME = 0,
123}; 123};
124 124
125/* Misc NVRAM-related */
126enum {
127 TP_NVRAM_LEVEL_VOLUME_MAX = 14,
128};
129
125/* ACPI HIDs */ 130/* ACPI HIDs */
126#define TPACPI_ACPI_HKEY_HID "IBM0068" 131#define TPACPI_ACPI_HKEY_HID "IBM0068"
127 132
@@ -2418,6 +2423,21 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
2418 tpacpi_hotkey_send_key(__scancode); \ 2423 tpacpi_hotkey_send_key(__scancode); \
2419 } while (0) 2424 } while (0)
2420 2425
2426 void issue_volchange(const unsigned int oldvol,
2427 const unsigned int newvol)
2428 {
2429 unsigned int i = oldvol;
2430
2431 while (i > newvol) {
2432 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
2433 i--;
2434 }
2435 while (i < newvol) {
2436 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
2437 i++;
2438 }
2439 }
2440
2421 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_THINKPAD, thinkpad_toggle); 2441 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_THINKPAD, thinkpad_toggle);
2422 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNSPACE, zoom_toggle); 2442 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNSPACE, zoom_toggle);
2423 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF7, display_toggle); 2443 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF7, display_toggle);
@@ -2427,24 +2447,47 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
2427 2447
2428 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF8, displayexp_toggle); 2448 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF8, displayexp_toggle);
2429 2449
2430 /* handle volume */ 2450 /*
2431 if (oldn->volume_toggle != newn->volume_toggle) { 2451 * Handle volume
2432 if (oldn->mute != newn->mute) { 2452 *
2453 * This code is supposed to duplicate the IBM firmware behaviour:
2454 * - Pressing MUTE issues mute hotkey message, even when already mute
2455 * - Pressing Volume up/down issues volume up/down hotkey messages,
2456 * even when already at maximum or minumum volume
2457 * - The act of unmuting issues volume up/down notification,
2458 * depending which key was used to unmute
2459 *
2460 * We are constrained to what the NVRAM can tell us, which is not much
2461 * and certainly not enough if more than one volume hotkey was pressed
2462 * since the last poll cycle.
2463 *
2464 * Just to make our life interesting, some newer Lenovo ThinkPads have
2465 * bugs in the BIOS and may fail to update volume_toggle properly.
2466 */
2467 if (newn->mute) {
2468 /* muted */
2469 if (!oldn->mute ||
2470 oldn->volume_toggle != newn->volume_toggle ||
2471 oldn->volume_level != newn->volume_level) {
2472 /* recently muted, or repeated mute keypress, or
2473 * multiple presses ending in mute */
2474 issue_volchange(oldn->volume_level, newn->volume_level);
2433 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE); 2475 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE);
2434 } 2476 }
2435 if (oldn->volume_level > newn->volume_level) { 2477 } else {
2436 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN); 2478 /* unmute */
2437 } else if (oldn->volume_level < newn->volume_level) { 2479 if (oldn->mute) {
2480 /* recently unmuted, issue 'unmute' keypress */
2438 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP); 2481 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
2439 } else if (oldn->mute == newn->mute) { 2482 }
2440 /* repeated key presses that didn't change state */ 2483 if (oldn->volume_level != newn->volume_level) {
2441 if (newn->mute) { 2484 issue_volchange(oldn->volume_level, newn->volume_level);
2442 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE); 2485 } else if (oldn->volume_toggle != newn->volume_toggle) {
2443 } else if (newn->volume_level != 0) { 2486 /* repeated vol up/down keypress at end of scale ? */
2444 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP); 2487 if (newn->volume_level == 0)
2445 } else {
2446 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN); 2488 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
2447 } 2489 else if (newn->volume_level >= TP_NVRAM_LEVEL_VOLUME_MAX)
2490 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
2448 } 2491 }
2449 } 2492 }
2450 2493