Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI / init: Make it possible to override _REV

The platform firmware on some systems expects Linux to return "5" as
the supported ACPI revision which makes it expose system configuration
information in a special way.

For example, based on what ACPI exports as the supported revision,
Dell XPS 13 (2015) configures its audio device to either work in HDA
mode or in I2S mode, where the former is supposed to be used on Linux
until the latter is fully supported (in the kernel as well as in user
space).

Since ACPI 6 mandates that _REV should return "2" if ACPI 2 or later
is supported by the OS, a subsequent change will make that happen, so
make it possible to override that on systems where "5" is expected to
be returned for Linux to work correctly one them (such as the Dell
machine mentioned above).

Original-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

+71
+6
Documentation/kernel-parameters.txt
··· 274 274 acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS 275 275 Format: To spoof as Windows 98: ="Microsoft Windows" 276 276 277 + acpi_rev_override [ACPI] Override the _REV object to return 5 (instead 278 + of 2 which is mandated by ACPI 6) as the supported ACPI 279 + specification revision (when using this switch, it may 280 + be necessary to carry out a cold reboot _twice_ in a 281 + row to make it take effect on the platform firmware). 282 + 277 283 acpi_osi= [HW,ACPI] Modify list of supported OS interface strings 278 284 acpi_osi="string1" # add string1 279 285 acpi_osi="!string2" # remove string2
+20
drivers/acpi/Kconfig
··· 77 77 78 78 Say N to delete power /proc/acpi/ directories that have moved to /sys/ 79 79 80 + config ACPI_REV_OVERRIDE_POSSIBLE 81 + bool "Allow supported ACPI revision to be overriden" 82 + depends on X86 83 + default y 84 + help 85 + The platform firmware on some systems expects Linux to return "5" as 86 + the supported ACPI revision which makes it expose system configuration 87 + information in a special way. 88 + 89 + For example, based on what ACPI exports as the supported revision, 90 + Dell XPS 13 (2015) configures its audio device to either work in HDA 91 + mode or in I2S mode, where the former is supposed to be used on Linux 92 + until the latter is fully supported (in the kernel as well as in user 93 + space). 94 + 95 + This option enables a DMI-based quirk for the above Dell machine (so 96 + that HDA audio is exposed by the platform firmware to the kernel) and 97 + makes it possible to force the kernel to return "5" as the supported 98 + ACPI revision via the "acpi_rev_override" command line switch. 99 + 80 100 config ACPI_EC_DEBUGFS 81 101 tristate "EC read/write access through /sys/kernel/debug/ec" 82 102 default n
+26
drivers/acpi/blacklist.c
··· 162 162 acpi_osi_setup("!Windows 2012"); 163 163 return 0; 164 164 } 165 + #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE 166 + static int __init dmi_enable_rev_override(const struct dmi_system_id *d) 167 + { 168 + printk(KERN_NOTICE PREFIX "DMI detected: %s (force ACPI _REV to 5)\n", 169 + d->ident); 170 + acpi_rev_override_setup(NULL); 171 + return 0; 172 + } 173 + #endif 165 174 166 175 static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { 167 176 { ··· 334 325 DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"), 335 326 }, 336 327 }, 328 + 329 + #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE 330 + /* 331 + * DELL XPS 13 (2015) switches sound between HDA and I2S 332 + * depending on the ACPI _REV callback. If userspace supports 333 + * I2S sufficiently (or if you do not care about sound), you 334 + * can safely disable this quirk. 335 + */ 336 + { 337 + .callback = dmi_enable_rev_override, 338 + .ident = "DELL XPS 13 (2015)", 339 + .matches = { 340 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 341 + DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343"), 342 + }, 343 + }, 344 + #endif 337 345 {} 338 346 }; 339 347
+1
drivers/acpi/internal.h
··· 58 58 #else 59 59 static inline void acpi_cmos_rtc_init(void) {} 60 60 #endif 61 + int acpi_rev_override_setup(char *str); 61 62 62 63 extern bool acpi_force_hot_remove; 63 64
+18
drivers/acpi/osl.c
··· 537 537 } 538 538 #endif 539 539 540 + #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE 541 + static bool acpi_rev_override; 542 + 543 + int __init acpi_rev_override_setup(char *str) 544 + { 545 + acpi_rev_override = true; 546 + return 1; 547 + } 548 + __setup("acpi_rev_override", acpi_rev_override_setup); 549 + #else 550 + #define acpi_rev_override false 551 + #endif 552 + 540 553 #define ACPI_MAX_OVERRIDE_LEN 100 541 554 542 555 static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN]; ··· 566 553 printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n", 567 554 acpi_os_name); 568 555 *new_val = acpi_os_name; 556 + } 557 + 558 + if (!memcmp(init_val->name, "_REV", 4) && acpi_rev_override) { 559 + printk(KERN_INFO PREFIX "Overriding _REV return value to 5\n"); 560 + *new_val = (char *)5; 569 561 } 570 562 571 563 return AE_OK;