mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 10:01:43 +00:00
ACPI video support fixes for 3.11
- Change from Aaron Lu makes ACPICA export a variable which can be used by driver code to determine whether or not the BIOS believes that we are compatible with Windows 8. - Change from Matthew Garrett makes the ACPI video driver initialize the ACPI backlight even if it is not going to be used afterward (that is needed for backlight control to work on Thinkpads). - Fix from Rafael J Wysocki implements Windows 8 backlight support workaround making i915 take over bakclight control if the firmware thinks it's dealing with Windows 8. Based on the work of multiple developers including Matthew Garrett, Chun-Yi Lee, Seth Forshee, and Aaron Lu. - Fix from Aaron Lu makes the kernel follow Windows 8 by informing the firmware through the _DOS method that it should not carry out automatic brightness changes, so that brightness can be controlled by GUI. / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJR6yY7AAoJEKhOf7ml8uNsbGUQAIVXwX8HF+9AOnqEIQYEaBiF HqfLDtHS5qobraK06auF/YmVaA17RdUnHssTuGiEbtIxpiUbuLPJaecZ9BeAf0Pz V4Y2IxF27aF9TDZrzkZXHcnYflzQ/kxj36eR9AmM2vSXmKZKxhfqLMeihVh2GgMv IlOs9PltK2GNX6C/CzjUQuUj4TYw8yxXsG93Gta0Z8scmxR7mpq9a9d0cPU/TjN/ iatIhZLFU8ujp8xFiG9MDeG948AtperLu3g0v1D4mPnkmDJTuyMuE3FiioKL2zMY 7jh6mDPkWUYdjdZkJcmyzgKZh5lAlZIJTZnJV6TrW5fjIpUz5F8XeD4ArMVU/u+A smro6XFcpgToRZTtmaEuraxzJHCS44FTjlXyH01FSIiN/Ll6YKyxDYsAzz4Z2sf6 X5BJofAAiRelZh/o1MaMQzs3QeTUo44TaboGr2zka0cQ37KK9+8YRGYqcWo/BvGs sicgFKMeA6SANxHnCVNTslQzMYFrPp4yyMEu4gD7EE+U7cG6FSVhVHQjjTO9CmBd ZnX2EDX0Uy+oHTQ9BkyjWAD7rXF6StnOm37FPWHNZ+HnplHEoQQAn+vXsSfl9tbO 7CPefZ/LQQEo1PZwLLkxruZ67NgxOd8/9I/aVjLUKgd8CDjez0UJVJ65gIXl1J4V kvaDy6faYTnUF8h/AYJf =vlwF -----END PGP SIGNATURE----- Merge tag 'acpi-video-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull ACPI video support fixes from Rafael Wysocki: "I'm sending a separate pull request for this as it may be somewhat controversial. The breakage addressed here is not really new and the fixes may not satisfy all users of the affected systems, but we've had so much back and forth dance in this area over the last several weeks that I think it's time to actually make some progress. The source of the problem is that about a year ago we started to tell BIOSes that we're compatible with Windows 8, which we really need to do, because some systems shipping with Windows 8 are tested with it and nothing else, so if we tell their BIOSes that we aren't compatible with Windows 8, we expose our users to untested BIOS/AML code paths. However, as it turns out, some Windows 8-specific AML code paths are not tested either, because Windows 8 actually doesn't use the ACPI methods containing them, so if we declare Windows 8 compatibility and attempt to use those ACPI methods, things break. That occurs mostly in the backlight support area where in particular the _BCM and _BQC methods are plain unusable on some systems if the OS declares Windows 8 compatibility. [ The additional twist is that they actually become usable if the OS says it is not compatible with Windows 8, but that may cause problems to show up elsewhere ] Investigation carried out by Matthew Garrett indicates that what Windows 8 does about backlight is to leave backlight control up to individual graphics drivers. At least there's evidence that it does that if the Intel graphics driver is used, so we've decided to follow Windows 8 in that respect and allow i915 to control backlight (Daniel likes that part). The first commit from Aaron Lu makes ACPICA export the variable from which we can infer whether or not the BIOS believes that we are compatible with Windows 8. The second commit from Matthew Garrett prepares the ACPI video driver by making it initialize the ACPI backlight even if it is not going to be used afterward (that is needed for backlight control to work on Thinkpads). The third commit implements the actual workaround making i915 take over backlight control if the firmware thinks it's dealing with Windows 8 and is based on the work of multiple developers, including Matthew Garrett, Chun-Yi Lee, Seth Forshee, and Aaron Lu. The final commit from Aaron Lu makes us follow Windows 8 by informing the firmware through the _DOS method that it should not carry out automatic brightness changes, so that brightness can be controlled by GUI. Hopefully, this approach will allow us to avoid using blacklists of systems that should not declare Windows 8 compatibility just to avoid backlight control problems in the future. - Change from Aaron Lu makes ACPICA export a variable which can be used by driver code to determine whether or not the BIOS believes that we are compatible with Windows 8. - Change from Matthew Garrett makes the ACPI video driver initialize the ACPI backlight even if it is not going to be used afterward (that is needed for backlight control to work on Thinkpads). - Fix from Rafael J Wysocki implements Windows 8 backlight support workaround making i915 take over bakclight control if the firmware thinks it's dealing with Windows 8. Based on the work of multiple developers including Matthew Garrett, Chun-Yi Lee, Seth Forshee, and Aaron Lu. - Fix from Aaron Lu makes the kernel follow Windows 8 by informing the firmware through the _DOS method that it should not carry out automatic brightness changes, so that brightness can be controlled by GUI" * tag 'acpi-video-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / video: no automatic brightness changes by win8-compatible firmware ACPI / video / i915: No ACPI backlight if firmware expects Windows 8 ACPI / video: Always call acpi_video_init_brightness() on init ACPICA: expose OSI version
This commit is contained in:
commit
ea45ea70b6
@ -931,19 +931,6 @@ struct acpi_bit_register_info {
|
||||
|
||||
/* Structs and definitions for _OSI support and I/O port validation */
|
||||
|
||||
#define ACPI_OSI_WIN_2000 0x01
|
||||
#define ACPI_OSI_WIN_XP 0x02
|
||||
#define ACPI_OSI_WIN_XP_SP1 0x03
|
||||
#define ACPI_OSI_WINSRV_2003 0x04
|
||||
#define ACPI_OSI_WIN_XP_SP2 0x05
|
||||
#define ACPI_OSI_WINSRV_2003_SP1 0x06
|
||||
#define ACPI_OSI_WIN_VISTA 0x07
|
||||
#define ACPI_OSI_WINSRV_2008 0x08
|
||||
#define ACPI_OSI_WIN_VISTA_SP1 0x09
|
||||
#define ACPI_OSI_WIN_VISTA_SP2 0x0A
|
||||
#define ACPI_OSI_WIN_7 0x0B
|
||||
#define ACPI_OSI_WIN_8 0x0C
|
||||
|
||||
#define ACPI_ALWAYS_ILLEGAL 0x00
|
||||
|
||||
struct acpi_interface_info {
|
||||
|
@ -164,4 +164,15 @@ struct platform_device;
|
||||
int acpi_create_platform_device(struct acpi_device *adev,
|
||||
const struct acpi_device_id *id);
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Video
|
||||
-------------------------------------------------------------------------- */
|
||||
#if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
|
||||
bool acpi_video_backlight_quirks(void);
|
||||
bool acpi_video_verify_backlight_support(void);
|
||||
#else
|
||||
static inline bool acpi_video_backlight_quirks(void) { return false; }
|
||||
static inline bool acpi_video_verify_backlight_support(void) { return false; }
|
||||
#endif
|
||||
|
||||
#endif /* _ACPI_INTERNAL_H_ */
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include <linux/suspend.h>
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
#define ACPI_VIDEO_BUS_NAME "Video Bus"
|
||||
@ -906,7 +908,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
|
||||
device->cap._DDC = 1;
|
||||
}
|
||||
|
||||
if (acpi_video_backlight_support()) {
|
||||
if (acpi_video_init_brightness(device))
|
||||
return;
|
||||
|
||||
if (acpi_video_verify_backlight_support()) {
|
||||
struct backlight_properties props;
|
||||
struct pci_dev *pdev;
|
||||
acpi_handle acpi_parent;
|
||||
@ -915,9 +920,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
|
||||
static int count = 0;
|
||||
char *name;
|
||||
|
||||
result = acpi_video_init_brightness(device);
|
||||
if (result)
|
||||
return;
|
||||
name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
|
||||
if (!name)
|
||||
return;
|
||||
@ -977,6 +979,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
|
||||
if (result)
|
||||
printk(KERN_ERR PREFIX "Create sysfs link\n");
|
||||
|
||||
} else {
|
||||
/* Remove the brightness object. */
|
||||
kfree(device->brightness->levels);
|
||||
kfree(device->brightness);
|
||||
device->brightness = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1359,8 +1366,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
|
||||
unsigned long long level_current, level_next;
|
||||
int result = -EINVAL;
|
||||
|
||||
/* no warning message if acpi_backlight=vendor is used */
|
||||
if (!acpi_video_backlight_support())
|
||||
/* no warning message if acpi_backlight=vendor or a quirk is used */
|
||||
if (!acpi_video_verify_backlight_support())
|
||||
return 0;
|
||||
|
||||
if (!device->brightness)
|
||||
@ -1540,14 +1547,20 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
|
||||
|
||||
/* acpi_video interface */
|
||||
|
||||
/*
|
||||
* Win8 requires setting bit2 of _DOS to let firmware know it shouldn't
|
||||
* preform any automatic brightness change on receiving a notification.
|
||||
*/
|
||||
static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
|
||||
{
|
||||
return acpi_video_bus_DOS(video, 0, 0);
|
||||
return acpi_video_bus_DOS(video, 0,
|
||||
acpi_video_backlight_quirks() ? 1 : 0);
|
||||
}
|
||||
|
||||
static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
|
||||
{
|
||||
return acpi_video_bus_DOS(video, 0, 1);
|
||||
return acpi_video_bus_DOS(video, 0,
|
||||
acpi_video_backlight_quirks() ? 0 : 1);
|
||||
}
|
||||
|
||||
static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
|
||||
@ -1862,6 +1875,46 @@ static int acpi_video_bus_remove(struct acpi_device *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static acpi_status video_unregister_backlight(acpi_handle handle, u32 lvl,
|
||||
void *context, void **rv)
|
||||
{
|
||||
struct acpi_device *acpi_dev;
|
||||
struct acpi_video_bus *video;
|
||||
struct acpi_video_device *dev, *next;
|
||||
|
||||
if (acpi_bus_get_device(handle, &acpi_dev))
|
||||
return AE_OK;
|
||||
|
||||
if (acpi_match_device_ids(acpi_dev, video_device_ids))
|
||||
return AE_OK;
|
||||
|
||||
video = acpi_driver_data(acpi_dev);
|
||||
if (!video)
|
||||
return AE_OK;
|
||||
|
||||
acpi_video_bus_stop_devices(video);
|
||||
mutex_lock(&video->device_list_lock);
|
||||
list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
|
||||
if (dev->backlight) {
|
||||
backlight_device_unregister(dev->backlight);
|
||||
dev->backlight = NULL;
|
||||
kfree(dev->brightness->levels);
|
||||
kfree(dev->brightness);
|
||||
}
|
||||
if (dev->cooling_dev) {
|
||||
sysfs_remove_link(&dev->dev->dev.kobj,
|
||||
"thermal_cooling");
|
||||
sysfs_remove_link(&dev->cooling_dev->device.kobj,
|
||||
"device");
|
||||
thermal_cooling_device_unregister(dev->cooling_dev);
|
||||
dev->cooling_dev = NULL;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&video->device_list_lock);
|
||||
acpi_video_bus_start_devices(video);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int __init is_i740(struct pci_dev *dev)
|
||||
{
|
||||
if (dev->device == 0x00D1)
|
||||
@ -1893,14 +1946,25 @@ static int __init intel_opregion_present(void)
|
||||
return opregion;
|
||||
}
|
||||
|
||||
int acpi_video_register(void)
|
||||
int __acpi_video_register(bool backlight_quirks)
|
||||
{
|
||||
int result = 0;
|
||||
bool no_backlight;
|
||||
int result;
|
||||
|
||||
no_backlight = backlight_quirks ? acpi_video_backlight_quirks() : false;
|
||||
|
||||
if (register_count) {
|
||||
/*
|
||||
* if the function of acpi_video_register is already called,
|
||||
* don't register the acpi_vide_bus again and return no error.
|
||||
* If acpi_video_register() has been called already, don't try
|
||||
* to register acpi_video_bus, but unregister backlight devices
|
||||
* if no backlight support is requested.
|
||||
*/
|
||||
if (no_backlight)
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
video_unregister_backlight,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1916,7 +1980,7 @@ int acpi_video_register(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_register);
|
||||
EXPORT_SYMBOL(__acpi_video_register);
|
||||
|
||||
void acpi_video_unregister(void)
|
||||
{
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
ACPI_MODULE_NAME("video");
|
||||
@ -234,6 +236,17 @@ static void acpi_video_caps_check(void)
|
||||
acpi_video_get_capabilities(NULL);
|
||||
}
|
||||
|
||||
bool acpi_video_backlight_quirks(void)
|
||||
{
|
||||
if (acpi_gbl_osi_data >= ACPI_OSI_WIN_8) {
|
||||
acpi_video_caps_check();
|
||||
acpi_video_support |= ACPI_VIDEO_SKIP_BACKLIGHT;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_backlight_quirks);
|
||||
|
||||
/* Promote the vendor interface instead of the generic video module.
|
||||
* This function allow DMI blacklists to be implemented by externals
|
||||
* platform drivers instead of putting a big blacklist in video_detect.c
|
||||
@ -278,6 +291,14 @@ int acpi_video_backlight_support(void)
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_backlight_support);
|
||||
|
||||
/* For the ACPI video driver use only. */
|
||||
bool acpi_video_verify_backlight_support(void)
|
||||
{
|
||||
return (acpi_video_support & ACPI_VIDEO_SKIP_BACKLIGHT) ?
|
||||
false : acpi_video_backlight_support();
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_verify_backlight_support);
|
||||
|
||||
/*
|
||||
* Use acpi_backlight=vendor/video to force that backlight switching
|
||||
* is processed by vendor specific acpi drivers or video.ko driver.
|
||||
|
@ -1648,7 +1648,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
if (INTEL_INFO(dev)->num_pipes) {
|
||||
/* Must be done after probing outputs */
|
||||
intel_opregion_init(dev);
|
||||
acpi_video_register();
|
||||
acpi_video_register_with_quirks();
|
||||
}
|
||||
|
||||
if (IS_GEN5(dev))
|
||||
|
@ -62,6 +62,7 @@ extern u32 acpi_current_gpe_count;
|
||||
extern struct acpi_table_fadt acpi_gbl_FADT;
|
||||
extern u8 acpi_gbl_system_awake_and_running;
|
||||
extern u8 acpi_gbl_reduced_hardware; /* ACPI 5.0 */
|
||||
extern u8 acpi_gbl_osi_data;
|
||||
|
||||
/* Runtime configuration of debug print levels */
|
||||
|
||||
|
@ -1144,4 +1144,19 @@ struct acpi_memory_list {
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Definitions for _OSI support */
|
||||
|
||||
#define ACPI_OSI_WIN_2000 0x01
|
||||
#define ACPI_OSI_WIN_XP 0x02
|
||||
#define ACPI_OSI_WIN_XP_SP1 0x03
|
||||
#define ACPI_OSI_WINSRV_2003 0x04
|
||||
#define ACPI_OSI_WIN_XP_SP2 0x05
|
||||
#define ACPI_OSI_WINSRV_2003_SP1 0x06
|
||||
#define ACPI_OSI_WIN_VISTA 0x07
|
||||
#define ACPI_OSI_WINSRV_2008 0x08
|
||||
#define ACPI_OSI_WIN_VISTA_SP1 0x09
|
||||
#define ACPI_OSI_WIN_VISTA_SP2 0x0A
|
||||
#define ACPI_OSI_WIN_7 0x0B
|
||||
#define ACPI_OSI_WIN_8 0x0C
|
||||
|
||||
#endif /* __ACTYPES_H__ */
|
||||
|
@ -17,12 +17,21 @@ struct acpi_device;
|
||||
#define ACPI_VIDEO_DISPLAY_LEGACY_TV 0x0200
|
||||
|
||||
#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
|
||||
extern int acpi_video_register(void);
|
||||
extern int __acpi_video_register(bool backlight_quirks);
|
||||
static inline int acpi_video_register(void)
|
||||
{
|
||||
return __acpi_video_register(false);
|
||||
}
|
||||
static inline int acpi_video_register_with_quirks(void)
|
||||
{
|
||||
return __acpi_video_register(true);
|
||||
}
|
||||
extern void acpi_video_unregister(void);
|
||||
extern int acpi_video_get_edid(struct acpi_device *device, int type,
|
||||
int device_id, void **edid);
|
||||
#else
|
||||
static inline int acpi_video_register(void) { return 0; }
|
||||
static inline int acpi_video_register_with_quirks(void) { return 0; }
|
||||
static inline void acpi_video_unregister(void) { return; }
|
||||
static inline int acpi_video_get_edid(struct acpi_device *device, int type,
|
||||
int device_id, void **edid)
|
||||
|
@ -191,6 +191,7 @@ extern bool wmi_has_guid(const char *guid);
|
||||
#define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200
|
||||
#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400
|
||||
#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800
|
||||
#define ACPI_VIDEO_SKIP_BACKLIGHT 0x1000
|
||||
|
||||
#if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user