1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * osi.c - _OSI implementation
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2016 Intel Corporation
6*4882a593Smuzhiyun * Author: Lv Zheng <lv.zheng@intel.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun /* Uncomment next line to get verbose printout */
10*4882a593Smuzhiyun /* #define DEBUG */
11*4882a593Smuzhiyun #define pr_fmt(fmt) "ACPI: " fmt
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/acpi.h>
16*4882a593Smuzhiyun #include <linux/dmi.h>
17*4882a593Smuzhiyun #include <linux/platform_data/x86/apple.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include "internal.h"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define OSI_STRING_LENGTH_MAX 64
23*4882a593Smuzhiyun #define OSI_STRING_ENTRIES_MAX 16
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun struct acpi_osi_entry {
26*4882a593Smuzhiyun char string[OSI_STRING_LENGTH_MAX];
27*4882a593Smuzhiyun bool enable;
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static struct acpi_osi_config {
31*4882a593Smuzhiyun u8 default_disabling;
32*4882a593Smuzhiyun unsigned int linux_enable:1;
33*4882a593Smuzhiyun unsigned int linux_dmi:1;
34*4882a593Smuzhiyun unsigned int linux_cmdline:1;
35*4882a593Smuzhiyun unsigned int darwin_enable:1;
36*4882a593Smuzhiyun unsigned int darwin_dmi:1;
37*4882a593Smuzhiyun unsigned int darwin_cmdline:1;
38*4882a593Smuzhiyun } osi_config;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static struct acpi_osi_config osi_config;
41*4882a593Smuzhiyun static struct acpi_osi_entry
42*4882a593Smuzhiyun osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
43*4882a593Smuzhiyun {"Module Device", true},
44*4882a593Smuzhiyun {"Processor Device", true},
45*4882a593Smuzhiyun {"3.0 _SCP Extensions", true},
46*4882a593Smuzhiyun {"Processor Aggregator Device", true},
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun * Linux-Dell-Video is used by BIOS to disable RTD3 for NVidia graphics
49*4882a593Smuzhiyun * cards as RTD3 is not supported by drivers now. Systems with NVidia
50*4882a593Smuzhiyun * cards will hang without RTD3 disabled.
51*4882a593Smuzhiyun *
52*4882a593Smuzhiyun * Once NVidia drivers officially support RTD3, this _OSI strings can
53*4882a593Smuzhiyun * be removed if both new and old graphics cards are supported.
54*4882a593Smuzhiyun */
55*4882a593Smuzhiyun {"Linux-Dell-Video", true},
56*4882a593Smuzhiyun /*
57*4882a593Smuzhiyun * Linux-Lenovo-NV-HDMI-Audio is used by BIOS to power on NVidia's HDMI
58*4882a593Smuzhiyun * audio device which is turned off for power-saving in Windows OS.
59*4882a593Smuzhiyun * This power management feature observed on some Lenovo Thinkpad
60*4882a593Smuzhiyun * systems which will not be able to output audio via HDMI without
61*4882a593Smuzhiyun * a BIOS workaround.
62*4882a593Smuzhiyun */
63*4882a593Smuzhiyun {"Linux-Lenovo-NV-HDMI-Audio", true},
64*4882a593Smuzhiyun /*
65*4882a593Smuzhiyun * Linux-HPI-Hybrid-Graphics is used by BIOS to enable dGPU to
66*4882a593Smuzhiyun * output video directly to external monitors on HP Inc. mobile
67*4882a593Smuzhiyun * workstations as Nvidia and AMD VGA drivers provide limited
68*4882a593Smuzhiyun * hybrid graphics supports.
69*4882a593Smuzhiyun */
70*4882a593Smuzhiyun {"Linux-HPI-Hybrid-Graphics", true},
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun
acpi_osi_handler(acpi_string interface,u32 supported)73*4882a593Smuzhiyun static u32 acpi_osi_handler(acpi_string interface, u32 supported)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun if (!strcmp("Linux", interface)) {
76*4882a593Smuzhiyun pr_notice_once(FW_BUG
77*4882a593Smuzhiyun "BIOS _OSI(Linux) query %s%s\n",
78*4882a593Smuzhiyun osi_config.linux_enable ? "honored" : "ignored",
79*4882a593Smuzhiyun osi_config.linux_cmdline ? " via cmdline" :
80*4882a593Smuzhiyun osi_config.linux_dmi ? " via DMI" : "");
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun if (!strcmp("Darwin", interface)) {
83*4882a593Smuzhiyun pr_notice_once(
84*4882a593Smuzhiyun "BIOS _OSI(Darwin) query %s%s\n",
85*4882a593Smuzhiyun osi_config.darwin_enable ? "honored" : "ignored",
86*4882a593Smuzhiyun osi_config.darwin_cmdline ? " via cmdline" :
87*4882a593Smuzhiyun osi_config.darwin_dmi ? " via DMI" : "");
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun return supported;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
acpi_osi_setup(char * str)93*4882a593Smuzhiyun void __init acpi_osi_setup(char *str)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun struct acpi_osi_entry *osi;
96*4882a593Smuzhiyun bool enable = true;
97*4882a593Smuzhiyun int i;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun if (!acpi_gbl_create_osi_method)
100*4882a593Smuzhiyun return;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun if (str == NULL || *str == '\0') {
103*4882a593Smuzhiyun pr_info("_OSI method disabled\n");
104*4882a593Smuzhiyun acpi_gbl_create_osi_method = FALSE;
105*4882a593Smuzhiyun return;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun if (*str == '!') {
109*4882a593Smuzhiyun str++;
110*4882a593Smuzhiyun if (*str == '\0') {
111*4882a593Smuzhiyun /* Do not override acpi_osi=!* */
112*4882a593Smuzhiyun if (!osi_config.default_disabling)
113*4882a593Smuzhiyun osi_config.default_disabling =
114*4882a593Smuzhiyun ACPI_DISABLE_ALL_VENDOR_STRINGS;
115*4882a593Smuzhiyun return;
116*4882a593Smuzhiyun } else if (*str == '*') {
117*4882a593Smuzhiyun osi_config.default_disabling = ACPI_DISABLE_ALL_STRINGS;
118*4882a593Smuzhiyun for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
119*4882a593Smuzhiyun osi = &osi_setup_entries[i];
120*4882a593Smuzhiyun osi->enable = false;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun return;
123*4882a593Smuzhiyun } else if (*str == '!') {
124*4882a593Smuzhiyun osi_config.default_disabling = 0;
125*4882a593Smuzhiyun return;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun enable = false;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
131*4882a593Smuzhiyun osi = &osi_setup_entries[i];
132*4882a593Smuzhiyun if (!strcmp(osi->string, str)) {
133*4882a593Smuzhiyun osi->enable = enable;
134*4882a593Smuzhiyun break;
135*4882a593Smuzhiyun } else if (osi->string[0] == '\0') {
136*4882a593Smuzhiyun osi->enable = enable;
137*4882a593Smuzhiyun strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
138*4882a593Smuzhiyun break;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
__acpi_osi_setup_darwin(bool enable)143*4882a593Smuzhiyun static void __init __acpi_osi_setup_darwin(bool enable)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun osi_config.darwin_enable = !!enable;
146*4882a593Smuzhiyun if (enable) {
147*4882a593Smuzhiyun acpi_osi_setup("!");
148*4882a593Smuzhiyun acpi_osi_setup("Darwin");
149*4882a593Smuzhiyun } else {
150*4882a593Smuzhiyun acpi_osi_setup("!!");
151*4882a593Smuzhiyun acpi_osi_setup("!Darwin");
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
acpi_osi_setup_darwin(bool enable)155*4882a593Smuzhiyun static void __init acpi_osi_setup_darwin(bool enable)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun /* Override acpi_osi_dmi_blacklisted() */
158*4882a593Smuzhiyun osi_config.darwin_dmi = 0;
159*4882a593Smuzhiyun osi_config.darwin_cmdline = 1;
160*4882a593Smuzhiyun __acpi_osi_setup_darwin(enable);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /*
164*4882a593Smuzhiyun * The story of _OSI(Linux)
165*4882a593Smuzhiyun *
166*4882a593Smuzhiyun * From pre-history through Linux-2.6.22, Linux responded TRUE upon a BIOS
167*4882a593Smuzhiyun * OSI(Linux) query.
168*4882a593Smuzhiyun *
169*4882a593Smuzhiyun * Unfortunately, reference BIOS writers got wind of this and put
170*4882a593Smuzhiyun * OSI(Linux) in their example code, quickly exposing this string as
171*4882a593Smuzhiyun * ill-conceived and opening the door to an un-bounded number of BIOS
172*4882a593Smuzhiyun * incompatibilities.
173*4882a593Smuzhiyun *
174*4882a593Smuzhiyun * For example, OSI(Linux) was used on resume to re-POST a video card on
175*4882a593Smuzhiyun * one system, because Linux at that time could not do a speedy restore in
176*4882a593Smuzhiyun * its native driver. But then upon gaining quick native restore
177*4882a593Smuzhiyun * capability, Linux has no way to tell the BIOS to skip the time-consuming
178*4882a593Smuzhiyun * POST -- putting Linux at a permanent performance disadvantage. On
179*4882a593Smuzhiyun * another system, the BIOS writer used OSI(Linux) to infer native OS
180*4882a593Smuzhiyun * support for IPMI! On other systems, OSI(Linux) simply got in the way of
181*4882a593Smuzhiyun * Linux claiming to be compatible with other operating systems, exposing
182*4882a593Smuzhiyun * BIOS issues such as skipped device initialization.
183*4882a593Smuzhiyun *
184*4882a593Smuzhiyun * So "Linux" turned out to be a really poor chose of OSI string, and from
185*4882a593Smuzhiyun * Linux-2.6.23 onward we respond FALSE.
186*4882a593Smuzhiyun *
187*4882a593Smuzhiyun * BIOS writers should NOT query _OSI(Linux) on future systems. Linux will
188*4882a593Smuzhiyun * complain on the console when it sees it, and return FALSE. To get Linux
189*4882a593Smuzhiyun * to return TRUE for your system will require a kernel source update to
190*4882a593Smuzhiyun * add a DMI entry, or boot with "acpi_osi=Linux"
191*4882a593Smuzhiyun */
__acpi_osi_setup_linux(bool enable)192*4882a593Smuzhiyun static void __init __acpi_osi_setup_linux(bool enable)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun osi_config.linux_enable = !!enable;
195*4882a593Smuzhiyun if (enable)
196*4882a593Smuzhiyun acpi_osi_setup("Linux");
197*4882a593Smuzhiyun else
198*4882a593Smuzhiyun acpi_osi_setup("!Linux");
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
acpi_osi_setup_linux(bool enable)201*4882a593Smuzhiyun static void __init acpi_osi_setup_linux(bool enable)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun /* Override acpi_osi_dmi_blacklisted() */
204*4882a593Smuzhiyun osi_config.linux_dmi = 0;
205*4882a593Smuzhiyun osi_config.linux_cmdline = 1;
206*4882a593Smuzhiyun __acpi_osi_setup_linux(enable);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun /*
210*4882a593Smuzhiyun * Modify the list of "OS Interfaces" reported to BIOS via _OSI
211*4882a593Smuzhiyun *
212*4882a593Smuzhiyun * empty string disables _OSI
213*4882a593Smuzhiyun * string starting with '!' disables that string
214*4882a593Smuzhiyun * otherwise string is added to list, augmenting built-in strings
215*4882a593Smuzhiyun */
acpi_osi_setup_late(void)216*4882a593Smuzhiyun static void __init acpi_osi_setup_late(void)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun struct acpi_osi_entry *osi;
219*4882a593Smuzhiyun char *str;
220*4882a593Smuzhiyun int i;
221*4882a593Smuzhiyun acpi_status status;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun if (osi_config.default_disabling) {
224*4882a593Smuzhiyun status = acpi_update_interfaces(osi_config.default_disabling);
225*4882a593Smuzhiyun if (ACPI_SUCCESS(status))
226*4882a593Smuzhiyun pr_info("Disabled all _OSI OS vendors%s\n",
227*4882a593Smuzhiyun osi_config.default_disabling ==
228*4882a593Smuzhiyun ACPI_DISABLE_ALL_STRINGS ?
229*4882a593Smuzhiyun " and feature groups" : "");
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
233*4882a593Smuzhiyun osi = &osi_setup_entries[i];
234*4882a593Smuzhiyun str = osi->string;
235*4882a593Smuzhiyun if (*str == '\0')
236*4882a593Smuzhiyun break;
237*4882a593Smuzhiyun if (osi->enable) {
238*4882a593Smuzhiyun status = acpi_install_interface(str);
239*4882a593Smuzhiyun if (ACPI_SUCCESS(status))
240*4882a593Smuzhiyun pr_info("Added _OSI(%s)\n", str);
241*4882a593Smuzhiyun } else {
242*4882a593Smuzhiyun status = acpi_remove_interface(str);
243*4882a593Smuzhiyun if (ACPI_SUCCESS(status))
244*4882a593Smuzhiyun pr_info("Deleted _OSI(%s)\n", str);
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
osi_setup(char * str)249*4882a593Smuzhiyun static int __init osi_setup(char *str)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun if (str && !strcmp("Linux", str))
252*4882a593Smuzhiyun acpi_osi_setup_linux(true);
253*4882a593Smuzhiyun else if (str && !strcmp("!Linux", str))
254*4882a593Smuzhiyun acpi_osi_setup_linux(false);
255*4882a593Smuzhiyun else if (str && !strcmp("Darwin", str))
256*4882a593Smuzhiyun acpi_osi_setup_darwin(true);
257*4882a593Smuzhiyun else if (str && !strcmp("!Darwin", str))
258*4882a593Smuzhiyun acpi_osi_setup_darwin(false);
259*4882a593Smuzhiyun else
260*4882a593Smuzhiyun acpi_osi_setup(str);
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun return 1;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun __setup("acpi_osi=", osi_setup);
265*4882a593Smuzhiyun
acpi_osi_is_win8(void)266*4882a593Smuzhiyun bool acpi_osi_is_win8(void)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun EXPORT_SYMBOL(acpi_osi_is_win8);
271*4882a593Smuzhiyun
acpi_osi_dmi_darwin(void)272*4882a593Smuzhiyun static void __init acpi_osi_dmi_darwin(void)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun pr_notice("DMI detected to setup _OSI(\"Darwin\"): Apple hardware\n");
275*4882a593Smuzhiyun osi_config.darwin_dmi = 1;
276*4882a593Smuzhiyun __acpi_osi_setup_darwin(true);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
acpi_osi_dmi_linux(bool enable,const struct dmi_system_id * d)279*4882a593Smuzhiyun static void __init acpi_osi_dmi_linux(bool enable,
280*4882a593Smuzhiyun const struct dmi_system_id *d)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun pr_notice("DMI detected to setup _OSI(\"Linux\"): %s\n", d->ident);
283*4882a593Smuzhiyun osi_config.linux_dmi = 1;
284*4882a593Smuzhiyun __acpi_osi_setup_linux(enable);
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
dmi_enable_osi_linux(const struct dmi_system_id * d)287*4882a593Smuzhiyun static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun acpi_osi_dmi_linux(true, d);
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun return 0;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
dmi_disable_osi_vista(const struct dmi_system_id * d)294*4882a593Smuzhiyun static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun pr_notice("DMI detected: %s\n", d->ident);
297*4882a593Smuzhiyun acpi_osi_setup("!Windows 2006");
298*4882a593Smuzhiyun acpi_osi_setup("!Windows 2006 SP1");
299*4882a593Smuzhiyun acpi_osi_setup("!Windows 2006 SP2");
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun return 0;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
dmi_disable_osi_win7(const struct dmi_system_id * d)304*4882a593Smuzhiyun static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun pr_notice("DMI detected: %s\n", d->ident);
307*4882a593Smuzhiyun acpi_osi_setup("!Windows 2009");
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun return 0;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
dmi_disable_osi_win8(const struct dmi_system_id * d)312*4882a593Smuzhiyun static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun pr_notice("DMI detected: %s\n", d->ident);
315*4882a593Smuzhiyun acpi_osi_setup("!Windows 2012");
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun return 0;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun /*
321*4882a593Smuzhiyun * Linux default _OSI response behavior is determined by this DMI table.
322*4882a593Smuzhiyun *
323*4882a593Smuzhiyun * Note that _OSI("Linux")/_OSI("Darwin") determined here can be overridden
324*4882a593Smuzhiyun * by acpi_osi=!Linux/acpi_osi=!Darwin command line options.
325*4882a593Smuzhiyun */
326*4882a593Smuzhiyun static const struct dmi_system_id acpi_osi_dmi_table[] __initconst = {
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun .callback = dmi_disable_osi_vista,
329*4882a593Smuzhiyun .ident = "Fujitsu Siemens",
330*4882a593Smuzhiyun .matches = {
331*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
332*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
333*4882a593Smuzhiyun },
334*4882a593Smuzhiyun },
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun /*
337*4882a593Smuzhiyun * There have a NVIF method in MSI GX723 DSDT need call by Nvidia
338*4882a593Smuzhiyun * driver (e.g. nouveau) when user press brightness hotkey.
339*4882a593Smuzhiyun * Currently, nouveau driver didn't do the job and it causes there
340*4882a593Smuzhiyun * have a infinite while loop in DSDT when user press hotkey.
341*4882a593Smuzhiyun * We add MSI GX723's dmi information to this table for workaround
342*4882a593Smuzhiyun * this issue.
343*4882a593Smuzhiyun * Will remove MSI GX723 from the table after nouveau grows support.
344*4882a593Smuzhiyun */
345*4882a593Smuzhiyun .callback = dmi_disable_osi_vista,
346*4882a593Smuzhiyun .ident = "MSI GX723",
347*4882a593Smuzhiyun .matches = {
348*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
349*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
350*4882a593Smuzhiyun },
351*4882a593Smuzhiyun },
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun .callback = dmi_disable_osi_vista,
354*4882a593Smuzhiyun .ident = "Sony VGN-NS10J_S",
355*4882a593Smuzhiyun .matches = {
356*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
357*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
358*4882a593Smuzhiyun },
359*4882a593Smuzhiyun },
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun .callback = dmi_disable_osi_vista,
362*4882a593Smuzhiyun .ident = "Sony VGN-SR290J",
363*4882a593Smuzhiyun .matches = {
364*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
365*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
366*4882a593Smuzhiyun },
367*4882a593Smuzhiyun },
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun .callback = dmi_disable_osi_vista,
370*4882a593Smuzhiyun .ident = "VGN-NS50B_L",
371*4882a593Smuzhiyun .matches = {
372*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
373*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
374*4882a593Smuzhiyun },
375*4882a593Smuzhiyun },
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun .callback = dmi_disable_osi_vista,
378*4882a593Smuzhiyun .ident = "VGN-SR19XN",
379*4882a593Smuzhiyun .matches = {
380*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
381*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"),
382*4882a593Smuzhiyun },
383*4882a593Smuzhiyun },
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun .callback = dmi_disable_osi_vista,
386*4882a593Smuzhiyun .ident = "Toshiba Satellite L355",
387*4882a593Smuzhiyun .matches = {
388*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
389*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
390*4882a593Smuzhiyun },
391*4882a593Smuzhiyun },
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun .callback = dmi_disable_osi_win7,
394*4882a593Smuzhiyun .ident = "ASUS K50IJ",
395*4882a593Smuzhiyun .matches = {
396*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
397*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
398*4882a593Smuzhiyun },
399*4882a593Smuzhiyun },
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun .callback = dmi_disable_osi_vista,
402*4882a593Smuzhiyun .ident = "Toshiba P305D",
403*4882a593Smuzhiyun .matches = {
404*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
405*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
406*4882a593Smuzhiyun },
407*4882a593Smuzhiyun },
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun .callback = dmi_disable_osi_vista,
410*4882a593Smuzhiyun .ident = "Toshiba NB100",
411*4882a593Smuzhiyun .matches = {
412*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
413*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
414*4882a593Smuzhiyun },
415*4882a593Smuzhiyun },
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /*
418*4882a593Smuzhiyun * The wireless hotkey does not work on those machines when
419*4882a593Smuzhiyun * returning true for _OSI("Windows 2012")
420*4882a593Smuzhiyun */
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun .callback = dmi_disable_osi_win8,
423*4882a593Smuzhiyun .ident = "Dell Inspiron 7737",
424*4882a593Smuzhiyun .matches = {
425*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
426*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
427*4882a593Smuzhiyun },
428*4882a593Smuzhiyun },
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun .callback = dmi_disable_osi_win8,
431*4882a593Smuzhiyun .ident = "Dell Inspiron 7537",
432*4882a593Smuzhiyun .matches = {
433*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
434*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
435*4882a593Smuzhiyun },
436*4882a593Smuzhiyun },
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun .callback = dmi_disable_osi_win8,
439*4882a593Smuzhiyun .ident = "Dell Inspiron 5437",
440*4882a593Smuzhiyun .matches = {
441*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
442*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"),
443*4882a593Smuzhiyun },
444*4882a593Smuzhiyun },
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun .callback = dmi_disable_osi_win8,
447*4882a593Smuzhiyun .ident = "Dell Inspiron 3437",
448*4882a593Smuzhiyun .matches = {
449*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
450*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"),
451*4882a593Smuzhiyun },
452*4882a593Smuzhiyun },
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun .callback = dmi_disable_osi_win8,
455*4882a593Smuzhiyun .ident = "Dell Vostro 3446",
456*4882a593Smuzhiyun .matches = {
457*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
458*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
459*4882a593Smuzhiyun },
460*4882a593Smuzhiyun },
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun .callback = dmi_disable_osi_win8,
463*4882a593Smuzhiyun .ident = "Dell Vostro 3546",
464*4882a593Smuzhiyun .matches = {
465*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
466*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
467*4882a593Smuzhiyun },
468*4882a593Smuzhiyun },
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun /*
471*4882a593Smuzhiyun * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
472*4882a593Smuzhiyun * Linux ignores it, except for the machines enumerated below.
473*4882a593Smuzhiyun */
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun /*
476*4882a593Smuzhiyun * Without this EEEpc exports a non working WMI interface, with
477*4882a593Smuzhiyun * this it exports a working "good old" eeepc_laptop interface,
478*4882a593Smuzhiyun * fixing both brightness control, and rfkill not working.
479*4882a593Smuzhiyun */
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun .callback = dmi_enable_osi_linux,
482*4882a593Smuzhiyun .ident = "Asus EEE PC 1015PX",
483*4882a593Smuzhiyun .matches = {
484*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
485*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"),
486*4882a593Smuzhiyun },
487*4882a593Smuzhiyun },
488*4882a593Smuzhiyun {}
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun
acpi_osi_dmi_blacklisted(void)491*4882a593Smuzhiyun static __init void acpi_osi_dmi_blacklisted(void)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun dmi_check_system(acpi_osi_dmi_table);
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun /* Enable _OSI("Darwin") for Apple platforms. */
496*4882a593Smuzhiyun if (x86_apple_machine)
497*4882a593Smuzhiyun acpi_osi_dmi_darwin();
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun
early_acpi_osi_init(void)500*4882a593Smuzhiyun int __init early_acpi_osi_init(void)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun acpi_osi_dmi_blacklisted();
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun return 0;
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun
acpi_osi_init(void)507*4882a593Smuzhiyun int __init acpi_osi_init(void)
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun acpi_install_interface_handler(acpi_osi_handler);
510*4882a593Smuzhiyun acpi_osi_setup_late();
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun return 0;
513*4882a593Smuzhiyun }
514