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

Configure Feed

Select the types of activity you want to include in your feed.

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

+137 -28
-13
drivers/acpi/acpica/aclocal.h
··· 931 931 932 932 /* Structs and definitions for _OSI support and I/O port validation */ 933 933 934 - #define ACPI_OSI_WIN_2000 0x01 935 - #define ACPI_OSI_WIN_XP 0x02 936 - #define ACPI_OSI_WIN_XP_SP1 0x03 937 - #define ACPI_OSI_WINSRV_2003 0x04 938 - #define ACPI_OSI_WIN_XP_SP2 0x05 939 - #define ACPI_OSI_WINSRV_2003_SP1 0x06 940 - #define ACPI_OSI_WIN_VISTA 0x07 941 - #define ACPI_OSI_WINSRV_2008 0x08 942 - #define ACPI_OSI_WIN_VISTA_SP1 0x09 943 - #define ACPI_OSI_WIN_VISTA_SP2 0x0A 944 - #define ACPI_OSI_WIN_7 0x0B 945 - #define ACPI_OSI_WIN_8 0x0C 946 - 947 934 #define ACPI_ALWAYS_ILLEGAL 0x00 948 935 949 936 struct acpi_interface_info {
+11
drivers/acpi/internal.h
··· 164 164 int acpi_create_platform_device(struct acpi_device *adev, 165 165 const struct acpi_device_id *id); 166 166 167 + /*-------------------------------------------------------------------------- 168 + Video 169 + -------------------------------------------------------------------------- */ 170 + #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) 171 + bool acpi_video_backlight_quirks(void); 172 + bool acpi_video_verify_backlight_support(void); 173 + #else 174 + static inline bool acpi_video_backlight_quirks(void) { return false; } 175 + static inline bool acpi_video_verify_backlight_support(void) { return false; } 176 + #endif 177 + 167 178 #endif /* _ACPI_INTERNAL_H_ */
+77 -13
drivers/acpi/video.c
··· 44 44 #include <linux/suspend.h> 45 45 #include <acpi/video.h> 46 46 47 + #include "internal.h" 48 + 47 49 #define PREFIX "ACPI: " 48 50 49 51 #define ACPI_VIDEO_BUS_NAME "Video Bus" ··· 908 906 device->cap._DDC = 1; 909 907 } 910 908 911 - if (acpi_video_backlight_support()) { 909 + if (acpi_video_init_brightness(device)) 910 + return; 911 + 912 + if (acpi_video_verify_backlight_support()) { 912 913 struct backlight_properties props; 913 914 struct pci_dev *pdev; 914 915 acpi_handle acpi_parent; ··· 920 915 static int count = 0; 921 916 char *name; 922 917 923 - result = acpi_video_init_brightness(device); 924 - if (result) 925 - return; 926 918 name = kasprintf(GFP_KERNEL, "acpi_video%d", count); 927 919 if (!name) 928 920 return; ··· 979 977 if (result) 980 978 printk(KERN_ERR PREFIX "Create sysfs link\n"); 981 979 980 + } else { 981 + /* Remove the brightness object. */ 982 + kfree(device->brightness->levels); 983 + kfree(device->brightness); 984 + device->brightness = NULL; 982 985 } 983 986 } 984 987 ··· 1366 1359 unsigned long long level_current, level_next; 1367 1360 int result = -EINVAL; 1368 1361 1369 - /* no warning message if acpi_backlight=vendor is used */ 1370 - if (!acpi_video_backlight_support()) 1362 + /* no warning message if acpi_backlight=vendor or a quirk is used */ 1363 + if (!acpi_video_verify_backlight_support()) 1371 1364 return 0; 1372 1365 1373 1366 if (!device->brightness) ··· 1547 1540 1548 1541 /* acpi_video interface */ 1549 1542 1543 + /* 1544 + * Win8 requires setting bit2 of _DOS to let firmware know it shouldn't 1545 + * preform any automatic brightness change on receiving a notification. 1546 + */ 1550 1547 static int acpi_video_bus_start_devices(struct acpi_video_bus *video) 1551 1548 { 1552 - return acpi_video_bus_DOS(video, 0, 0); 1549 + return acpi_video_bus_DOS(video, 0, 1550 + acpi_video_backlight_quirks() ? 1 : 0); 1553 1551 } 1554 1552 1555 1553 static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) 1556 1554 { 1557 - return acpi_video_bus_DOS(video, 0, 1); 1555 + return acpi_video_bus_DOS(video, 0, 1556 + acpi_video_backlight_quirks() ? 0 : 1); 1558 1557 } 1559 1558 1560 1559 static void acpi_video_bus_notify(struct acpi_device *device, u32 event) ··· 1875 1862 return 0; 1876 1863 } 1877 1864 1865 + static acpi_status video_unregister_backlight(acpi_handle handle, u32 lvl, 1866 + void *context, void **rv) 1867 + { 1868 + struct acpi_device *acpi_dev; 1869 + struct acpi_video_bus *video; 1870 + struct acpi_video_device *dev, *next; 1871 + 1872 + if (acpi_bus_get_device(handle, &acpi_dev)) 1873 + return AE_OK; 1874 + 1875 + if (acpi_match_device_ids(acpi_dev, video_device_ids)) 1876 + return AE_OK; 1877 + 1878 + video = acpi_driver_data(acpi_dev); 1879 + if (!video) 1880 + return AE_OK; 1881 + 1882 + acpi_video_bus_stop_devices(video); 1883 + mutex_lock(&video->device_list_lock); 1884 + list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { 1885 + if (dev->backlight) { 1886 + backlight_device_unregister(dev->backlight); 1887 + dev->backlight = NULL; 1888 + kfree(dev->brightness->levels); 1889 + kfree(dev->brightness); 1890 + } 1891 + if (dev->cooling_dev) { 1892 + sysfs_remove_link(&dev->dev->dev.kobj, 1893 + "thermal_cooling"); 1894 + sysfs_remove_link(&dev->cooling_dev->device.kobj, 1895 + "device"); 1896 + thermal_cooling_device_unregister(dev->cooling_dev); 1897 + dev->cooling_dev = NULL; 1898 + } 1899 + } 1900 + mutex_unlock(&video->device_list_lock); 1901 + acpi_video_bus_start_devices(video); 1902 + return AE_OK; 1903 + } 1904 + 1878 1905 static int __init is_i740(struct pci_dev *dev) 1879 1906 { 1880 1907 if (dev->device == 0x00D1) ··· 1946 1893 return opregion; 1947 1894 } 1948 1895 1949 - int acpi_video_register(void) 1896 + int __acpi_video_register(bool backlight_quirks) 1950 1897 { 1951 - int result = 0; 1898 + bool no_backlight; 1899 + int result; 1900 + 1901 + no_backlight = backlight_quirks ? acpi_video_backlight_quirks() : false; 1902 + 1952 1903 if (register_count) { 1953 1904 /* 1954 - * if the function of acpi_video_register is already called, 1955 - * don't register the acpi_vide_bus again and return no error. 1905 + * If acpi_video_register() has been called already, don't try 1906 + * to register acpi_video_bus, but unregister backlight devices 1907 + * if no backlight support is requested. 1956 1908 */ 1909 + if (no_backlight) 1910 + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 1911 + ACPI_UINT32_MAX, 1912 + video_unregister_backlight, 1913 + NULL, NULL, NULL); 1914 + 1957 1915 return 0; 1958 1916 } 1959 1917 ··· 1980 1916 1981 1917 return 0; 1982 1918 } 1983 - EXPORT_SYMBOL(acpi_video_register); 1919 + EXPORT_SYMBOL(__acpi_video_register); 1984 1920 1985 1921 void acpi_video_unregister(void) 1986 1922 {
+21
drivers/acpi/video_detect.c
··· 38 38 #include <linux/dmi.h> 39 39 #include <linux/pci.h> 40 40 41 + #include "internal.h" 42 + 41 43 #define PREFIX "ACPI: " 42 44 43 45 ACPI_MODULE_NAME("video"); ··· 236 234 acpi_video_get_capabilities(NULL); 237 235 } 238 236 237 + bool acpi_video_backlight_quirks(void) 238 + { 239 + if (acpi_gbl_osi_data >= ACPI_OSI_WIN_8) { 240 + acpi_video_caps_check(); 241 + acpi_video_support |= ACPI_VIDEO_SKIP_BACKLIGHT; 242 + return true; 243 + } 244 + return false; 245 + } 246 + EXPORT_SYMBOL(acpi_video_backlight_quirks); 247 + 239 248 /* Promote the vendor interface instead of the generic video module. 240 249 * This function allow DMI blacklists to be implemented by externals 241 250 * platform drivers instead of putting a big blacklist in video_detect.c ··· 290 277 return acpi_video_support & ACPI_VIDEO_BACKLIGHT; 291 278 } 292 279 EXPORT_SYMBOL(acpi_video_backlight_support); 280 + 281 + /* For the ACPI video driver use only. */ 282 + bool acpi_video_verify_backlight_support(void) 283 + { 284 + return (acpi_video_support & ACPI_VIDEO_SKIP_BACKLIGHT) ? 285 + false : acpi_video_backlight_support(); 286 + } 287 + EXPORT_SYMBOL(acpi_video_verify_backlight_support); 293 288 294 289 /* 295 290 * Use acpi_backlight=vendor/video to force that backlight switching
+1 -1
drivers/gpu/drm/i915/i915_dma.c
··· 1648 1648 if (INTEL_INFO(dev)->num_pipes) { 1649 1649 /* Must be done after probing outputs */ 1650 1650 intel_opregion_init(dev); 1651 - acpi_video_register(); 1651 + acpi_video_register_with_quirks(); 1652 1652 } 1653 1653 1654 1654 if (IS_GEN5(dev))
+1
include/acpi/acpixf.h
··· 62 62 extern struct acpi_table_fadt acpi_gbl_FADT; 63 63 extern u8 acpi_gbl_system_awake_and_running; 64 64 extern u8 acpi_gbl_reduced_hardware; /* ACPI 5.0 */ 65 + extern u8 acpi_gbl_osi_data; 65 66 66 67 /* Runtime configuration of debug print levels */ 67 68
+15
include/acpi/actypes.h
··· 1144 1144 #endif 1145 1145 }; 1146 1146 1147 + /* Definitions for _OSI support */ 1148 + 1149 + #define ACPI_OSI_WIN_2000 0x01 1150 + #define ACPI_OSI_WIN_XP 0x02 1151 + #define ACPI_OSI_WIN_XP_SP1 0x03 1152 + #define ACPI_OSI_WINSRV_2003 0x04 1153 + #define ACPI_OSI_WIN_XP_SP2 0x05 1154 + #define ACPI_OSI_WINSRV_2003_SP1 0x06 1155 + #define ACPI_OSI_WIN_VISTA 0x07 1156 + #define ACPI_OSI_WINSRV_2008 0x08 1157 + #define ACPI_OSI_WIN_VISTA_SP1 0x09 1158 + #define ACPI_OSI_WIN_VISTA_SP2 0x0A 1159 + #define ACPI_OSI_WIN_7 0x0B 1160 + #define ACPI_OSI_WIN_8 0x0C 1161 + 1147 1162 #endif /* __ACTYPES_H__ */
+10 -1
include/acpi/video.h
··· 17 17 #define ACPI_VIDEO_DISPLAY_LEGACY_TV 0x0200 18 18 19 19 #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) 20 - extern int acpi_video_register(void); 20 + extern int __acpi_video_register(bool backlight_quirks); 21 + static inline int acpi_video_register(void) 22 + { 23 + return __acpi_video_register(false); 24 + } 25 + static inline int acpi_video_register_with_quirks(void) 26 + { 27 + return __acpi_video_register(true); 28 + } 21 29 extern void acpi_video_unregister(void); 22 30 extern int acpi_video_get_edid(struct acpi_device *device, int type, 23 31 int device_id, void **edid); 24 32 #else 25 33 static inline int acpi_video_register(void) { return 0; } 34 + static inline int acpi_video_register_with_quirks(void) { return 0; } 26 35 static inline void acpi_video_unregister(void) { return; } 27 36 static inline int acpi_video_get_edid(struct acpi_device *device, int type, 28 37 int device_id, void **edid)
+1
include/linux/acpi.h
··· 191 191 #define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200 192 192 #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400 193 193 #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800 194 + #define ACPI_VIDEO_SKIP_BACKLIGHT 0x1000 194 195 195 196 #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) 196 197