aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/video_detect.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2015-06-16 10:27:48 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-06-18 19:10:44 -0400
commit87521e16a7abbf3fa337f56cb4d1e18247f15e8a (patch)
tree63ae44bbc4a4aaf0b48f03536c825d36baaf4238 /drivers/acpi/video_detect.c
parent14ca7a47d0ab2a7a35faab130e6d9682f8ff1a46 (diff)
acpi-video-detect: Rewrite backlight interface selection logic
Currently we have 2 kernel commandline options + dmi-quirks in 3 places all interacting (in interesting ways) to select which which backlight interface to use. On the commandline we've acpi_backlight=[video|vendor] and video.use_native_backlight=[0|1]. DMI quirks we have in acpi/video-detect.c, acpi/video.c and drivers/platform/x86/*.c . This commit is the first step to cleaning this up, replacing the 2 cmdline options with just acpi_backlight=[video|vendor|native|none], and adds a new API to video_detect.c to reflect this. Follow up commits will also move other related code, like unregistering the acpi_video backlight interface if it was registered before other drivers which take priority over it are loaded, to video_detect.c where this logic really belongs. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Darren Hart <dvhart@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/video_detect.c')
-rw-r--r--drivers/acpi/video_detect.c171
1 files changed, 83 insertions, 88 deletions
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index bb6133c60175..0f9586b7f3d1 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -1,4 +1,6 @@
1/* 1/*
2 * Copyright (C) 2015 Red Hat Inc.
3 * Hans de Goede <hdegoede@redhat.com>
2 * Copyright (C) 2008 SuSE Linux Products GmbH 4 * Copyright (C) 2008 SuSE Linux Products GmbH
3 * Thomas Renninger <trenn@suse.de> 5 * Thomas Renninger <trenn@suse.de>
4 * 6 *
@@ -9,44 +11,45 @@
9 * acpi_get_pci_dev() can be called to identify ACPI graphics 11 * acpi_get_pci_dev() can be called to identify ACPI graphics
10 * devices for which a real graphics card is plugged in 12 * devices for which a real graphics card is plugged in
11 * 13 *
12 * Now acpi_video_get_capabilities() can be called to check which
13 * capabilities the graphics cards plugged in support. The check for general
14 * video capabilities will be triggered by the first caller of
15 * acpi_video_get_capabilities(NULL); which will happen when the first
16 * backlight switching supporting driver calls:
17 * acpi_video_backlight_support();
18 *
19 * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B) 14 * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B)
20 * are available, video.ko should be used to handle the device. 15 * are available, video.ko should be used to handle the device.
21 * 16 *
22 * Otherwise vendor specific drivers like thinkpad_acpi, asus-laptop, 17 * Otherwise vendor specific drivers like thinkpad_acpi, asus-laptop,
23 * sony_acpi,... can take care about backlight brightness. 18 * sony_acpi,... can take care about backlight brightness.
24 * 19 *
25 * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m) 20 * Backlight drivers can use acpi_video_get_backlight_type() to determine
26 * this file will not be compiled, acpi_video_get_capabilities() and 21 * which driver should handle the backlight.
27 * acpi_video_backlight_support() will always return 0 and vendor specific
28 * drivers always can handle backlight.
29 * 22 *
23 * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m)
24 * this file will not be compiled and acpi_video_get_backlight_type() will
25 * always return acpi_backlight_vendor.
30 */ 26 */
31 27
32#include <linux/export.h> 28#include <linux/export.h>
33#include <linux/acpi.h> 29#include <linux/acpi.h>
30#include <linux/backlight.h>
34#include <linux/dmi.h> 31#include <linux/dmi.h>
35#include <linux/module.h> 32#include <linux/module.h>
36#include <linux/pci.h> 33#include <linux/pci.h>
34#include <linux/types.h>
35#include <acpi/video.h>
37 36
38ACPI_MODULE_NAME("video"); 37ACPI_MODULE_NAME("video");
39#define _COMPONENT ACPI_VIDEO_COMPONENT 38#define _COMPONENT ACPI_VIDEO_COMPONENT
40 39
41static long acpi_video_support; 40static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef;
42static bool acpi_video_caps_checked; 41static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef;
43 42
44static void acpi_video_parse_cmdline(void) 43static void acpi_video_parse_cmdline(void)
45{ 44{
46 if (!strcmp("vendor", acpi_video_backlight_string)) 45 if (!strcmp("vendor", acpi_video_backlight_string))
47 acpi_video_support |= ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR; 46 acpi_backlight_cmdline = acpi_backlight_vendor;
48 if (!strcmp("video", acpi_video_backlight_string)) 47 if (!strcmp("video", acpi_video_backlight_string))
49 acpi_video_support |= ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO; 48 acpi_backlight_cmdline = acpi_backlight_video;
49 if (!strcmp("native", acpi_video_backlight_string))
50 acpi_backlight_cmdline = acpi_backlight_native;
51 if (!strcmp("none", acpi_video_backlight_string))
52 acpi_backlight_cmdline = acpi_backlight_none;
50} 53}
51 54
52static acpi_status 55static acpi_status
@@ -77,7 +80,7 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
77 * buggy */ 80 * buggy */
78static int video_detect_force_vendor(const struct dmi_system_id *d) 81static int video_detect_force_vendor(const struct dmi_system_id *d)
79{ 82{
80 acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; 83 acpi_backlight_dmi = acpi_backlight_vendor;
81 return 0; 84 return 0;
82} 85}
83 86
@@ -125,99 +128,91 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
125}; 128};
126 129
127/* 130/*
128 * Returns the video capabilities of a specific ACPI graphics device 131 * Determine which type of backlight interface to use on this system,
132 * First check cmdline, then dmi quirks, then do autodetect.
133 *
134 * The autodetect order is:
135 * 1) Is the acpi-video backlight interface supported ->
136 * no, use a vendor interface
137 * 2) Is this a win8 "ready" BIOS and do we have a native interface ->
138 * yes, use a native interface
139 * 3) Else use the acpi-video interface
129 * 140 *
130 * if NULL is passed as argument all ACPI devices are enumerated and 141 * Arguably the native on win8 check should be done first, but that would
131 * all graphics capabilities of physically present devices are 142 * be a behavior change, which may causes issues.
132 * summarized and returned. This is cached and done only once.
133 */ 143 */
134static long acpi_video_get_capabilities(acpi_handle graphics_handle) 144enum acpi_backlight_type acpi_video_get_backlight_type(void)
135{ 145{
136 long caps = 0; 146 static DEFINE_MUTEX(init_mutex);
137 struct acpi_device *tmp_dev; 147 static bool init_done;
138 acpi_status status; 148 static long video_caps;
139
140 if (acpi_video_caps_checked && graphics_handle == NULL)
141 return acpi_video_support;
142
143 if (!graphics_handle) {
144 /* Only do the global walk through all graphics devices once */
145 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
146 ACPI_UINT32_MAX, find_video, NULL,
147 &caps, NULL);
148 /* There might be boot param flags set already... */
149 acpi_video_support |= caps;
150 acpi_video_caps_checked = 1;
151 /* Add blacklists here. Be careful to use the right *DMI* bits
152 * to still be able to override logic via boot params, e.g.:
153 *
154 * if (dmi_name_in_vendors("XY")) {
155 * acpi_video_support |=
156 * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
157 *}
158 */
159 149
150 /* Parse cmdline, dmi and acpi only once */
151 mutex_lock(&init_mutex);
152 if (!init_done) {
153 acpi_video_parse_cmdline();
160 dmi_check_system(video_detect_dmi_table); 154 dmi_check_system(video_detect_dmi_table);
161 } else { 155 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
162 status = acpi_bus_get_device(graphics_handle, &tmp_dev);
163 if (ACPI_FAILURE(status)) {
164 ACPI_EXCEPTION((AE_INFO, status, "Invalid device"));
165 return 0;
166 }
167 acpi_walk_namespace(ACPI_TYPE_DEVICE, graphics_handle,
168 ACPI_UINT32_MAX, find_video, NULL, 156 ACPI_UINT32_MAX, find_video, NULL,
169 &caps, NULL); 157 &video_caps, NULL);
158 init_done = true;
170 } 159 }
171 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support %s %s\n", 160 mutex_unlock(&init_mutex);
172 graphics_handle ? caps : acpi_video_support, 161
173 graphics_handle ? "on device " : "in general", 162 if (acpi_backlight_cmdline != acpi_backlight_undef)
174 graphics_handle ? acpi_device_bid(tmp_dev) : "")); 163 return acpi_backlight_cmdline;
175 return caps; 164
165 if (acpi_backlight_dmi != acpi_backlight_undef)
166 return acpi_backlight_dmi;
167
168 if (!(video_caps & ACPI_VIDEO_BACKLIGHT))
169 return acpi_backlight_vendor;
170
171 if (acpi_osi_is_win8() && backlight_device_registered(BACKLIGHT_RAW))
172 return acpi_backlight_native;
173
174 return acpi_backlight_video;
176} 175}
176EXPORT_SYMBOL(acpi_video_get_backlight_type);
177 177
178static void acpi_video_caps_check(void) 178/*
179 * Set the preferred backlight interface type based on DMI info.
180 * This function allows DMI blacklists to be implemented by external
181 * platform drivers instead of putting a big blacklist in video_detect.c
182 */
183void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type)
179{ 184{
180 /* 185 acpi_backlight_dmi = type;
181 * We must check whether the ACPI graphics device is physically plugged
182 * in. Therefore this must be called after binding PCI and ACPI devices
183 */
184 if (!acpi_video_caps_checked) {
185 acpi_video_parse_cmdline();
186 acpi_video_get_capabilities(NULL);
187 }
188} 186}
187EXPORT_SYMBOL(acpi_video_set_dmi_backlight_type);
189 188
190/* Promote the vendor interface instead of the generic video module. 189/*
191 * This function allow DMI blacklists to be implemented by externals 190 * Compatiblity function, this is going away as soon as all drivers are
192 * platform drivers instead of putting a big blacklist in video_detect.c 191 * converted to acpi_video_set_dmi_backlight_type().
192 *
193 * Promote the vendor interface instead of the generic video module.
193 * After calling this function you will probably want to call 194 * After calling this function you will probably want to call
194 * acpi_video_unregister() to make sure the video module is not loaded 195 * acpi_video_unregister() to make sure the video module is not loaded
195 */ 196 */
196void acpi_video_dmi_promote_vendor(void) 197void acpi_video_dmi_promote_vendor(void)
197{ 198{
198 acpi_video_caps_check(); 199 acpi_video_set_dmi_backlight_type(acpi_backlight_vendor);
199 acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
200} 200}
201EXPORT_SYMBOL(acpi_video_dmi_promote_vendor); 201EXPORT_SYMBOL(acpi_video_dmi_promote_vendor);
202 202
203/* Returns true if video.ko can do backlight switching */ 203/*
204 * Compatiblity function, this is going away as soon as all drivers are
205 * converted to acpi_video_get_backlight_type().
206 *
207 * Returns true if video.ko can do backlight switching.
208 */
204int acpi_video_backlight_support(void) 209int acpi_video_backlight_support(void)
205{ 210{
206 acpi_video_caps_check(); 211 /*
207 212 * This is done this way since vendor drivers call this to see
208 /* First check for boot param -> highest prio */ 213 * if they should load, and we do not want them to load for both
209 if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR) 214 * the acpi_backlight_video and acpi_backlight_native cases.
210 return 0; 215 */
211 else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO) 216 return acpi_video_get_backlight_type() != acpi_backlight_vendor;
212 return 1;
213
214 /* Then check for DMI blacklist -> second highest prio */
215 if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VENDOR)
216 return 0;
217 else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VIDEO)
218 return 1;
219
220 /* Then go the default way */
221 return acpi_video_support & ACPI_VIDEO_BACKLIGHT;
222} 217}
223EXPORT_SYMBOL(acpi_video_backlight_support); 218EXPORT_SYMBOL(acpi_video_backlight_support);