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

Merge tag 'backlight-detect-refactor-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86 into drm-misc-next

Immutable backlight-detect-refactor branch between acpi, drm-* and pdx86

Tag (immutable branch) with v6.0-rc1 + the (acpi/x86) backlight
detect refactor work. For merging into the acpi, drm-* and pdx86
subsystems.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmMVsogUHGhkZWdvZWRl
# QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9yy6wgAlig+7hkq940L62lTpj0g2gNQv8zc
# HCsMpnU7dnJcZYaEvIjouZhf33ZbN52c0fQq2JWjt7fFX04LLyIiyrJ26Lc293JR
# ++yXpJcVoewRGqApy/P3Z05TKUCLll5bexvK4t8isnhOtEXD/nDPWKTLIV2Kd1DK
# nLY4KgRznXZ85RhYheUEdidZ7Lwlzt1JVBMq7tpnzu3nVdDExyZmqlqCUITcLynu
# ysuASQGr0D2i+1vb9eifHIA3xsQO0S37Bv62aBMBKxB6B8Fz1DYr8VA2YvoT82Hv
# IFT0hzCCZ/63Ljga05O78TwraxAQX0RvZWqjqGgnZg6fIBh2hxUiqeQY6g==
# =SA1R
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 05 Sep 2022 09:25:44 AM IST
# gpg: using RSA key BAF03B5D2718411A5E9E177E92EC4779440327DC
# gpg: issuer "hdegoede@redhat.com"
# gpg: Can't check signature: No public key
From: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/261afe3d-7790-e945-adf6-a2c96c9b1eff@redhat.com

+594 -513
+68
Documentation/gpu/todo.rst
··· 679 679 680 680 Level: Advanced 681 681 682 + Brightness handling on devices with multiple internal panels 683 + ============================================================ 684 + 685 + On x86/ACPI devices there can be multiple backlight firmware interfaces: 686 + (ACPI) video, vendor specific and others. As well as direct/native (PWM) 687 + register programming by the KMS driver. 688 + 689 + To deal with this backlight drivers used on x86/ACPI call 690 + acpi_video_get_backlight_type() which has heuristics (+quirks) to select 691 + which backlight interface to use; and backlight drivers which do not match 692 + the returned type will not register themselves, so that only one backlight 693 + device gets registered (in a single GPU setup, see below). 694 + 695 + At the moment this more or less assumes that there will only 696 + be 1 (internal) panel on a system. 697 + 698 + On systems with 2 panels this may be a problem, depending on 699 + what interface acpi_video_get_backlight_type() selects: 700 + 701 + 1. native: in this case the KMS driver is expected to know which backlight 702 + device belongs to which output so everything should just work. 703 + 2. video: this does support controlling multiple backlights, but some work 704 + will need to be done to get the output <-> backlight device mapping 705 + 706 + The above assumes both panels will require the same backlight interface type. 707 + Things will break on systems with multiple panels where the 2 panels need 708 + a different type of control. E.g. one panel needs ACPI video backlight control, 709 + where as the other is using native backlight control. Currently in this case 710 + only one of the 2 required backlight devices will get registered, based on 711 + the acpi_video_get_backlight_type() return value. 712 + 713 + If this (theoretical) case ever shows up, then supporting this will need some 714 + work. A possible solution here would be to pass a device and connector-name 715 + to acpi_video_get_backlight_type() so that it can deal with this. 716 + 717 + Note in a way we already have a case where userspace sees 2 panels, 718 + in dual GPU laptop setups with a mux. On those systems we may see 719 + either 2 native backlight devices; or 2 native backlight devices. 720 + 721 + Userspace already has code to deal with this by detecting if the related 722 + panel is active (iow which way the mux between the GPU and the panels 723 + points) and then uses that backlight device. Userspace here very much 724 + assumes a single panel though. It picks only 1 of the 2 backlight devices 725 + and then only uses that one. 726 + 727 + Note that all userspace code (that I know off) is currently hardcoded 728 + to assume a single panel. 729 + 730 + Before the recent changes to not register multiple (e.g. video + native) 731 + /sys/class/backlight devices for a single panel (on a single GPU laptop), 732 + userspace would see multiple backlight devices all controlling the same 733 + backlight. 734 + 735 + To deal with this userspace had to always picks one preferred device under 736 + /sys/class/backlight and will ignore the others. So to support brightness 737 + control on multiple panels userspace will need to be updated too. 738 + 739 + There are plans to allow brightness control through the KMS API by adding 740 + a "display brightness" property to drm_connector objects for panels. This 741 + solves a number of issues with the /sys/class/backlight API, including not 742 + being able to map a sysfs backlight device to a specific connector. Any 743 + userspace changes to add support for brightness control on devices with 744 + multiple panels really should build on top of this new KMS property. 745 + 746 + Contact: Hans de Goede 747 + 748 + Level: Advanced 749 + 682 750 Outside DRM 683 751 =========== 684 752
+1
MAINTAINERS
··· 14532 14532 L: platform-driver-x86@vger.kernel.org 14533 14533 S: Supported 14534 14534 F: drivers/platform/x86/nvidia-wmi-ec-backlight.c 14535 + F: include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h 14535 14536 14536 14537 NVM EXPRESS DRIVER 14537 14538 M: Keith Busch <kbusch@kernel.org>
+1
drivers/acpi/Kconfig
··· 212 212 tristate "Video" 213 213 depends on BACKLIGHT_CLASS_DEVICE 214 214 depends on INPUT 215 + depends on ACPI_WMI || !X86 215 216 select THERMAL 216 217 help 217 218 This driver implements the ACPI Extensions For Display Adapters
+46 -18
drivers/acpi/acpi_video.c
··· 73 73 static int only_lcd = -1; 74 74 module_param(only_lcd, int, 0444); 75 75 76 + /* 77 + * Display probing is known to take up to 5 seconds, so delay the fallback 78 + * backlight registration by 5 seconds + 3 seconds for some extra margin. 79 + */ 80 + static int register_backlight_delay = 8; 81 + module_param(register_backlight_delay, int, 0444); 82 + MODULE_PARM_DESC(register_backlight_delay, 83 + "Delay in seconds before doing fallback (non GPU driver triggered) " 84 + "backlight registration, set to 0 to disable."); 85 + 76 86 static bool may_report_brightness_keys; 77 87 static int register_count; 78 88 static DEFINE_MUTEX(register_count_mutex); ··· 91 81 static int acpi_video_bus_add(struct acpi_device *device); 92 82 static int acpi_video_bus_remove(struct acpi_device *device); 93 83 static void acpi_video_bus_notify(struct acpi_device *device, u32 event); 94 - void acpi_video_detect_exit(void); 84 + static void acpi_video_bus_register_backlight_work(struct work_struct *ignored); 85 + static DECLARE_DELAYED_WORK(video_bus_register_backlight_work, 86 + acpi_video_bus_register_backlight_work); 95 87 96 88 /* 97 89 * Indices in the _BCL method response: the first two items are special, ··· 1871 1859 if (video->backlight_registered) 1872 1860 return 0; 1873 1861 1874 - acpi_video_run_bcl_for_osi(video); 1875 - 1876 1862 if (acpi_video_get_backlight_type() != acpi_backlight_video) 1877 1863 return 0; 1878 1864 ··· 2096 2086 list_add_tail(&video->entry, &video_bus_head); 2097 2087 mutex_unlock(&video_list_lock); 2098 2088 2099 - acpi_video_bus_register_backlight(video); 2089 + /* 2090 + * The userspace visible backlight_device gets registered separately 2091 + * from acpi_video_register_backlight(). 2092 + */ 2093 + acpi_video_run_bcl_for_osi(video); 2100 2094 acpi_video_bus_add_notify_handler(video); 2101 2095 2102 2096 return 0; ··· 2125 2111 2126 2112 video = acpi_driver_data(device); 2127 2113 2128 - acpi_video_bus_remove_notify_handler(video); 2129 - acpi_video_bus_unregister_backlight(video); 2130 - acpi_video_bus_put_devices(video); 2131 - 2132 2114 mutex_lock(&video_list_lock); 2133 2115 list_del(&video->entry); 2134 2116 mutex_unlock(&video_list_lock); 2117 + 2118 + acpi_video_bus_remove_notify_handler(video); 2119 + acpi_video_bus_unregister_backlight(video); 2120 + acpi_video_bus_put_devices(video); 2135 2121 2136 2122 kfree(video->attached_array); 2137 2123 kfree(video); 2138 2124 2139 2125 return 0; 2126 + } 2127 + 2128 + static void acpi_video_bus_register_backlight_work(struct work_struct *ignored) 2129 + { 2130 + acpi_video_register_backlight(); 2140 2131 } 2141 2132 2142 2133 static int __init is_i740(struct pci_dev *dev) ··· 2254 2235 */ 2255 2236 register_count = 1; 2256 2237 2238 + /* 2239 + * acpi_video_bus_add() skips registering the userspace visible 2240 + * backlight_device. The intend is for this to be registered by the 2241 + * drm/kms driver calling acpi_video_register_backlight() *after* it is 2242 + * done setting up its own native backlight device. The delayed work 2243 + * ensures that acpi_video_register_backlight() always gets called 2244 + * eventually, in case there is no drm/kms driver or it is disabled. 2245 + */ 2246 + if (register_backlight_delay) 2247 + schedule_delayed_work(&video_bus_register_backlight_work, 2248 + register_backlight_delay * HZ); 2249 + 2257 2250 leave: 2258 2251 mutex_unlock(&register_count_mutex); 2259 2252 return ret; ··· 2276 2245 { 2277 2246 mutex_lock(&register_count_mutex); 2278 2247 if (register_count) { 2248 + cancel_delayed_work_sync(&video_bus_register_backlight_work); 2279 2249 acpi_bus_unregister_driver(&acpi_video_bus); 2280 2250 register_count = 0; 2281 2251 may_report_brightness_keys = false; ··· 2285 2253 } 2286 2254 EXPORT_SYMBOL(acpi_video_unregister); 2287 2255 2288 - void acpi_video_unregister_backlight(void) 2256 + void acpi_video_register_backlight(void) 2289 2257 { 2290 2258 struct acpi_video_bus *video; 2291 2259 2292 - mutex_lock(&register_count_mutex); 2293 - if (register_count) { 2294 - mutex_lock(&video_list_lock); 2295 - list_for_each_entry(video, &video_bus_head, entry) 2296 - acpi_video_bus_unregister_backlight(video); 2297 - mutex_unlock(&video_list_lock); 2298 - } 2299 - mutex_unlock(&register_count_mutex); 2260 + mutex_lock(&video_list_lock); 2261 + list_for_each_entry(video, &video_bus_head, entry) 2262 + acpi_video_bus_register_backlight(video); 2263 + mutex_unlock(&video_list_lock); 2300 2264 } 2265 + EXPORT_SYMBOL(acpi_video_register_backlight); 2301 2266 2302 2267 bool acpi_video_handles_brightness_key_presses(void) 2303 2268 { ··· 2331 2302 2332 2303 static void __exit acpi_video_exit(void) 2333 2304 { 2334 - acpi_video_detect_exit(); 2335 2305 acpi_video_unregister(); 2336 2306 } 2337 2307
+260 -180
drivers/acpi/video_detect.c
··· 17 17 * Otherwise vendor specific drivers like thinkpad_acpi, asus-laptop, 18 18 * sony_acpi,... can take care about backlight brightness. 19 19 * 20 - * Backlight drivers can use acpi_video_get_backlight_type() to determine 21 - * which driver should handle the backlight. 20 + * Backlight drivers can use acpi_video_get_backlight_type() to determine which 21 + * driver should handle the backlight. RAW/GPU-driver backlight drivers must 22 + * use the acpi_video_backlight_use_native() helper for this. 22 23 * 23 24 * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m) 24 25 * this file will not be compiled and acpi_video_get_backlight_type() will ··· 28 27 29 28 #include <linux/export.h> 30 29 #include <linux/acpi.h> 30 + #include <linux/apple-gmux.h> 31 31 #include <linux/backlight.h> 32 32 #include <linux/dmi.h> 33 33 #include <linux/module.h> 34 34 #include <linux/pci.h> 35 + #include <linux/platform_data/x86/nvidia-wmi-ec-backlight.h> 35 36 #include <linux/types.h> 36 37 #include <linux/workqueue.h> 37 38 #include <acpi/video.h> 38 - 39 - void acpi_video_unregister_backlight(void); 40 - 41 - static bool backlight_notifier_registered; 42 - static struct notifier_block backlight_nb; 43 - static struct work_struct backlight_notify_work; 44 39 45 40 static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef; 46 41 static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef; ··· 75 78 return AE_OK; 76 79 } 77 80 81 + /* This depends on ACPI_WMI which is X86 only */ 82 + #ifdef CONFIG_X86 83 + static bool nvidia_wmi_ec_supported(void) 84 + { 85 + struct wmi_brightness_args args = { 86 + .mode = WMI_BRIGHTNESS_MODE_GET, 87 + .val = 0, 88 + .ret = 0, 89 + }; 90 + struct acpi_buffer buf = { (acpi_size)sizeof(args), &args }; 91 + acpi_status status; 92 + 93 + status = wmi_evaluate_method(WMI_BRIGHTNESS_GUID, 0, 94 + WMI_BRIGHTNESS_METHOD_SOURCE, &buf, &buf); 95 + if (ACPI_FAILURE(status)) 96 + return false; 97 + 98 + /* 99 + * If brightness is handled by the EC then nvidia-wmi-ec-backlight 100 + * should be used, else the GPU driver(s) should be used. 101 + */ 102 + return args.ret == WMI_BRIGHTNESS_SOURCE_EC; 103 + } 104 + #else 105 + static bool nvidia_wmi_ec_supported(void) 106 + { 107 + return false; 108 + } 109 + #endif 110 + 78 111 /* Force to use vendor driver when the ACPI device is known to be 79 112 * buggy */ 80 113 static int video_detect_force_vendor(const struct dmi_system_id *d) ··· 132 105 } 133 106 134 107 static const struct dmi_system_id video_detect_dmi_table[] = { 135 - /* On Samsung X360, the BIOS will set a flag (VDRV) if generic 136 - * ACPI backlight device is used. This flag will definitively break 137 - * the backlight interface (even the vendor interface) until next 138 - * reboot. It's why we should prevent video.ko from being used here 139 - * and we can't rely on a later call to acpi_video_unregister(). 140 - */ 141 108 { 109 + /* https://bugzilla.redhat.com/show_bug.cgi?id=1128309 */ 142 110 .callback = video_detect_force_vendor, 143 - /* X360 */ 111 + /* Acer KAV80 */ 144 112 .matches = { 145 - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 146 - DMI_MATCH(DMI_PRODUCT_NAME, "X360"), 147 - DMI_MATCH(DMI_BOARD_NAME, "X360"), 113 + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 114 + DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"), 148 115 }, 149 116 }, 150 117 { 151 - .callback = video_detect_force_vendor, 152 - /* Asus UL30VT */ 153 - .matches = { 118 + .callback = video_detect_force_vendor, 119 + /* Asus UL30VT */ 120 + .matches = { 154 121 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), 155 122 DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"), 156 123 }, 157 124 }, 158 125 { 159 - .callback = video_detect_force_vendor, 160 - /* Asus UL30A */ 161 - .matches = { 126 + .callback = video_detect_force_vendor, 127 + /* Asus UL30A */ 128 + .matches = { 162 129 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), 163 130 DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), 164 131 }, 165 132 }, 166 133 { 167 - .callback = video_detect_force_vendor, 168 - /* GIGABYTE GB-BXBT-2807 */ 169 - .matches = { 134 + .callback = video_detect_force_vendor, 135 + /* Asus X55U */ 136 + .matches = { 137 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 138 + DMI_MATCH(DMI_PRODUCT_NAME, "X55U"), 139 + }, 140 + }, 141 + { 142 + .callback = video_detect_force_vendor, 143 + /* Asus X101CH */ 144 + .matches = { 145 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 146 + DMI_MATCH(DMI_PRODUCT_NAME, "X101CH"), 147 + }, 148 + }, 149 + { 150 + .callback = video_detect_force_vendor, 151 + /* Asus X401U */ 152 + .matches = { 153 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 154 + DMI_MATCH(DMI_PRODUCT_NAME, "X401U"), 155 + }, 156 + }, 157 + { 158 + .callback = video_detect_force_vendor, 159 + /* Asus X501U */ 160 + .matches = { 161 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 162 + DMI_MATCH(DMI_PRODUCT_NAME, "X501U"), 163 + }, 164 + }, 165 + { 166 + .callback = video_detect_force_vendor, 167 + /* Asus 1015CX */ 168 + .matches = { 169 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 170 + DMI_MATCH(DMI_PRODUCT_NAME, "1015CX"), 171 + }, 172 + }, 173 + { 174 + .callback = video_detect_force_vendor, 175 + /* GIGABYTE GB-BXBT-2807 */ 176 + .matches = { 170 177 DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), 171 178 DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"), 172 179 }, 173 180 }, 174 181 { 175 - .callback = video_detect_force_vendor, 176 - /* Sony VPCEH3U1E */ 177 - .matches = { 182 + .callback = video_detect_force_vendor, 183 + /* Samsung N150/N210/N220 */ 184 + .matches = { 185 + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 186 + DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"), 187 + DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"), 188 + }, 189 + }, 190 + { 191 + .callback = video_detect_force_vendor, 192 + /* Samsung NF110/NF210/NF310 */ 193 + .matches = { 194 + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 195 + DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"), 196 + DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"), 197 + }, 198 + }, 199 + { 200 + .callback = video_detect_force_vendor, 201 + /* Samsung NC210 */ 202 + .matches = { 203 + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 204 + DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"), 205 + DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"), 206 + }, 207 + }, 208 + { 209 + .callback = video_detect_force_vendor, 210 + /* Sony VPCEH3U1E */ 211 + .matches = { 178 212 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 179 213 DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"), 180 214 }, 181 215 }, 182 216 { 183 - .callback = video_detect_force_vendor, 184 - /* Xiaomi Mi Pad 2 */ 185 - .matches = { 217 + .callback = video_detect_force_vendor, 218 + /* Xiaomi Mi Pad 2 */ 219 + .matches = { 186 220 DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), 187 221 DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), 222 + }, 223 + }, 224 + 225 + /* 226 + * Toshiba models with Transflective display, these need to use 227 + * the toshiba_acpi vendor driver for proper Transflective handling. 228 + */ 229 + { 230 + .callback = video_detect_force_vendor, 231 + .matches = { 232 + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 233 + DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R500"), 234 + }, 235 + }, 236 + { 237 + .callback = video_detect_force_vendor, 238 + .matches = { 239 + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 240 + DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R600"), 188 241 }, 189 242 }, 190 243 ··· 497 390 }, 498 391 }, 499 392 { 393 + /* https://bugzilla.redhat.com/show_bug.cgi?id=1012674 */ 394 + .callback = video_detect_force_native, 395 + /* Acer Aspire 5741 */ 396 + .matches = { 397 + DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 398 + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"), 399 + }, 400 + }, 401 + { 402 + /* https://bugzilla.kernel.org/show_bug.cgi?id=42993 */ 403 + .callback = video_detect_force_native, 404 + /* Acer Aspire 5750 */ 405 + .matches = { 406 + DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 407 + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), 408 + }, 409 + }, 410 + { 411 + /* https://bugzilla.kernel.org/show_bug.cgi?id=42833 */ 412 + .callback = video_detect_force_native, 413 + /* Acer Extensa 5235 */ 414 + .matches = { 415 + DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 416 + DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"), 417 + }, 418 + }, 419 + { 420 + .callback = video_detect_force_native, 421 + /* Acer TravelMate 4750 */ 422 + .matches = { 423 + DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 424 + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"), 425 + }, 426 + }, 427 + { 500 428 /* https://bugzilla.kernel.org/show_bug.cgi?id=207835 */ 501 429 .callback = video_detect_force_native, 502 430 /* Acer TravelMate 5735Z */ ··· 542 400 }, 543 401 }, 544 402 { 545 - .callback = video_detect_force_native, 546 - /* ASUSTeK COMPUTER INC. GA401 */ 547 - .matches = { 403 + /* https://bugzilla.kernel.org/show_bug.cgi?id=36322 */ 404 + .callback = video_detect_force_native, 405 + /* Acer TravelMate 5760 */ 406 + .matches = { 407 + DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 408 + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"), 409 + }, 410 + }, 411 + { 412 + .callback = video_detect_force_native, 413 + /* ASUSTeK COMPUTER INC. GA401 */ 414 + .matches = { 548 415 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 549 416 DMI_MATCH(DMI_PRODUCT_NAME, "GA401"), 550 417 }, 551 418 }, 552 419 { 553 - .callback = video_detect_force_native, 554 - /* ASUSTeK COMPUTER INC. GA502 */ 555 - .matches = { 420 + .callback = video_detect_force_native, 421 + /* ASUSTeK COMPUTER INC. GA502 */ 422 + .matches = { 556 423 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 557 424 DMI_MATCH(DMI_PRODUCT_NAME, "GA502"), 558 425 }, 559 426 }, 560 427 { 561 - .callback = video_detect_force_native, 562 - /* ASUSTeK COMPUTER INC. GA503 */ 563 - .matches = { 428 + .callback = video_detect_force_native, 429 + /* ASUSTeK COMPUTER INC. GA503 */ 430 + .matches = { 564 431 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 565 432 DMI_MATCH(DMI_PRODUCT_NAME, "GA503"), 566 433 }, 567 434 }, 568 - /* 569 - * Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a 570 - * working native and video interface. However the default detection 571 - * mechanism first registers the video interface before unregistering 572 - * it again and switching to the native interface during boot. This 573 - * results in a dangling SBIOS request for backlight change for some 574 - * reason, causing the backlight to switch to ~2% once per boot on the 575 - * first power cord connect or disconnect event. Setting the native 576 - * interface explicitly circumvents this buggy behaviour, by avoiding 577 - * the unregistering process. 578 - */ 579 435 { 580 - .callback = video_detect_force_native, 581 - .ident = "Clevo NL5xRU", 582 - .matches = { 583 - DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), 436 + .callback = video_detect_force_native, 437 + /* Asus UX303UB */ 438 + .matches = { 439 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 440 + DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"), 584 441 }, 585 442 }, 586 443 { 587 - .callback = video_detect_force_native, 588 - .ident = "Clevo NL5xRU", 589 - .matches = { 590 - DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 591 - DMI_MATCH(DMI_BOARD_NAME, "AURA1501"), 444 + .callback = video_detect_force_native, 445 + /* Samsung N150P */ 446 + .matches = { 447 + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 448 + DMI_MATCH(DMI_PRODUCT_NAME, "N150P"), 449 + DMI_MATCH(DMI_BOARD_NAME, "N150P"), 592 450 }, 593 451 }, 594 452 { 595 - .callback = video_detect_force_native, 596 - .ident = "Clevo NL5xRU", 597 - .matches = { 598 - DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 599 - DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"), 453 + .callback = video_detect_force_native, 454 + /* Samsung N145P/N250P/N260P */ 455 + .matches = { 456 + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 457 + DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"), 458 + DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"), 600 459 }, 601 460 }, 602 461 { 603 - .callback = video_detect_force_native, 604 - .ident = "Clevo NL5xNU", 605 - .matches = { 606 - DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"), 462 + .callback = video_detect_force_native, 463 + /* Samsung N250P */ 464 + .matches = { 465 + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 466 + DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), 467 + DMI_MATCH(DMI_BOARD_NAME, "N250P"), 607 468 }, 608 469 }, 609 - /* 610 - * The TongFang PF5PU1G, PF4NU1F, PF5NU1G, and PF5LUXG/TUXEDO BA15 Gen10, 611 - * Pulse 14/15 Gen1, and Pulse 15 Gen2 have the same problem as the Clevo 612 - * NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2. See the description 613 - * above. 614 - */ 615 - { 616 - .callback = video_detect_force_native, 617 - .ident = "TongFang PF5PU1G", 618 - .matches = { 619 - DMI_MATCH(DMI_BOARD_NAME, "PF5PU1G"), 620 - }, 621 - }, 622 - { 623 - .callback = video_detect_force_native, 624 - .ident = "TongFang PF4NU1F", 625 - .matches = { 626 - DMI_MATCH(DMI_BOARD_NAME, "PF4NU1F"), 627 - }, 628 - }, 629 - { 630 - .callback = video_detect_force_native, 631 - .ident = "TongFang PF4NU1F", 632 - .matches = { 633 - DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 634 - DMI_MATCH(DMI_BOARD_NAME, "PULSE1401"), 635 - }, 636 - }, 637 - { 638 - .callback = video_detect_force_native, 639 - .ident = "TongFang PF5NU1G", 640 - .matches = { 641 - DMI_MATCH(DMI_BOARD_NAME, "PF5NU1G"), 642 - }, 643 - }, 644 - { 645 - .callback = video_detect_force_native, 646 - .ident = "TongFang PF5NU1G", 647 - .matches = { 648 - DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 649 - DMI_MATCH(DMI_BOARD_NAME, "PULSE1501"), 650 - }, 651 - }, 652 - { 653 - .callback = video_detect_force_native, 654 - .ident = "TongFang PF5LUXG", 655 - .matches = { 656 - DMI_MATCH(DMI_BOARD_NAME, "PF5LUXG"), 657 - }, 658 - }, 470 + 659 471 /* 660 472 * Desktops which falsely report a backlight and which our heuristics 661 473 * for this do not catch. ··· 633 537 { }, 634 538 }; 635 539 636 - /* This uses a workqueue to avoid various locking ordering issues */ 637 - static void acpi_video_backlight_notify_work(struct work_struct *work) 638 - { 639 - if (acpi_video_get_backlight_type() != acpi_backlight_video) 640 - acpi_video_unregister_backlight(); 641 - } 642 - 643 - static int acpi_video_backlight_notify(struct notifier_block *nb, 644 - unsigned long val, void *bd) 645 - { 646 - struct backlight_device *backlight = bd; 647 - 648 - /* A raw bl registering may change video -> native */ 649 - if (backlight->props.type == BACKLIGHT_RAW && 650 - val == BACKLIGHT_REGISTERED) 651 - schedule_work(&backlight_notify_work); 652 - 653 - return NOTIFY_OK; 654 - } 655 - 656 540 /* 657 541 * Determine which type of backlight interface to use on this system, 658 542 * First check cmdline, then dmi quirks, then do autodetect. 659 - * 660 - * The autodetect order is: 661 - * 1) Is the acpi-video backlight interface supported -> 662 - * no, use a vendor interface 663 - * 2) Is this a win8 "ready" BIOS and do we have a native interface -> 664 - * yes, use a native interface 665 - * 3) Else use the acpi-video interface 666 - * 667 - * Arguably the native on win8 check should be done first, but that would 668 - * be a behavior change, which may causes issues. 669 543 */ 670 - enum acpi_backlight_type acpi_video_get_backlight_type(void) 544 + static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) 671 545 { 672 546 static DEFINE_MUTEX(init_mutex); 547 + static bool nvidia_wmi_ec_present; 548 + static bool native_available; 673 549 static bool init_done; 674 550 static long video_caps; 675 551 ··· 653 585 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 654 586 ACPI_UINT32_MAX, find_video, NULL, 655 587 &video_caps, NULL); 656 - INIT_WORK(&backlight_notify_work, 657 - acpi_video_backlight_notify_work); 658 - backlight_nb.notifier_call = acpi_video_backlight_notify; 659 - backlight_nb.priority = 0; 660 - if (backlight_register_notifier(&backlight_nb) == 0) 661 - backlight_notifier_registered = true; 588 + nvidia_wmi_ec_present = nvidia_wmi_ec_supported(); 662 589 init_done = true; 663 590 } 591 + if (native) 592 + native_available = true; 664 593 mutex_unlock(&init_mutex); 665 594 595 + /* 596 + * The below heuristics / detection steps are in order of descending 597 + * presedence. The commandline takes presedence over anything else. 598 + */ 666 599 if (acpi_backlight_cmdline != acpi_backlight_undef) 667 600 return acpi_backlight_cmdline; 668 601 602 + /* DMI quirks override any autodetection. */ 669 603 if (acpi_backlight_dmi != acpi_backlight_undef) 670 604 return acpi_backlight_dmi; 671 605 672 - if (!(video_caps & ACPI_VIDEO_BACKLIGHT)) 673 - return acpi_backlight_vendor; 606 + /* Special cases such as nvidia_wmi_ec and apple gmux. */ 607 + if (nvidia_wmi_ec_present) 608 + return acpi_backlight_nvidia_wmi_ec; 674 609 675 - if (acpi_osi_is_win8() && backlight_device_get_by_type(BACKLIGHT_RAW)) 676 - return acpi_backlight_native; 610 + if (apple_gmux_present()) 611 + return acpi_backlight_apple_gmux; 677 612 678 - return acpi_backlight_video; 613 + /* On systems with ACPI video use either native or ACPI video. */ 614 + if (video_caps & ACPI_VIDEO_BACKLIGHT) { 615 + /* 616 + * Windows 8 and newer no longer use the ACPI video interface, 617 + * so it often does not work. If the ACPI tables are written 618 + * for win8 and native brightness ctl is available, use that. 619 + * 620 + * The native check deliberately is inside the if acpi-video 621 + * block on older devices without acpi-video support native 622 + * is usually not the best choice. 623 + */ 624 + if (acpi_osi_is_win8() && native_available) 625 + return acpi_backlight_native; 626 + else 627 + return acpi_backlight_video; 628 + } 629 + 630 + /* No ACPI video (old hw), use vendor specific fw methods. */ 631 + return acpi_backlight_vendor; 632 + } 633 + 634 + enum acpi_backlight_type acpi_video_get_backlight_type(void) 635 + { 636 + return __acpi_video_get_backlight_type(false); 679 637 } 680 638 EXPORT_SYMBOL(acpi_video_get_backlight_type); 681 639 682 - /* 683 - * Set the preferred backlight interface type based on DMI info. 684 - * This function allows DMI blacklists to be implemented by external 685 - * platform drivers instead of putting a big blacklist in video_detect.c 686 - */ 687 - void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type) 640 + bool acpi_video_backlight_use_native(void) 688 641 { 689 - acpi_backlight_dmi = type; 690 - /* Remove acpi-video backlight interface if it is no longer desired */ 691 - if (acpi_video_get_backlight_type() != acpi_backlight_video) 692 - acpi_video_unregister_backlight(); 642 + return __acpi_video_get_backlight_type(true) == acpi_backlight_native; 693 643 } 694 - EXPORT_SYMBOL(acpi_video_set_dmi_backlight_type); 695 - 696 - void __exit acpi_video_detect_exit(void) 697 - { 698 - if (backlight_notifier_registered) 699 - backlight_unregister_notifier(&backlight_nb); 700 - } 644 + EXPORT_SYMBOL(acpi_video_backlight_use_native);
+14
drivers/gpu/drm/Kconfig
··· 235 235 select HWMON 236 236 select BACKLIGHT_CLASS_DEVICE 237 237 select INTERVAL_TREE 238 + # radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work 239 + # ACPI_VIDEO's dependencies must also be selected. 240 + select INPUT if ACPI 241 + select ACPI_VIDEO if ACPI 242 + # On x86 ACPI_VIDEO also needs ACPI_WMI 243 + select X86_PLATFORM_DEVICES if ACPI && X86 244 + select ACPI_WMI if ACPI && X86 238 245 help 239 246 Choose this option if you have an ATI Radeon graphics card. There 240 247 are both PCI and AGP versions. You don't need to choose this to ··· 267 260 select BACKLIGHT_CLASS_DEVICE 268 261 select INTERVAL_TREE 269 262 select DRM_BUDDY 263 + # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work 264 + # ACPI_VIDEO's dependencies must also be selected. 265 + select INPUT if ACPI 266 + select ACPI_VIDEO if ACPI 267 + # On x86 ACPI_VIDEO also needs ACPI_WMI 268 + select X86_PLATFORM_DEVICES if ACPI && X86 269 + select ACPI_WMI if ACPI && X86 270 270 help 271 271 Choose this option if you have a recent AMD Radeon graphics card. 272 272
+13 -1
drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
··· 26 26 27 27 #include <linux/pci.h> 28 28 29 + #include <acpi/video.h> 30 + 29 31 #include <drm/drm_crtc_helper.h> 30 32 #include <drm/amdgpu_drm.h> 31 33 #include "amdgpu.h" ··· 184 182 return; 185 183 186 184 if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 187 - return; 185 + goto register_acpi_backlight; 186 + 187 + if (!acpi_video_backlight_use_native()) { 188 + drm_info(dev, "Skipping amdgpu atom DIG backlight registration\n"); 189 + goto register_acpi_backlight; 190 + } 188 191 189 192 pdata = kmalloc(sizeof(struct amdgpu_backlight_privdata), GFP_KERNEL); 190 193 if (!pdata) { ··· 224 217 225 218 error: 226 219 kfree(pdata); 220 + return; 221 + 222 + register_acpi_backlight: 223 + /* Try registering an ACPI video backlight device instead. */ 224 + acpi_video_register_backlight(); 227 225 return; 228 226 } 229 227
+9
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 90 90 #include <drm/drm_gem_atomic_helper.h> 91 91 #include <drm/drm_plane_helper.h> 92 92 93 + #include <acpi/video.h> 94 + 93 95 #include "ivsrcid/dcn/irqsrcs_dcn_1_0.h" 94 96 95 97 #include "dcn/dcn_1_0_offset.h" ··· 4033 4031 4034 4032 amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps); 4035 4033 dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL; 4034 + 4035 + if (!acpi_video_backlight_use_native()) { 4036 + drm_info(adev_to_drm(dm->adev), "Skipping amdgpu DM backlight registration\n"); 4037 + /* Try registering an ACPI video backlight device instead. */ 4038 + acpi_video_register_backlight(); 4039 + return; 4040 + } 4036 4041 4037 4042 props.max_brightness = AMDGPU_MAX_BL_LEVEL; 4038 4043 props.brightness = AMDGPU_MAX_BL_LEVEL;
+2
drivers/gpu/drm/gma500/Kconfig
··· 7 7 select ACPI_VIDEO if ACPI 8 8 select BACKLIGHT_CLASS_DEVICE if ACPI 9 9 select INPUT if ACPI 10 + select X86_PLATFORM_DEVICES if ACPI 11 + select ACPI_WMI if ACPI 10 12 help 11 13 Say yes for an experimental 2D KMS framebuffer driver for the 12 14 Intel GMA500 (Poulsbo), Intel GMA600 (Moorestown/Oak Trail) and
+2
drivers/gpu/drm/i915/Kconfig
··· 23 23 # but for select to work, need to select ACPI_VIDEO's dependencies, ick 24 24 select BACKLIGHT_CLASS_DEVICE if ACPI 25 25 select INPUT if ACPI 26 + select X86_PLATFORM_DEVICES if ACPI 27 + select ACPI_WMI if ACPI 26 28 select ACPI_VIDEO if ACPI 27 29 select ACPI_BUTTON if ACPI 28 30 select SYNC_FILE
+27
drivers/gpu/drm/i915/display/intel_acpi.c
··· 7 7 8 8 #include <linux/pci.h> 9 9 #include <linux/acpi.h> 10 + #include <acpi/video.h> 10 11 11 12 #include "i915_drv.h" 12 13 #include "intel_acpi.h" ··· 331 330 * put this, otherwise fwnode is NULL and the put is a no-op. 332 331 */ 333 332 fwnode_handle_put(fwnode); 333 + } 334 + 335 + void intel_acpi_video_register(struct drm_i915_private *i915) 336 + { 337 + struct drm_connector_list_iter conn_iter; 338 + struct drm_connector *connector; 339 + 340 + acpi_video_register(); 341 + 342 + /* 343 + * If i915 is driving an internal panel without registering its native 344 + * backlight handler try to register the acpi_video backlight. 345 + * For panels not driven by i915 another GPU driver may still register 346 + * a native backlight later and acpi_video_register_backlight() should 347 + * only be called after any native backlights have been registered. 348 + */ 349 + drm_connector_list_iter_begin(&i915->drm, &conn_iter); 350 + drm_for_each_connector_iter(connector, &conn_iter) { 351 + struct intel_panel *panel = &to_intel_connector(connector)->panel; 352 + 353 + if (panel->backlight.funcs && !panel->backlight.device) { 354 + acpi_video_register_backlight(); 355 + break; 356 + } 357 + } 358 + drm_connector_list_iter_end(&conn_iter); 334 359 }
+3
drivers/gpu/drm/i915/display/intel_acpi.h
··· 14 14 void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915); 15 15 void intel_acpi_device_id_update(struct drm_i915_private *i915); 16 16 void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915); 17 + void intel_acpi_video_register(struct drm_i915_private *i915); 17 18 #else 18 19 static inline void intel_register_dsm_handler(void) { return; } 19 20 static inline void intel_unregister_dsm_handler(void) { return; } ··· 24 23 void intel_acpi_device_id_update(struct drm_i915_private *i915) { return; } 25 24 static inline 26 25 void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) { return; } 26 + static inline 27 + void intel_acpi_video_register(struct drm_i915_private *i915) { return; } 27 28 #endif /* CONFIG_ACPI */ 28 29 29 30 #endif /* __INTEL_ACPI_H__ */
+7
drivers/gpu/drm/i915/display/intel_backlight.c
··· 8 8 #include <linux/pwm.h> 9 9 #include <linux/string_helpers.h> 10 10 11 + #include <acpi/video.h> 12 + 11 13 #include "intel_backlight.h" 12 14 #include "intel_connector.h" 13 15 #include "intel_de.h" ··· 951 949 return 0; 952 950 953 951 WARN_ON(panel->backlight.max == 0); 952 + 953 + if (!acpi_video_backlight_use_native()) { 954 + drm_info(&i915->drm, "Skipping intel_backlight registration\n"); 955 + return 0; 956 + } 954 957 955 958 memset(&props, 0, sizeof(props)); 956 959 props.type = BACKLIGHT_RAW;
+1 -1
drivers/gpu/drm/i915/display/intel_display.c
··· 9089 9089 9090 9090 /* Must be done after probing outputs */ 9091 9091 intel_opregion_register(i915); 9092 - acpi_video_register(); 9092 + intel_acpi_video_register(i915); 9093 9093 9094 9094 intel_audio_init(i915); 9095 9095
+10
drivers/gpu/drm/nouveau/nouveau_acpi.c
··· 386 386 387 387 return kmemdup(edid, EDID_LENGTH, GFP_KERNEL); 388 388 } 389 + 390 + bool nouveau_acpi_video_backlight_use_native(void) 391 + { 392 + return acpi_video_backlight_use_native(); 393 + } 394 + 395 + void nouveau_acpi_video_register_backlight(void) 396 + { 397 + acpi_video_register_backlight(); 398 + }
+4
drivers/gpu/drm/nouveau/nouveau_acpi.h
··· 11 11 void nouveau_unregister_dsm_handler(void); 12 12 void nouveau_switcheroo_optimus_dsm(void); 13 13 void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *); 14 + bool nouveau_acpi_video_backlight_use_native(void); 15 + void nouveau_acpi_video_register_backlight(void); 14 16 #else 15 17 static inline bool nouveau_is_optimus(void) { return false; }; 16 18 static inline bool nouveau_is_v1_dsm(void) { return false; }; ··· 20 18 static inline void nouveau_unregister_dsm_handler(void) {} 21 19 static inline void nouveau_switcheroo_optimus_dsm(void) {} 22 20 static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; } 21 + static inline bool nouveau_acpi_video_backlight_use_native(void) { return true; } 22 + static inline void nouveau_acpi_video_register_backlight(void) {} 23 23 #endif 24 24 25 25 #endif
+13
drivers/gpu/drm/nouveau/nouveau_backlight.c
··· 38 38 #include "nouveau_reg.h" 39 39 #include "nouveau_encoder.h" 40 40 #include "nouveau_connector.h" 41 + #include "nouveau_acpi.h" 41 42 42 43 static struct ida bl_ida; 43 44 #define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0' ··· 406 405 goto fail_alloc; 407 406 } 408 407 408 + if (!nouveau_acpi_video_backlight_use_native()) { 409 + NV_INFO(drm, "Skipping nv_backlight registration\n"); 410 + goto fail_alloc; 411 + } 412 + 409 413 if (!nouveau_get_backlight_name(backlight_name, bl)) { 410 414 NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n"); 411 415 goto fail_alloc; ··· 436 430 437 431 fail_alloc: 438 432 kfree(bl); 433 + /* 434 + * If we get here we have an internal panel, but no nv_backlight, 435 + * try registering an ACPI video backlight device instead. 436 + */ 437 + if (ret == 0) 438 + nouveau_acpi_video_register_backlight(); 439 + 439 440 return ret; 440 441 } 441 442
+7
drivers/gpu/drm/radeon/atombios_encoders.c
··· 32 32 #include <drm/drm_file.h> 33 33 #include <drm/radeon_drm.h> 34 34 35 + #include <acpi/video.h> 36 + 35 37 #include "atom.h" 36 38 #include "radeon_atombios.h" 37 39 #include "radeon.h" ··· 210 208 211 209 if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 212 210 return; 211 + 212 + if (!acpi_video_backlight_use_native()) { 213 + drm_info(dev, "Skipping radeon atom DIG backlight registration\n"); 214 + return; 215 + } 213 216 214 217 pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL); 215 218 if (!pdata) {
+10 -1
drivers/gpu/drm/radeon/radeon_encoders.c
··· 30 30 #include <drm/drm_device.h> 31 31 #include <drm/radeon_drm.h> 32 32 33 + #include <acpi/video.h> 34 + 33 35 #include "radeon.h" 34 36 #include "radeon_atombios.h" 35 37 #include "radeon_legacy_encoders.h" ··· 169 167 return; 170 168 171 169 if (radeon_backlight == 0) { 172 - return; 170 + use_bl = false; 173 171 } else if (radeon_backlight == 1) { 174 172 use_bl = true; 175 173 } else if (radeon_backlight == -1) { ··· 195 193 else 196 194 radeon_legacy_backlight_init(radeon_encoder, connector); 197 195 } 196 + 197 + /* 198 + * If there is no native backlight device (which may happen even when 199 + * use_bl==true) try registering an ACPI video backlight device instead. 200 + */ 201 + if (!rdev->mode_info.bl_encoder) 202 + acpi_video_register_backlight(); 198 203 } 199 204 200 205 void
+7
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
··· 33 33 #include <drm/drm_util.h> 34 34 #include <drm/radeon_drm.h> 35 35 36 + #include <acpi/video.h> 37 + 36 38 #include "radeon.h" 37 39 #include "radeon_asic.h" 38 40 #include "radeon_legacy_encoders.h" ··· 388 386 !pmac_has_backlight_type("mnca")) 389 387 return; 390 388 #endif 389 + 390 + if (!acpi_video_backlight_use_native()) { 391 + drm_info(dev, "Skipping radeon legacy LVDS backlight registration\n"); 392 + return; 393 + } 391 394 392 395 pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL); 393 396 if (!pdata) {
+1
drivers/platform/x86/Kconfig
··· 93 93 94 94 config NVIDIA_WMI_EC_BACKLIGHT 95 95 tristate "EC Backlight Driver for Hybrid Graphics Notebook Systems" 96 + depends on ACPI_VIDEO 96 97 depends on ACPI_WMI 97 98 depends on BACKLIGHT_CLASS_DEVICE 98 99 help
-66
drivers/platform/x86/acer-wmi.c
··· 643 643 {} 644 644 }; 645 645 646 - static int __init 647 - video_set_backlight_video_vendor(const struct dmi_system_id *d) 648 - { 649 - interface->capability &= ~ACER_CAP_BRIGHTNESS; 650 - pr_info("Brightness must be controlled by generic video driver\n"); 651 - return 0; 652 - } 653 - 654 - static const struct dmi_system_id video_vendor_dmi_table[] __initconst = { 655 - { 656 - .callback = video_set_backlight_video_vendor, 657 - .ident = "Acer TravelMate 4750", 658 - .matches = { 659 - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 660 - DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"), 661 - }, 662 - }, 663 - { 664 - .callback = video_set_backlight_video_vendor, 665 - .ident = "Acer Extensa 5235", 666 - .matches = { 667 - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 668 - DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"), 669 - }, 670 - }, 671 - { 672 - .callback = video_set_backlight_video_vendor, 673 - .ident = "Acer TravelMate 5760", 674 - .matches = { 675 - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 676 - DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"), 677 - }, 678 - }, 679 - { 680 - .callback = video_set_backlight_video_vendor, 681 - .ident = "Acer Aspire 5750", 682 - .matches = { 683 - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 684 - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), 685 - }, 686 - }, 687 - { 688 - .callback = video_set_backlight_video_vendor, 689 - .ident = "Acer Aspire 5741", 690 - .matches = { 691 - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 692 - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"), 693 - }, 694 - }, 695 - { 696 - /* 697 - * Note no video_set_backlight_video_vendor, we must use the 698 - * acer interface, as there is no native backlight interface. 699 - */ 700 - .ident = "Acer KAV80", 701 - .matches = { 702 - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 703 - DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"), 704 - }, 705 - }, 706 - {} 707 - }; 708 - 709 646 /* Find which quirks are needed for a particular vendor/ model pair */ 710 647 static void __init find_quirks(void) 711 648 { ··· 2413 2476 } 2414 2477 2415 2478 set_quirks(); 2416 - 2417 - if (dmi_check_system(video_vendor_dmi_table)) 2418 - acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); 2419 2479 2420 2480 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 2421 2481 interface->capability &= ~ACER_CAP_BRIGHTNESS;
-3
drivers/platform/x86/apple-gmux.c
··· 21 21 #include <linux/delay.h> 22 22 #include <linux/pci.h> 23 23 #include <linux/vga_switcheroo.h> 24 - #include <acpi/video.h> 25 24 #include <asm/io.h> 26 25 27 26 /** ··· 693 694 * backlight control and supports more levels than other options. 694 695 * Disable the other backlight choices. 695 696 */ 696 - acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); 697 697 apple_bl_unregister(); 698 698 699 699 gmux_data->power_state = VGA_SWITCHEROO_ON; ··· 802 804 apple_gmux_data = NULL; 803 805 kfree(gmux_data); 804 806 805 - acpi_video_register(); 806 807 apple_bl_register(); 807 808 } 808 809
-21
drivers/platform/x86/asus-nb-wmi.c
··· 79 79 80 80 /* 81 81 * For those machines that need software to control bt/wifi status 82 - * and can't adjust brightness through ACPI interface 83 82 * and have duplicate events(ACPI and WMI) for display toggle 84 83 */ 85 84 static struct quirk_entry quirk_asus_x55u = { 86 85 .wapf = 4, 87 - .wmi_backlight_power = true, 88 86 .wmi_backlight_set_devstate = true, 89 87 .no_display_toggle = true, 90 88 }; ··· 94 96 95 97 static struct quirk_entry quirk_asus_x200ca = { 96 98 .wapf = 2, 97 - .wmi_backlight_set_devstate = true, 98 - }; 99 - 100 - static struct quirk_entry quirk_asus_ux303ub = { 101 - .wmi_backlight_native = true, 102 99 .wmi_backlight_set_devstate = true, 103 100 }; 104 101 ··· 140 147 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), 141 148 DMI_MATCH(DMI_PRODUCT_NAME, "U32U"), 142 149 }, 143 - /* 144 - * Note this machine has a Brazos APU, and most Brazos Asus 145 - * machines need quirk_asus_x55u / wmi_backlight_power but 146 - * here acpi-video seems to work fine for backlight control. 147 - */ 148 150 .driver_data = &quirk_asus_wapf4, 149 151 }, 150 152 { ··· 366 378 DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"), 367 379 }, 368 380 .driver_data = &quirk_asus_x200ca, 369 - }, 370 - { 371 - .callback = dmi_matched, 372 - .ident = "ASUSTeK COMPUTER INC. UX303UB", 373 - .matches = { 374 - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 375 - DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"), 376 - }, 377 - .driver_data = &quirk_asus_ux303ub, 378 381 }, 379 382 { 380 383 .callback = dmi_matched,
-13
drivers/platform/x86/asus-wmi.c
··· 3553 3553 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); 3554 3554 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); 3555 3555 struct asus_wmi *asus; 3556 - const char *chassis_type; 3557 3556 acpi_status status; 3558 3557 int err; 3559 3558 u32 result; ··· 3633 3634 3634 3635 if (asus->driver->quirks->wmi_force_als_set) 3635 3636 asus_wmi_set_als(); 3636 - 3637 - /* Some Asus desktop boards export an acpi-video backlight interface, 3638 - stop this from showing up */ 3639 - chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); 3640 - if (chassis_type && !strcmp(chassis_type, "3")) 3641 - acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); 3642 - 3643 - if (asus->driver->quirks->wmi_backlight_power) 3644 - acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); 3645 - 3646 - if (asus->driver->quirks->wmi_backlight_native) 3647 - acpi_video_set_dmi_backlight_type(acpi_backlight_native); 3648 3637 3649 3638 if (asus->driver->quirks->xusb2pr) 3650 3639 asus_wmi_set_xusb2pr(asus);
-2
drivers/platform/x86/asus-wmi.h
··· 29 29 bool hotplug_wireless; 30 30 bool scalar_panel_brightness; 31 31 bool store_backlight_power; 32 - bool wmi_backlight_power; 33 - bool wmi_backlight_native; 34 32 bool wmi_backlight_set_devstate; 35 33 bool wmi_force_als_set; 36 34 bool use_kbd_dock_devid;
+1 -24
drivers/platform/x86/eeepc-wmi.c
··· 96 96 .store_backlight_power = true, 97 97 }; 98 98 99 - static struct quirk_entry quirk_asus_x101ch = { 100 - /* We need this when ACPI function doesn't do this well */ 101 - .wmi_backlight_power = true, 102 - }; 103 - 104 99 static struct quirk_entry *quirks; 105 100 106 101 static void et2012_quirks(void) ··· 146 151 }, 147 152 .driver_data = &quirk_asus_unknown, 148 153 }, 149 - { 150 - .callback = dmi_matched, 151 - .ident = "ASUSTeK Computer INC. X101CH", 152 - .matches = { 153 - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 154 - DMI_MATCH(DMI_PRODUCT_NAME, "X101CH"), 155 - }, 156 - .driver_data = &quirk_asus_x101ch, 157 - }, 158 - { 159 - .callback = dmi_matched, 160 - .ident = "ASUSTeK Computer INC. 1015CX", 161 - .matches = { 162 - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 163 - DMI_MATCH(DMI_PRODUCT_NAME, "1015CX"), 164 - }, 165 - .driver_data = &quirk_asus_x101ch, 166 - }, 167 - {}, 154 + {} 168 155 }; 169 156 170 157 static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
+4 -78
drivers/platform/x86/nvidia-wmi-ec-backlight.c
··· 7 7 #include <linux/backlight.h> 8 8 #include <linux/mod_devicetable.h> 9 9 #include <linux/module.h> 10 + #include <linux/platform_data/x86/nvidia-wmi-ec-backlight.h> 10 11 #include <linux/types.h> 11 12 #include <linux/wmi.h> 12 - 13 - /** 14 - * enum wmi_brightness_method - WMI method IDs 15 - * @WMI_BRIGHTNESS_METHOD_LEVEL: Get/Set EC brightness level status 16 - * @WMI_BRIGHTNESS_METHOD_SOURCE: Get/Set EC Brightness Source 17 - */ 18 - enum wmi_brightness_method { 19 - WMI_BRIGHTNESS_METHOD_LEVEL = 1, 20 - WMI_BRIGHTNESS_METHOD_SOURCE = 2, 21 - WMI_BRIGHTNESS_METHOD_MAX 22 - }; 23 - 24 - /** 25 - * enum wmi_brightness_mode - Operation mode for WMI-wrapped method 26 - * @WMI_BRIGHTNESS_MODE_GET: Get the current brightness level/source. 27 - * @WMI_BRIGHTNESS_MODE_SET: Set the brightness level. 28 - * @WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL: Get the maximum brightness level. This 29 - * is only valid when the WMI method is 30 - * %WMI_BRIGHTNESS_METHOD_LEVEL. 31 - */ 32 - enum wmi_brightness_mode { 33 - WMI_BRIGHTNESS_MODE_GET = 0, 34 - WMI_BRIGHTNESS_MODE_SET = 1, 35 - WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL = 2, 36 - WMI_BRIGHTNESS_MODE_MAX 37 - }; 38 - 39 - /** 40 - * enum wmi_brightness_source - Backlight brightness control source selection 41 - * @WMI_BRIGHTNESS_SOURCE_GPU: Backlight brightness is controlled by the GPU. 42 - * @WMI_BRIGHTNESS_SOURCE_EC: Backlight brightness is controlled by the 43 - * system's Embedded Controller (EC). 44 - * @WMI_BRIGHTNESS_SOURCE_AUX: Backlight brightness is controlled over the 45 - * DisplayPort AUX channel. 46 - */ 47 - enum wmi_brightness_source { 48 - WMI_BRIGHTNESS_SOURCE_GPU = 1, 49 - WMI_BRIGHTNESS_SOURCE_EC = 2, 50 - WMI_BRIGHTNESS_SOURCE_AUX = 3, 51 - WMI_BRIGHTNESS_SOURCE_MAX 52 - }; 53 - 54 - /** 55 - * struct wmi_brightness_args - arguments for the WMI-wrapped ACPI method 56 - * @mode: Pass in an &enum wmi_brightness_mode value to select between 57 - * getting or setting a value. 58 - * @val: In parameter for value to set when using %WMI_BRIGHTNESS_MODE_SET 59 - * mode. Not used in conjunction with %WMI_BRIGHTNESS_MODE_GET or 60 - * %WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL mode. 61 - * @ret: Out parameter returning retrieved value when operating in 62 - * %WMI_BRIGHTNESS_MODE_GET or %WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL 63 - * mode. Not used in %WMI_BRIGHTNESS_MODE_SET mode. 64 - * @ignored: Padding; not used. The ACPI method expects a 24 byte params struct. 65 - * 66 - * This is the parameters structure for the WmiBrightnessNotify ACPI method as 67 - * wrapped by WMI. The value passed in to @val or returned by @ret will be a 68 - * brightness value when the WMI method ID is %WMI_BRIGHTNESS_METHOD_LEVEL, or 69 - * an &enum wmi_brightness_source value with %WMI_BRIGHTNESS_METHOD_SOURCE. 70 - */ 71 - struct wmi_brightness_args { 72 - u32 mode; 73 - u32 val; 74 - u32 ret; 75 - u32 ignored[3]; 76 - }; 13 + #include <acpi/video.h> 77 14 78 15 /** 79 16 * wmi_brightness_notify() - helper function for calling WMI-wrapped ACPI method ··· 88 151 { 89 152 struct backlight_properties props = {}; 90 153 struct backlight_device *bdev; 91 - u32 source; 92 154 int ret; 93 155 94 - ret = wmi_brightness_notify(wdev, WMI_BRIGHTNESS_METHOD_SOURCE, 95 - WMI_BRIGHTNESS_MODE_GET, &source); 96 - if (ret) 97 - return ret; 98 - 99 - /* 100 - * This driver is only to be used when brightness control is handled 101 - * by the EC; otherwise, the GPU driver(s) should control brightness. 102 - */ 103 - if (source != WMI_BRIGHTNESS_SOURCE_EC) 156 + /* drivers/acpi/video_detect.c also checks that SOURCE == EC */ 157 + if (acpi_video_get_backlight_type() != acpi_backlight_nvidia_wmi_ec) 104 158 return -ENODEV; 105 159 106 160 /* ··· 118 190 &props); 119 191 return PTR_ERR_OR_ZERO(bdev); 120 192 } 121 - 122 - #define WMI_BRIGHTNESS_GUID "603E9613-EF25-4338-A3D0-C46177516DB7" 123 193 124 194 static const struct wmi_device_id nvidia_wmi_ec_backlight_id_table[] = { 125 195 { .guid_string = WMI_BRIGHTNESS_GUID },
-87
drivers/platform/x86/samsung-laptop.c
··· 356 356 }; 357 357 358 358 struct samsung_quirks { 359 - bool broken_acpi_video; 360 359 bool four_kbd_backlight_levels; 361 360 bool enable_kbd_backlight; 362 - bool use_native_backlight; 363 361 bool lid_handling; 364 362 }; 365 363 366 364 static struct samsung_quirks samsung_unknown = {}; 367 - 368 - static struct samsung_quirks samsung_broken_acpi_video = { 369 - .broken_acpi_video = true, 370 - }; 371 - 372 - static struct samsung_quirks samsung_use_native_backlight = { 373 - .use_native_backlight = true, 374 - }; 375 365 376 366 static struct samsung_quirks samsung_np740u3e = { 377 367 .four_kbd_backlight_levels = true, ··· 1532 1542 /* Specific DMI ids for laptop with quirks */ 1533 1543 { 1534 1544 .callback = samsung_dmi_matched, 1535 - .ident = "N150P", 1536 - .matches = { 1537 - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 1538 - DMI_MATCH(DMI_PRODUCT_NAME, "N150P"), 1539 - DMI_MATCH(DMI_BOARD_NAME, "N150P"), 1540 - }, 1541 - .driver_data = &samsung_use_native_backlight, 1542 - }, 1543 - { 1544 - .callback = samsung_dmi_matched, 1545 - .ident = "N145P/N250P/N260P", 1546 - .matches = { 1547 - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 1548 - DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"), 1549 - DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"), 1550 - }, 1551 - .driver_data = &samsung_use_native_backlight, 1552 - }, 1553 - { 1554 - .callback = samsung_dmi_matched, 1555 - .ident = "N150/N210/N220", 1556 - .matches = { 1557 - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 1558 - DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"), 1559 - DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"), 1560 - }, 1561 - .driver_data = &samsung_broken_acpi_video, 1562 - }, 1563 - { 1564 - .callback = samsung_dmi_matched, 1565 - .ident = "NF110/NF210/NF310", 1566 - .matches = { 1567 - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 1568 - DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"), 1569 - DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"), 1570 - }, 1571 - .driver_data = &samsung_broken_acpi_video, 1572 - }, 1573 - { 1574 - .callback = samsung_dmi_matched, 1575 - .ident = "X360", 1576 - .matches = { 1577 - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 1578 - DMI_MATCH(DMI_PRODUCT_NAME, "X360"), 1579 - DMI_MATCH(DMI_BOARD_NAME, "X360"), 1580 - }, 1581 - .driver_data = &samsung_broken_acpi_video, 1582 - }, 1583 - { 1584 - .callback = samsung_dmi_matched, 1585 - .ident = "N250P", 1586 - .matches = { 1587 - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 1588 - DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), 1589 - DMI_MATCH(DMI_BOARD_NAME, "N250P"), 1590 - }, 1591 - .driver_data = &samsung_use_native_backlight, 1592 - }, 1593 - { 1594 - .callback = samsung_dmi_matched, 1595 - .ident = "NC210", 1596 - .matches = { 1597 - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 1598 - DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"), 1599 - DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"), 1600 - }, 1601 - .driver_data = &samsung_broken_acpi_video, 1602 - }, 1603 - { 1604 - .callback = samsung_dmi_matched, 1605 1545 .ident = "730U3E/740U3E", 1606 1546 .matches = { 1607 1547 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), ··· 1574 1654 samsung->handle_backlight = true; 1575 1655 samsung->quirks = quirks; 1576 1656 1577 - #ifdef CONFIG_ACPI 1578 - if (samsung->quirks->broken_acpi_video) 1579 - acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); 1580 - if (samsung->quirks->use_native_backlight) 1581 - acpi_video_set_dmi_backlight_type(acpi_backlight_native); 1582 - 1583 1657 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 1584 1658 samsung->handle_backlight = false; 1585 - #endif 1586 1659 1587 1660 ret = samsung_platform_init(samsung); 1588 1661 if (ret)
-16
drivers/platform/x86/toshiba_acpi.c
··· 272 272 }; 273 273 274 274 /* 275 - * List of models which have a broken acpi-video backlight interface and thus 276 - * need to use the toshiba (vendor) interface instead. 277 - */ 278 - static const struct dmi_system_id toshiba_vendor_backlight_dmi[] = { 279 - {} 280 - }; 281 - 282 - /* 283 275 * Utility 284 276 */ 285 277 ··· 2872 2880 pr_debug("Backlight method is read-only, disabling backlight support\n"); 2873 2881 return 0; 2874 2882 } 2875 - 2876 - /* 2877 - * Tell acpi-video-detect code to prefer vendor backlight on all 2878 - * systems with transflective backlight and on dmi matched systems. 2879 - */ 2880 - if (dev->tr_backlight_supported || 2881 - dmi_check_system(toshiba_vendor_backlight_dmi)) 2882 - acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); 2883 2883 2884 2884 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 2885 2885 return 0;
+7 -2
include/acpi/video.h
··· 48 48 acpi_backlight_video, 49 49 acpi_backlight_vendor, 50 50 acpi_backlight_native, 51 + acpi_backlight_nvidia_wmi_ec, 52 + acpi_backlight_apple_gmux, 51 53 }; 52 54 53 55 #if IS_ENABLED(CONFIG_ACPI_VIDEO) 54 56 extern int acpi_video_register(void); 55 57 extern void acpi_video_unregister(void); 58 + extern void acpi_video_register_backlight(void); 56 59 extern int acpi_video_get_edid(struct acpi_device *device, int type, 57 60 int device_id, void **edid); 58 61 extern enum acpi_backlight_type acpi_video_get_backlight_type(void); 59 - extern void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type); 62 + extern bool acpi_video_backlight_use_native(void); 60 63 /* 61 64 * Note: The value returned by acpi_video_handles_brightness_key_presses() 62 65 * may change over time and should not be cached. ··· 71 68 #else 72 69 static inline int acpi_video_register(void) { return -ENODEV; } 73 70 static inline void acpi_video_unregister(void) { return; } 71 + static inline void acpi_video_register_backlight(void) { return; } 74 72 static inline int acpi_video_get_edid(struct acpi_device *device, int type, 75 73 int device_id, void **edid) 76 74 { ··· 81 77 { 82 78 return acpi_backlight_vendor; 83 79 } 84 - static inline void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type) 80 + static inline bool acpi_video_backlight_use_native(void) 85 81 { 82 + return true; 86 83 } 87 84 static inline bool acpi_video_handles_brightness_key_presses(void) 88 85 {
+76
include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. 4 + */ 5 + 6 + #ifndef __PLATFORM_DATA_X86_NVIDIA_WMI_EC_BACKLIGHT_H 7 + #define __PLATFORM_DATA_X86_NVIDIA_WMI_EC_BACKLIGHT_H 8 + 9 + #define WMI_BRIGHTNESS_GUID "603E9613-EF25-4338-A3D0-C46177516DB7" 10 + 11 + /** 12 + * enum wmi_brightness_method - WMI method IDs 13 + * @WMI_BRIGHTNESS_METHOD_LEVEL: Get/Set EC brightness level status 14 + * @WMI_BRIGHTNESS_METHOD_SOURCE: Get/Set EC Brightness Source 15 + */ 16 + enum wmi_brightness_method { 17 + WMI_BRIGHTNESS_METHOD_LEVEL = 1, 18 + WMI_BRIGHTNESS_METHOD_SOURCE = 2, 19 + WMI_BRIGHTNESS_METHOD_MAX 20 + }; 21 + 22 + /** 23 + * enum wmi_brightness_mode - Operation mode for WMI-wrapped method 24 + * @WMI_BRIGHTNESS_MODE_GET: Get the current brightness level/source. 25 + * @WMI_BRIGHTNESS_MODE_SET: Set the brightness level. 26 + * @WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL: Get the maximum brightness level. This 27 + * is only valid when the WMI method is 28 + * %WMI_BRIGHTNESS_METHOD_LEVEL. 29 + */ 30 + enum wmi_brightness_mode { 31 + WMI_BRIGHTNESS_MODE_GET = 0, 32 + WMI_BRIGHTNESS_MODE_SET = 1, 33 + WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL = 2, 34 + WMI_BRIGHTNESS_MODE_MAX 35 + }; 36 + 37 + /** 38 + * enum wmi_brightness_source - Backlight brightness control source selection 39 + * @WMI_BRIGHTNESS_SOURCE_GPU: Backlight brightness is controlled by the GPU. 40 + * @WMI_BRIGHTNESS_SOURCE_EC: Backlight brightness is controlled by the 41 + * system's Embedded Controller (EC). 42 + * @WMI_BRIGHTNESS_SOURCE_AUX: Backlight brightness is controlled over the 43 + * DisplayPort AUX channel. 44 + */ 45 + enum wmi_brightness_source { 46 + WMI_BRIGHTNESS_SOURCE_GPU = 1, 47 + WMI_BRIGHTNESS_SOURCE_EC = 2, 48 + WMI_BRIGHTNESS_SOURCE_AUX = 3, 49 + WMI_BRIGHTNESS_SOURCE_MAX 50 + }; 51 + 52 + /** 53 + * struct wmi_brightness_args - arguments for the WMI-wrapped ACPI method 54 + * @mode: Pass in an &enum wmi_brightness_mode value to select between 55 + * getting or setting a value. 56 + * @val: In parameter for value to set when using %WMI_BRIGHTNESS_MODE_SET 57 + * mode. Not used in conjunction with %WMI_BRIGHTNESS_MODE_GET or 58 + * %WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL mode. 59 + * @ret: Out parameter returning retrieved value when operating in 60 + * %WMI_BRIGHTNESS_MODE_GET or %WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL 61 + * mode. Not used in %WMI_BRIGHTNESS_MODE_SET mode. 62 + * @ignored: Padding; not used. The ACPI method expects a 24 byte params struct. 63 + * 64 + * This is the parameters structure for the WmiBrightnessNotify ACPI method as 65 + * wrapped by WMI. The value passed in to @val or returned by @ret will be a 66 + * brightness value when the WMI method ID is %WMI_BRIGHTNESS_METHOD_LEVEL, or 67 + * an &enum wmi_brightness_source value with %WMI_BRIGHTNESS_METHOD_SOURCE. 68 + */ 69 + struct wmi_brightness_args { 70 + u32 mode; 71 + u32 val; 72 + u32 ret; 73 + u32 ignored[3]; 74 + }; 75 + 76 + #endif