xref: /OK3568_Linux_fs/kernel/drivers/acpi/osi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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