forked from Minki/linux
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. -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmMVsogUHGhkZWdvZWRl QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9yy6wgAlig+7hkq940L62lTpj0g2gNQv8zc HCsMpnU7dnJcZYaEvIjouZhf33ZbN52c0fQq2JWjt7fFX04LLyIiyrJ26Lc293JR ++yXpJcVoewRGqApy/P3Z05TKUCLll5bexvK4t8isnhOtEXD/nDPWKTLIV2Kd1DK nLY4KgRznXZ85RhYheUEdidZ7Lwlzt1JVBMq7tpnzu3nVdDExyZmqlqCUITcLynu ysuASQGr0D2i+1vb9eifHIA3xsQO0S37Bv62aBMBKxB6B8Fz1DYr8VA2YvoT82Hv IFT0hzCCZ/63Ljga05O78TwraxAQX0RvZWqjqGgnZg6fIBh2hxUiqeQY6g== =SA1R -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iHUEABMIAB0WIQTXEe0+DlZaRlgM8LOIQ8rmN6G3ywUCYyG6jgAKCRCIQ8rmN6G3 y3JSAQCKELIhrWPrqAixxWn3OWcaU9PHb4Uhf9Qg3sLL2Bm2TAEAuT8iJ0Kssakg GKWScS5nj+8kbFm0J067JLOOYjvTxEI= =42X0 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
3f1a3a28e9
@ -679,6 +679,74 @@ Contact: Sam Ravnborg
|
||||
|
||||
Level: Advanced
|
||||
|
||||
Brightness handling on devices with multiple internal panels
|
||||
============================================================
|
||||
|
||||
On x86/ACPI devices there can be multiple backlight firmware interfaces:
|
||||
(ACPI) video, vendor specific and others. As well as direct/native (PWM)
|
||||
register programming by the KMS driver.
|
||||
|
||||
To deal with this backlight drivers used on x86/ACPI call
|
||||
acpi_video_get_backlight_type() which has heuristics (+quirks) to select
|
||||
which backlight interface to use; and backlight drivers which do not match
|
||||
the returned type will not register themselves, so that only one backlight
|
||||
device gets registered (in a single GPU setup, see below).
|
||||
|
||||
At the moment this more or less assumes that there will only
|
||||
be 1 (internal) panel on a system.
|
||||
|
||||
On systems with 2 panels this may be a problem, depending on
|
||||
what interface acpi_video_get_backlight_type() selects:
|
||||
|
||||
1. native: in this case the KMS driver is expected to know which backlight
|
||||
device belongs to which output so everything should just work.
|
||||
2. video: this does support controlling multiple backlights, but some work
|
||||
will need to be done to get the output <-> backlight device mapping
|
||||
|
||||
The above assumes both panels will require the same backlight interface type.
|
||||
Things will break on systems with multiple panels where the 2 panels need
|
||||
a different type of control. E.g. one panel needs ACPI video backlight control,
|
||||
where as the other is using native backlight control. Currently in this case
|
||||
only one of the 2 required backlight devices will get registered, based on
|
||||
the acpi_video_get_backlight_type() return value.
|
||||
|
||||
If this (theoretical) case ever shows up, then supporting this will need some
|
||||
work. A possible solution here would be to pass a device and connector-name
|
||||
to acpi_video_get_backlight_type() so that it can deal with this.
|
||||
|
||||
Note in a way we already have a case where userspace sees 2 panels,
|
||||
in dual GPU laptop setups with a mux. On those systems we may see
|
||||
either 2 native backlight devices; or 2 native backlight devices.
|
||||
|
||||
Userspace already has code to deal with this by detecting if the related
|
||||
panel is active (iow which way the mux between the GPU and the panels
|
||||
points) and then uses that backlight device. Userspace here very much
|
||||
assumes a single panel though. It picks only 1 of the 2 backlight devices
|
||||
and then only uses that one.
|
||||
|
||||
Note that all userspace code (that I know off) is currently hardcoded
|
||||
to assume a single panel.
|
||||
|
||||
Before the recent changes to not register multiple (e.g. video + native)
|
||||
/sys/class/backlight devices for a single panel (on a single GPU laptop),
|
||||
userspace would see multiple backlight devices all controlling the same
|
||||
backlight.
|
||||
|
||||
To deal with this userspace had to always picks one preferred device under
|
||||
/sys/class/backlight and will ignore the others. So to support brightness
|
||||
control on multiple panels userspace will need to be updated too.
|
||||
|
||||
There are plans to allow brightness control through the KMS API by adding
|
||||
a "display brightness" property to drm_connector objects for panels. This
|
||||
solves a number of issues with the /sys/class/backlight API, including not
|
||||
being able to map a sysfs backlight device to a specific connector. Any
|
||||
userspace changes to add support for brightness control on devices with
|
||||
multiple panels really should build on top of this new KMS property.
|
||||
|
||||
Contact: Hans de Goede
|
||||
|
||||
Level: Advanced
|
||||
|
||||
Outside DRM
|
||||
===========
|
||||
|
||||
|
@ -14532,6 +14532,7 @@ M: Daniel Dadap <ddadap@nvidia.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/platform/x86/nvidia-wmi-ec-backlight.c
|
||||
F: include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h
|
||||
|
||||
NVM EXPRESS DRIVER
|
||||
M: Keith Busch <kbusch@kernel.org>
|
||||
|
@ -212,6 +212,7 @@ config ACPI_VIDEO
|
||||
tristate "Video"
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
depends on INPUT
|
||||
depends on ACPI_WMI || !X86
|
||||
select THERMAL
|
||||
help
|
||||
This driver implements the ACPI Extensions For Display Adapters
|
||||
|
@ -73,6 +73,16 @@ module_param(device_id_scheme, bool, 0444);
|
||||
static int only_lcd = -1;
|
||||
module_param(only_lcd, int, 0444);
|
||||
|
||||
/*
|
||||
* Display probing is known to take up to 5 seconds, so delay the fallback
|
||||
* backlight registration by 5 seconds + 3 seconds for some extra margin.
|
||||
*/
|
||||
static int register_backlight_delay = 8;
|
||||
module_param(register_backlight_delay, int, 0444);
|
||||
MODULE_PARM_DESC(register_backlight_delay,
|
||||
"Delay in seconds before doing fallback (non GPU driver triggered) "
|
||||
"backlight registration, set to 0 to disable.");
|
||||
|
||||
static bool may_report_brightness_keys;
|
||||
static int register_count;
|
||||
static DEFINE_MUTEX(register_count_mutex);
|
||||
@ -81,7 +91,9 @@ static LIST_HEAD(video_bus_head);
|
||||
static int acpi_video_bus_add(struct acpi_device *device);
|
||||
static int acpi_video_bus_remove(struct acpi_device *device);
|
||||
static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
|
||||
void acpi_video_detect_exit(void);
|
||||
static void acpi_video_bus_register_backlight_work(struct work_struct *ignored);
|
||||
static DECLARE_DELAYED_WORK(video_bus_register_backlight_work,
|
||||
acpi_video_bus_register_backlight_work);
|
||||
|
||||
/*
|
||||
* Indices in the _BCL method response: the first two items are special,
|
||||
@ -1859,8 +1871,6 @@ static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
|
||||
if (video->backlight_registered)
|
||||
return 0;
|
||||
|
||||
acpi_video_run_bcl_for_osi(video);
|
||||
|
||||
if (acpi_video_get_backlight_type() != acpi_backlight_video)
|
||||
return 0;
|
||||
|
||||
@ -2086,7 +2096,11 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||
list_add_tail(&video->entry, &video_bus_head);
|
||||
mutex_unlock(&video_list_lock);
|
||||
|
||||
acpi_video_bus_register_backlight(video);
|
||||
/*
|
||||
* The userspace visible backlight_device gets registered separately
|
||||
* from acpi_video_register_backlight().
|
||||
*/
|
||||
acpi_video_run_bcl_for_osi(video);
|
||||
acpi_video_bus_add_notify_handler(video);
|
||||
|
||||
return 0;
|
||||
@ -2111,20 +2125,25 @@ static int acpi_video_bus_remove(struct acpi_device *device)
|
||||
|
||||
video = acpi_driver_data(device);
|
||||
|
||||
acpi_video_bus_remove_notify_handler(video);
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
acpi_video_bus_put_devices(video);
|
||||
|
||||
mutex_lock(&video_list_lock);
|
||||
list_del(&video->entry);
|
||||
mutex_unlock(&video_list_lock);
|
||||
|
||||
acpi_video_bus_remove_notify_handler(video);
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
acpi_video_bus_put_devices(video);
|
||||
|
||||
kfree(video->attached_array);
|
||||
kfree(video);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_video_bus_register_backlight_work(struct work_struct *ignored)
|
||||
{
|
||||
acpi_video_register_backlight();
|
||||
}
|
||||
|
||||
static int __init is_i740(struct pci_dev *dev)
|
||||
{
|
||||
if (dev->device == 0x00D1)
|
||||
@ -2235,6 +2254,18 @@ int acpi_video_register(void)
|
||||
*/
|
||||
register_count = 1;
|
||||
|
||||
/*
|
||||
* acpi_video_bus_add() skips registering the userspace visible
|
||||
* backlight_device. The intend is for this to be registered by the
|
||||
* drm/kms driver calling acpi_video_register_backlight() *after* it is
|
||||
* done setting up its own native backlight device. The delayed work
|
||||
* ensures that acpi_video_register_backlight() always gets called
|
||||
* eventually, in case there is no drm/kms driver or it is disabled.
|
||||
*/
|
||||
if (register_backlight_delay)
|
||||
schedule_delayed_work(&video_bus_register_backlight_work,
|
||||
register_backlight_delay * HZ);
|
||||
|
||||
leave:
|
||||
mutex_unlock(®ister_count_mutex);
|
||||
return ret;
|
||||
@ -2245,6 +2276,7 @@ void acpi_video_unregister(void)
|
||||
{
|
||||
mutex_lock(®ister_count_mutex);
|
||||
if (register_count) {
|
||||
cancel_delayed_work_sync(&video_bus_register_backlight_work);
|
||||
acpi_bus_unregister_driver(&acpi_video_bus);
|
||||
register_count = 0;
|
||||
may_report_brightness_keys = false;
|
||||
@ -2253,19 +2285,16 @@ void acpi_video_unregister(void)
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_unregister);
|
||||
|
||||
void acpi_video_unregister_backlight(void)
|
||||
void acpi_video_register_backlight(void)
|
||||
{
|
||||
struct acpi_video_bus *video;
|
||||
|
||||
mutex_lock(®ister_count_mutex);
|
||||
if (register_count) {
|
||||
mutex_lock(&video_list_lock);
|
||||
list_for_each_entry(video, &video_bus_head, entry)
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
mutex_unlock(&video_list_lock);
|
||||
}
|
||||
mutex_unlock(®ister_count_mutex);
|
||||
mutex_lock(&video_list_lock);
|
||||
list_for_each_entry(video, &video_bus_head, entry)
|
||||
acpi_video_bus_register_backlight(video);
|
||||
mutex_unlock(&video_list_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_register_backlight);
|
||||
|
||||
bool acpi_video_handles_brightness_key_presses(void)
|
||||
{
|
||||
@ -2302,7 +2331,6 @@ static int __init acpi_video_init(void)
|
||||
|
||||
static void __exit acpi_video_exit(void)
|
||||
{
|
||||
acpi_video_detect_exit();
|
||||
acpi_video_unregister();
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,9 @@
|
||||
* Otherwise vendor specific drivers like thinkpad_acpi, asus-laptop,
|
||||
* sony_acpi,... can take care about backlight brightness.
|
||||
*
|
||||
* Backlight drivers can use acpi_video_get_backlight_type() to determine
|
||||
* which driver should handle the backlight.
|
||||
* Backlight drivers can use acpi_video_get_backlight_type() to determine which
|
||||
* driver should handle the backlight. RAW/GPU-driver backlight drivers must
|
||||
* use the acpi_video_backlight_use_native() helper for this.
|
||||
*
|
||||
* If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m)
|
||||
* this file will not be compiled and acpi_video_get_backlight_type() will
|
||||
@ -27,20 +28,16 @@
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/apple-gmux.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_data/x86/nvidia-wmi-ec-backlight.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <acpi/video.h>
|
||||
|
||||
void acpi_video_unregister_backlight(void);
|
||||
|
||||
static bool backlight_notifier_registered;
|
||||
static struct notifier_block backlight_nb;
|
||||
static struct work_struct backlight_notify_work;
|
||||
|
||||
static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef;
|
||||
static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef;
|
||||
|
||||
@ -78,6 +75,36 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
/* This depends on ACPI_WMI which is X86 only */
|
||||
#ifdef CONFIG_X86
|
||||
static bool nvidia_wmi_ec_supported(void)
|
||||
{
|
||||
struct wmi_brightness_args args = {
|
||||
.mode = WMI_BRIGHTNESS_MODE_GET,
|
||||
.val = 0,
|
||||
.ret = 0,
|
||||
};
|
||||
struct acpi_buffer buf = { (acpi_size)sizeof(args), &args };
|
||||
acpi_status status;
|
||||
|
||||
status = wmi_evaluate_method(WMI_BRIGHTNESS_GUID, 0,
|
||||
WMI_BRIGHTNESS_METHOD_SOURCE, &buf, &buf);
|
||||
if (ACPI_FAILURE(status))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If brightness is handled by the EC then nvidia-wmi-ec-backlight
|
||||
* should be used, else the GPU driver(s) should be used.
|
||||
*/
|
||||
return args.ret == WMI_BRIGHTNESS_SOURCE_EC;
|
||||
}
|
||||
#else
|
||||
static bool nvidia_wmi_ec_supported(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Force to use vendor driver when the ACPI device is known to be
|
||||
* buggy */
|
||||
static int video_detect_force_vendor(const struct dmi_system_id *d)
|
||||
@ -105,62 +132,142 @@ static int video_detect_force_none(const struct dmi_system_id *d)
|
||||
}
|
||||
|
||||
static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
/* On Samsung X360, the BIOS will set a flag (VDRV) if generic
|
||||
* ACPI backlight device is used. This flag will definitively break
|
||||
* the backlight interface (even the vendor interface) until next
|
||||
* reboot. It's why we should prevent video.ko from being used here
|
||||
* and we can't rely on a later call to acpi_video_unregister().
|
||||
*/
|
||||
{
|
||||
/* https://bugzilla.redhat.com/show_bug.cgi?id=1128309 */
|
||||
.callback = video_detect_force_vendor,
|
||||
/* X360 */
|
||||
/* Acer KAV80 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "X360"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Asus UL30VT */
|
||||
.matches = {
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Asus UL30VT */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Asus UL30A */
|
||||
.matches = {
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Asus UL30A */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* GIGABYTE GB-BXBT-2807 */
|
||||
.matches = {
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Asus X55U */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X55U"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Asus X101CH */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X101CH"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Asus X401U */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X401U"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Asus X501U */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X501U"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Asus 1015CX */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "1015CX"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* GIGABYTE GB-BXBT-2807 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Sony VPCEH3U1E */
|
||||
.matches = {
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Samsung N150/N210/N220 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Samsung NF110/NF210/NF310 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Samsung NC210 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Sony VPCEH3U1E */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Xiaomi Mi Pad 2 */
|
||||
.matches = {
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Xiaomi Mi Pad 2 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Toshiba models with Transflective display, these need to use
|
||||
* the toshiba_acpi vendor driver for proper Transflective handling.
|
||||
*/
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R500"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R600"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* These models have a working acpi_video backlight control, and using
|
||||
* native backlight causes a regression where backlight does not work
|
||||
@ -389,6 +496,41 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "JV50"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* https://bugzilla.redhat.com/show_bug.cgi?id=1012674 */
|
||||
.callback = video_detect_force_native,
|
||||
/* Acer Aspire 5741 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=42993 */
|
||||
.callback = video_detect_force_native,
|
||||
/* Acer Aspire 5750 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=42833 */
|
||||
.callback = video_detect_force_native,
|
||||
/* Acer Extensa 5235 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
/* Acer TravelMate 4750 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=207835 */
|
||||
.callback = video_detect_force_native,
|
||||
@ -400,120 +542,74 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
/* ASUSTeK COMPUTER INC. GA401 */
|
||||
.matches = {
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=36322 */
|
||||
.callback = video_detect_force_native,
|
||||
/* Acer TravelMate 5760 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
/* ASUSTeK COMPUTER INC. GA401 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA401"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
/* ASUSTeK COMPUTER INC. GA502 */
|
||||
.matches = {
|
||||
.callback = video_detect_force_native,
|
||||
/* ASUSTeK COMPUTER INC. GA502 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA502"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
/* ASUSTeK COMPUTER INC. GA503 */
|
||||
.matches = {
|
||||
.callback = video_detect_force_native,
|
||||
/* ASUSTeK COMPUTER INC. GA503 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA503"),
|
||||
},
|
||||
},
|
||||
/*
|
||||
* Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a
|
||||
* working native and video interface. However the default detection
|
||||
* mechanism first registers the video interface before unregistering
|
||||
* it again and switching to the native interface during boot. This
|
||||
* results in a dangling SBIOS request for backlight change for some
|
||||
* reason, causing the backlight to switch to ~2% once per boot on the
|
||||
* first power cord connect or disconnect event. Setting the native
|
||||
* interface explicitly circumvents this buggy behaviour, by avoiding
|
||||
* the unregistering process.
|
||||
*/
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
|
||||
.callback = video_detect_force_native,
|
||||
/* Asus UX303UB */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "AURA1501"),
|
||||
.callback = video_detect_force_native,
|
||||
/* Samsung N150P */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N150P"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N150P"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"),
|
||||
.callback = video_detect_force_native,
|
||||
/* Samsung N145P/N250P/N260P */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xNU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
|
||||
},
|
||||
},
|
||||
/*
|
||||
* The TongFang PF5PU1G, PF4NU1F, PF5NU1G, and PF5LUXG/TUXEDO BA15 Gen10,
|
||||
* Pulse 14/15 Gen1, and Pulse 15 Gen2 have the same problem as the Clevo
|
||||
* NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2. See the description
|
||||
* above.
|
||||
*/
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF5PU1G",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF4NU1F",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PF4NU1F"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF4NU1F",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PULSE1401"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF5NU1G",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PF5NU1G"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF5NU1G",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PULSE1501"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF5LUXG",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PF5LUXG"),
|
||||
.callback = video_detect_force_native,
|
||||
/* Samsung N250P */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N250P"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N250P"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Desktops which falsely report a backlight and which our heuristics
|
||||
* for this do not catch.
|
||||
@ -537,43 +633,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
{ },
|
||||
};
|
||||
|
||||
/* This uses a workqueue to avoid various locking ordering issues */
|
||||
static void acpi_video_backlight_notify_work(struct work_struct *work)
|
||||
{
|
||||
if (acpi_video_get_backlight_type() != acpi_backlight_video)
|
||||
acpi_video_unregister_backlight();
|
||||
}
|
||||
|
||||
static int acpi_video_backlight_notify(struct notifier_block *nb,
|
||||
unsigned long val, void *bd)
|
||||
{
|
||||
struct backlight_device *backlight = bd;
|
||||
|
||||
/* A raw bl registering may change video -> native */
|
||||
if (backlight->props.type == BACKLIGHT_RAW &&
|
||||
val == BACKLIGHT_REGISTERED)
|
||||
schedule_work(&backlight_notify_work);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine which type of backlight interface to use on this system,
|
||||
* First check cmdline, then dmi quirks, then do autodetect.
|
||||
*
|
||||
* The autodetect order is:
|
||||
* 1) Is the acpi-video backlight interface supported ->
|
||||
* no, use a vendor interface
|
||||
* 2) Is this a win8 "ready" BIOS and do we have a native interface ->
|
||||
* yes, use a native interface
|
||||
* 3) Else use the acpi-video interface
|
||||
*
|
||||
* Arguably the native on win8 check should be done first, but that would
|
||||
* be a behavior change, which may causes issues.
|
||||
*/
|
||||
enum acpi_backlight_type acpi_video_get_backlight_type(void)
|
||||
static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
|
||||
{
|
||||
static DEFINE_MUTEX(init_mutex);
|
||||
static bool nvidia_wmi_ec_present;
|
||||
static bool native_available;
|
||||
static bool init_done;
|
||||
static long video_caps;
|
||||
|
||||
@ -585,48 +653,60 @@ enum acpi_backlight_type acpi_video_get_backlight_type(void)
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_video, NULL,
|
||||
&video_caps, NULL);
|
||||
INIT_WORK(&backlight_notify_work,
|
||||
acpi_video_backlight_notify_work);
|
||||
backlight_nb.notifier_call = acpi_video_backlight_notify;
|
||||
backlight_nb.priority = 0;
|
||||
if (backlight_register_notifier(&backlight_nb) == 0)
|
||||
backlight_notifier_registered = true;
|
||||
nvidia_wmi_ec_present = nvidia_wmi_ec_supported();
|
||||
init_done = true;
|
||||
}
|
||||
if (native)
|
||||
native_available = true;
|
||||
mutex_unlock(&init_mutex);
|
||||
|
||||
/*
|
||||
* The below heuristics / detection steps are in order of descending
|
||||
* presedence. The commandline takes presedence over anything else.
|
||||
*/
|
||||
if (acpi_backlight_cmdline != acpi_backlight_undef)
|
||||
return acpi_backlight_cmdline;
|
||||
|
||||
/* DMI quirks override any autodetection. */
|
||||
if (acpi_backlight_dmi != acpi_backlight_undef)
|
||||
return acpi_backlight_dmi;
|
||||
|
||||
if (!(video_caps & ACPI_VIDEO_BACKLIGHT))
|
||||
return acpi_backlight_vendor;
|
||||
/* Special cases such as nvidia_wmi_ec and apple gmux. */
|
||||
if (nvidia_wmi_ec_present)
|
||||
return acpi_backlight_nvidia_wmi_ec;
|
||||
|
||||
if (acpi_osi_is_win8() && backlight_device_get_by_type(BACKLIGHT_RAW))
|
||||
return acpi_backlight_native;
|
||||
if (apple_gmux_present())
|
||||
return acpi_backlight_apple_gmux;
|
||||
|
||||
return acpi_backlight_video;
|
||||
/* On systems with ACPI video use either native or ACPI video. */
|
||||
if (video_caps & ACPI_VIDEO_BACKLIGHT) {
|
||||
/*
|
||||
* Windows 8 and newer no longer use the ACPI video interface,
|
||||
* so it often does not work. If the ACPI tables are written
|
||||
* for win8 and native brightness ctl is available, use that.
|
||||
*
|
||||
* The native check deliberately is inside the if acpi-video
|
||||
* block on older devices without acpi-video support native
|
||||
* is usually not the best choice.
|
||||
*/
|
||||
if (acpi_osi_is_win8() && native_available)
|
||||
return acpi_backlight_native;
|
||||
else
|
||||
return acpi_backlight_video;
|
||||
}
|
||||
|
||||
/* No ACPI video (old hw), use vendor specific fw methods. */
|
||||
return acpi_backlight_vendor;
|
||||
}
|
||||
|
||||
enum acpi_backlight_type acpi_video_get_backlight_type(void)
|
||||
{
|
||||
return __acpi_video_get_backlight_type(false);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_get_backlight_type);
|
||||
|
||||
/*
|
||||
* Set the preferred backlight interface type based on DMI info.
|
||||
* This function allows DMI blacklists to be implemented by external
|
||||
* platform drivers instead of putting a big blacklist in video_detect.c
|
||||
*/
|
||||
void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type)
|
||||
bool acpi_video_backlight_use_native(void)
|
||||
{
|
||||
acpi_backlight_dmi = type;
|
||||
/* Remove acpi-video backlight interface if it is no longer desired */
|
||||
if (acpi_video_get_backlight_type() != acpi_backlight_video)
|
||||
acpi_video_unregister_backlight();
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_set_dmi_backlight_type);
|
||||
|
||||
void __exit acpi_video_detect_exit(void)
|
||||
{
|
||||
if (backlight_notifier_registered)
|
||||
backlight_unregister_notifier(&backlight_nb);
|
||||
return __acpi_video_get_backlight_type(true) == acpi_backlight_native;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_backlight_use_native);
|
||||
|
@ -235,6 +235,13 @@ config DRM_RADEON
|
||||
select HWMON
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
select INTERVAL_TREE
|
||||
# radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work
|
||||
# ACPI_VIDEO's dependencies must also be selected.
|
||||
select INPUT if ACPI
|
||||
select ACPI_VIDEO if ACPI
|
||||
# On x86 ACPI_VIDEO also needs ACPI_WMI
|
||||
select X86_PLATFORM_DEVICES if ACPI && X86
|
||||
select ACPI_WMI if ACPI && X86
|
||||
help
|
||||
Choose this option if you have an ATI Radeon graphics card. There
|
||||
are both PCI and AGP versions. You don't need to choose this to
|
||||
@ -260,6 +267,13 @@ config DRM_AMDGPU
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
select INTERVAL_TREE
|
||||
select DRM_BUDDY
|
||||
# amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work
|
||||
# ACPI_VIDEO's dependencies must also be selected.
|
||||
select INPUT if ACPI
|
||||
select ACPI_VIDEO if ACPI
|
||||
# On x86 ACPI_VIDEO also needs ACPI_WMI
|
||||
select X86_PLATFORM_DEVICES if ACPI && X86
|
||||
select ACPI_WMI if ACPI && X86
|
||||
help
|
||||
Choose this option if you have a recent AMD Radeon graphics card.
|
||||
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include "amdgpu.h"
|
||||
@ -182,7 +184,12 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode
|
||||
return;
|
||||
|
||||
if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
|
||||
return;
|
||||
goto register_acpi_backlight;
|
||||
|
||||
if (!acpi_video_backlight_use_native()) {
|
||||
drm_info(dev, "Skipping amdgpu atom DIG backlight registration\n");
|
||||
goto register_acpi_backlight;
|
||||
}
|
||||
|
||||
pdata = kmalloc(sizeof(struct amdgpu_backlight_privdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
@ -218,6 +225,11 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode
|
||||
error:
|
||||
kfree(pdata);
|
||||
return;
|
||||
|
||||
register_acpi_backlight:
|
||||
/* Try registering an ACPI video backlight device instead. */
|
||||
acpi_video_register_backlight();
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -90,6 +90,8 @@
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
|
||||
|
||||
#include "dcn/dcn_1_0_offset.h"
|
||||
@ -4032,6 +4034,13 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
|
||||
amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps);
|
||||
dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL;
|
||||
|
||||
if (!acpi_video_backlight_use_native()) {
|
||||
drm_info(adev_to_drm(dm->adev), "Skipping amdgpu DM backlight registration\n");
|
||||
/* Try registering an ACPI video backlight device instead. */
|
||||
acpi_video_register_backlight();
|
||||
return;
|
||||
}
|
||||
|
||||
props.max_brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
props.brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
props.type = BACKLIGHT_RAW;
|
||||
|
@ -7,6 +7,8 @@ config DRM_GMA500
|
||||
select ACPI_VIDEO if ACPI
|
||||
select BACKLIGHT_CLASS_DEVICE if ACPI
|
||||
select INPUT if ACPI
|
||||
select X86_PLATFORM_DEVICES if ACPI
|
||||
select ACPI_WMI if ACPI
|
||||
help
|
||||
Say yes for an experimental 2D KMS framebuffer driver for the
|
||||
Intel GMA500 (Poulsbo), Intel GMA600 (Moorestown/Oak Trail) and
|
||||
|
@ -23,6 +23,8 @@ config DRM_I915
|
||||
# but for select to work, need to select ACPI_VIDEO's dependencies, ick
|
||||
select BACKLIGHT_CLASS_DEVICE if ACPI
|
||||
select INPUT if ACPI
|
||||
select X86_PLATFORM_DEVICES if ACPI
|
||||
select ACPI_WMI if ACPI
|
||||
select ACPI_VIDEO if ACPI
|
||||
select ACPI_BUTTON if ACPI
|
||||
select SYNC_FILE
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_acpi.h"
|
||||
@ -331,3 +332,29 @@ void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915)
|
||||
*/
|
||||
fwnode_handle_put(fwnode);
|
||||
}
|
||||
|
||||
void intel_acpi_video_register(struct drm_i915_private *i915)
|
||||
{
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct drm_connector *connector;
|
||||
|
||||
acpi_video_register();
|
||||
|
||||
/*
|
||||
* If i915 is driving an internal panel without registering its native
|
||||
* backlight handler try to register the acpi_video backlight.
|
||||
* For panels not driven by i915 another GPU driver may still register
|
||||
* a native backlight later and acpi_video_register_backlight() should
|
||||
* only be called after any native backlights have been registered.
|
||||
*/
|
||||
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
struct intel_panel *panel = &to_intel_connector(connector)->panel;
|
||||
|
||||
if (panel->backlight.funcs && !panel->backlight.device) {
|
||||
acpi_video_register_backlight();
|
||||
break;
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ void intel_unregister_dsm_handler(void);
|
||||
void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915);
|
||||
void intel_acpi_device_id_update(struct drm_i915_private *i915);
|
||||
void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915);
|
||||
void intel_acpi_video_register(struct drm_i915_private *i915);
|
||||
#else
|
||||
static inline void intel_register_dsm_handler(void) { return; }
|
||||
static inline void intel_unregister_dsm_handler(void) { return; }
|
||||
@ -23,6 +24,8 @@ static inline
|
||||
void intel_acpi_device_id_update(struct drm_i915_private *i915) { return; }
|
||||
static inline
|
||||
void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) { return; }
|
||||
static inline
|
||||
void intel_acpi_video_register(struct drm_i915_private *i915) { return; }
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#endif /* __INTEL_ACPI_H__ */
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "intel_backlight.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_de.h"
|
||||
@ -950,6 +952,11 @@ int intel_backlight_device_register(struct intel_connector *connector)
|
||||
|
||||
WARN_ON(panel->backlight.max == 0);
|
||||
|
||||
if (!acpi_video_backlight_use_native()) {
|
||||
drm_info(&i915->drm, "Skipping intel_backlight registration\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.type = BACKLIGHT_RAW;
|
||||
|
||||
|
@ -9089,7 +9089,7 @@ void intel_display_driver_register(struct drm_i915_private *i915)
|
||||
|
||||
/* Must be done after probing outputs */
|
||||
intel_opregion_register(i915);
|
||||
acpi_video_register();
|
||||
intel_acpi_video_register(i915);
|
||||
|
||||
intel_audio_init(i915);
|
||||
|
||||
|
@ -386,3 +386,13 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector)
|
||||
|
||||
return kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
|
||||
}
|
||||
|
||||
bool nouveau_acpi_video_backlight_use_native(void)
|
||||
{
|
||||
return acpi_video_backlight_use_native();
|
||||
}
|
||||
|
||||
void nouveau_acpi_video_register_backlight(void)
|
||||
{
|
||||
acpi_video_register_backlight();
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ void nouveau_register_dsm_handler(void);
|
||||
void nouveau_unregister_dsm_handler(void);
|
||||
void nouveau_switcheroo_optimus_dsm(void);
|
||||
void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *);
|
||||
bool nouveau_acpi_video_backlight_use_native(void);
|
||||
void nouveau_acpi_video_register_backlight(void);
|
||||
#else
|
||||
static inline bool nouveau_is_optimus(void) { return false; };
|
||||
static inline bool nouveau_is_v1_dsm(void) { return false; };
|
||||
@ -18,6 +20,8 @@ static inline void nouveau_register_dsm_handler(void) {}
|
||||
static inline void nouveau_unregister_dsm_handler(void) {}
|
||||
static inline void nouveau_switcheroo_optimus_dsm(void) {}
|
||||
static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; }
|
||||
static inline bool nouveau_acpi_video_backlight_use_native(void) { return true; }
|
||||
static inline void nouveau_acpi_video_register_backlight(void) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "nouveau_reg.h"
|
||||
#include "nouveau_encoder.h"
|
||||
#include "nouveau_connector.h"
|
||||
#include "nouveau_acpi.h"
|
||||
|
||||
static struct ida bl_ida;
|
||||
#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
|
||||
@ -405,6 +406,11 @@ nouveau_backlight_init(struct drm_connector *connector)
|
||||
goto fail_alloc;
|
||||
}
|
||||
|
||||
if (!nouveau_acpi_video_backlight_use_native()) {
|
||||
NV_INFO(drm, "Skipping nv_backlight registration\n");
|
||||
goto fail_alloc;
|
||||
}
|
||||
|
||||
if (!nouveau_get_backlight_name(backlight_name, bl)) {
|
||||
NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
|
||||
goto fail_alloc;
|
||||
@ -430,6 +436,13 @@ nouveau_backlight_init(struct drm_connector *connector)
|
||||
|
||||
fail_alloc:
|
||||
kfree(bl);
|
||||
/*
|
||||
* If we get here we have an internal panel, but no nv_backlight,
|
||||
* try registering an ACPI video backlight device instead.
|
||||
*/
|
||||
if (ret == 0)
|
||||
nouveau_acpi_video_register_backlight();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "atom.h"
|
||||
#include "radeon_atombios.h"
|
||||
#include "radeon.h"
|
||||
@ -209,6 +211,11 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
|
||||
if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
|
||||
return;
|
||||
|
||||
if (!acpi_video_backlight_use_native()) {
|
||||
drm_info(dev, "Skipping radeon atom DIG backlight registration\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
DRM_ERROR("Memory allocation failed\n");
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "radeon.h"
|
||||
#include "radeon_atombios.h"
|
||||
#include "radeon_legacy_encoders.h"
|
||||
@ -167,7 +169,7 @@ static void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
|
||||
return;
|
||||
|
||||
if (radeon_backlight == 0) {
|
||||
return;
|
||||
use_bl = false;
|
||||
} else if (radeon_backlight == 1) {
|
||||
use_bl = true;
|
||||
} else if (radeon_backlight == -1) {
|
||||
@ -193,6 +195,13 @@ static void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
|
||||
else
|
||||
radeon_legacy_backlight_init(radeon_encoder, connector);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no native backlight device (which may happen even when
|
||||
* use_bl==true) try registering an ACPI video backlight device instead.
|
||||
*/
|
||||
if (!rdev->mode_info.bl_encoder)
|
||||
acpi_video_register_backlight();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include <drm/drm_util.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "radeon.h"
|
||||
#include "radeon_asic.h"
|
||||
#include "radeon_legacy_encoders.h"
|
||||
@ -387,6 +389,11 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!acpi_video_backlight_use_native()) {
|
||||
drm_info(dev, "Skipping radeon legacy LVDS backlight registration\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
DRM_ERROR("Memory allocation failed\n");
|
||||
|
@ -93,6 +93,7 @@ config PEAQ_WMI
|
||||
|
||||
config NVIDIA_WMI_EC_BACKLIGHT
|
||||
tristate "EC Backlight Driver for Hybrid Graphics Notebook Systems"
|
||||
depends on ACPI_VIDEO
|
||||
depends on ACPI_WMI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
|
@ -643,69 +643,6 @@ static const struct dmi_system_id non_acer_quirks[] __initconst = {
|
||||
{}
|
||||
};
|
||||
|
||||
static int __init
|
||||
video_set_backlight_video_vendor(const struct dmi_system_id *d)
|
||||
{
|
||||
interface->capability &= ~ACER_CAP_BRIGHTNESS;
|
||||
pr_info("Brightness must be controlled by generic video driver\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id video_vendor_dmi_table[] __initconst = {
|
||||
{
|
||||
.callback = video_set_backlight_video_vendor,
|
||||
.ident = "Acer TravelMate 4750",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_set_backlight_video_vendor,
|
||||
.ident = "Acer Extensa 5235",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_set_backlight_video_vendor,
|
||||
.ident = "Acer TravelMate 5760",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_set_backlight_video_vendor,
|
||||
.ident = "Acer Aspire 5750",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_set_backlight_video_vendor,
|
||||
.ident = "Acer Aspire 5741",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Note no video_set_backlight_video_vendor, we must use the
|
||||
* acer interface, as there is no native backlight interface.
|
||||
*/
|
||||
.ident = "Acer KAV80",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
/* Find which quirks are needed for a particular vendor/ model pair */
|
||||
static void __init find_quirks(void)
|
||||
{
|
||||
@ -2477,9 +2414,6 @@ static int __init acer_wmi_init(void)
|
||||
|
||||
set_quirks();
|
||||
|
||||
if (dmi_check_system(video_vendor_dmi_table))
|
||||
acpi_video_set_dmi_backlight_type(acpi_backlight_vendor);
|
||||
|
||||
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
|
||||
interface->capability &= ~ACER_CAP_BRIGHTNESS;
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
#include <acpi/video.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/**
|
||||
@ -694,7 +693,6 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
|
||||
* backlight control and supports more levels than other options.
|
||||
* Disable the other backlight choices.
|
||||
*/
|
||||
acpi_video_set_dmi_backlight_type(acpi_backlight_vendor);
|
||||
apple_bl_unregister();
|
||||
|
||||
gmux_data->power_state = VGA_SWITCHEROO_ON;
|
||||
@ -804,7 +802,6 @@ static void gmux_remove(struct pnp_dev *pnp)
|
||||
apple_gmux_data = NULL;
|
||||
kfree(gmux_data);
|
||||
|
||||
acpi_video_register();
|
||||
apple_bl_register();
|
||||
}
|
||||
|
||||
|
@ -79,12 +79,10 @@ static struct quirk_entry quirk_asus_q500a = {
|
||||
|
||||
/*
|
||||
* For those machines that need software to control bt/wifi status
|
||||
* and can't adjust brightness through ACPI interface
|
||||
* and have duplicate events(ACPI and WMI) for display toggle
|
||||
*/
|
||||
static struct quirk_entry quirk_asus_x55u = {
|
||||
.wapf = 4,
|
||||
.wmi_backlight_power = true,
|
||||
.wmi_backlight_set_devstate = true,
|
||||
.no_display_toggle = true,
|
||||
};
|
||||
@ -99,11 +97,6 @@ static struct quirk_entry quirk_asus_x200ca = {
|
||||
.wmi_backlight_set_devstate = true,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_asus_ux303ub = {
|
||||
.wmi_backlight_native = true,
|
||||
.wmi_backlight_set_devstate = true,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_asus_x550lb = {
|
||||
.wmi_backlight_set_devstate = true,
|
||||
.xusb2pr = 0x01D9,
|
||||
@ -147,11 +140,6 @@ static const struct dmi_system_id asus_quirks[] = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "U32U"),
|
||||
},
|
||||
/*
|
||||
* Note this machine has a Brazos APU, and most Brazos Asus
|
||||
* machines need quirk_asus_x55u / wmi_backlight_power but
|
||||
* here acpi-video seems to work fine for backlight control.
|
||||
*/
|
||||
.driver_data = &quirk_asus_wapf4,
|
||||
},
|
||||
{
|
||||
@ -379,15 +367,6 @@ static const struct dmi_system_id asus_quirks[] = {
|
||||
},
|
||||
.driver_data = &quirk_asus_x200ca,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. UX303UB",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"),
|
||||
},
|
||||
.driver_data = &quirk_asus_ux303ub,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. UX330UAK",
|
||||
|
@ -3553,7 +3553,6 @@ static int asus_wmi_add(struct platform_device *pdev)
|
||||
struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
|
||||
struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
|
||||
struct asus_wmi *asus;
|
||||
const char *chassis_type;
|
||||
acpi_status status;
|
||||
int err;
|
||||
u32 result;
|
||||
@ -3635,18 +3634,6 @@ static int asus_wmi_add(struct platform_device *pdev)
|
||||
if (asus->driver->quirks->wmi_force_als_set)
|
||||
asus_wmi_set_als();
|
||||
|
||||
/* Some Asus desktop boards export an acpi-video backlight interface,
|
||||
stop this from showing up */
|
||||
chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
|
||||
if (chassis_type && !strcmp(chassis_type, "3"))
|
||||
acpi_video_set_dmi_backlight_type(acpi_backlight_vendor);
|
||||
|
||||
if (asus->driver->quirks->wmi_backlight_power)
|
||||
acpi_video_set_dmi_backlight_type(acpi_backlight_vendor);
|
||||
|
||||
if (asus->driver->quirks->wmi_backlight_native)
|
||||
acpi_video_set_dmi_backlight_type(acpi_backlight_native);
|
||||
|
||||
if (asus->driver->quirks->xusb2pr)
|
||||
asus_wmi_set_xusb2pr(asus);
|
||||
|
||||
|
@ -29,8 +29,6 @@ struct quirk_entry {
|
||||
bool hotplug_wireless;
|
||||
bool scalar_panel_brightness;
|
||||
bool store_backlight_power;
|
||||
bool wmi_backlight_power;
|
||||
bool wmi_backlight_native;
|
||||
bool wmi_backlight_set_devstate;
|
||||
bool wmi_force_als_set;
|
||||
bool use_kbd_dock_devid;
|
||||
|
@ -96,11 +96,6 @@ static struct quirk_entry quirk_asus_et2012_type3 = {
|
||||
.store_backlight_power = true,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_asus_x101ch = {
|
||||
/* We need this when ACPI function doesn't do this well */
|
||||
.wmi_backlight_power = true,
|
||||
};
|
||||
|
||||
static struct quirk_entry *quirks;
|
||||
|
||||
static void et2012_quirks(void)
|
||||
@ -151,25 +146,7 @@ static const struct dmi_system_id asus_quirks[] = {
|
||||
},
|
||||
.driver_data = &quirk_asus_unknown,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK Computer INC. X101CH",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X101CH"),
|
||||
},
|
||||
.driver_data = &quirk_asus_x101ch,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK Computer INC. 1015CX",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "1015CX"),
|
||||
},
|
||||
.driver_data = &quirk_asus_x101ch,
|
||||
},
|
||||
{},
|
||||
{}
|
||||
};
|
||||
|
||||
static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
|
||||
|
@ -7,73 +7,10 @@
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/x86/nvidia-wmi-ec-backlight.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/wmi.h>
|
||||
|
||||
/**
|
||||
* enum wmi_brightness_method - WMI method IDs
|
||||
* @WMI_BRIGHTNESS_METHOD_LEVEL: Get/Set EC brightness level status
|
||||
* @WMI_BRIGHTNESS_METHOD_SOURCE: Get/Set EC Brightness Source
|
||||
*/
|
||||
enum wmi_brightness_method {
|
||||
WMI_BRIGHTNESS_METHOD_LEVEL = 1,
|
||||
WMI_BRIGHTNESS_METHOD_SOURCE = 2,
|
||||
WMI_BRIGHTNESS_METHOD_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wmi_brightness_mode - Operation mode for WMI-wrapped method
|
||||
* @WMI_BRIGHTNESS_MODE_GET: Get the current brightness level/source.
|
||||
* @WMI_BRIGHTNESS_MODE_SET: Set the brightness level.
|
||||
* @WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL: Get the maximum brightness level. This
|
||||
* is only valid when the WMI method is
|
||||
* %WMI_BRIGHTNESS_METHOD_LEVEL.
|
||||
*/
|
||||
enum wmi_brightness_mode {
|
||||
WMI_BRIGHTNESS_MODE_GET = 0,
|
||||
WMI_BRIGHTNESS_MODE_SET = 1,
|
||||
WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL = 2,
|
||||
WMI_BRIGHTNESS_MODE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wmi_brightness_source - Backlight brightness control source selection
|
||||
* @WMI_BRIGHTNESS_SOURCE_GPU: Backlight brightness is controlled by the GPU.
|
||||
* @WMI_BRIGHTNESS_SOURCE_EC: Backlight brightness is controlled by the
|
||||
* system's Embedded Controller (EC).
|
||||
* @WMI_BRIGHTNESS_SOURCE_AUX: Backlight brightness is controlled over the
|
||||
* DisplayPort AUX channel.
|
||||
*/
|
||||
enum wmi_brightness_source {
|
||||
WMI_BRIGHTNESS_SOURCE_GPU = 1,
|
||||
WMI_BRIGHTNESS_SOURCE_EC = 2,
|
||||
WMI_BRIGHTNESS_SOURCE_AUX = 3,
|
||||
WMI_BRIGHTNESS_SOURCE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wmi_brightness_args - arguments for the WMI-wrapped ACPI method
|
||||
* @mode: Pass in an &enum wmi_brightness_mode value to select between
|
||||
* getting or setting a value.
|
||||
* @val: In parameter for value to set when using %WMI_BRIGHTNESS_MODE_SET
|
||||
* mode. Not used in conjunction with %WMI_BRIGHTNESS_MODE_GET or
|
||||
* %WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL mode.
|
||||
* @ret: Out parameter returning retrieved value when operating in
|
||||
* %WMI_BRIGHTNESS_MODE_GET or %WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL
|
||||
* mode. Not used in %WMI_BRIGHTNESS_MODE_SET mode.
|
||||
* @ignored: Padding; not used. The ACPI method expects a 24 byte params struct.
|
||||
*
|
||||
* This is the parameters structure for the WmiBrightnessNotify ACPI method as
|
||||
* wrapped by WMI. The value passed in to @val or returned by @ret will be a
|
||||
* brightness value when the WMI method ID is %WMI_BRIGHTNESS_METHOD_LEVEL, or
|
||||
* an &enum wmi_brightness_source value with %WMI_BRIGHTNESS_METHOD_SOURCE.
|
||||
*/
|
||||
struct wmi_brightness_args {
|
||||
u32 mode;
|
||||
u32 val;
|
||||
u32 ret;
|
||||
u32 ignored[3];
|
||||
};
|
||||
#include <acpi/video.h>
|
||||
|
||||
/**
|
||||
* wmi_brightness_notify() - helper function for calling WMI-wrapped ACPI method
|
||||
@ -151,19 +88,10 @@ static int nvidia_wmi_ec_backlight_probe(struct wmi_device *wdev, const void *ct
|
||||
{
|
||||
struct backlight_properties props = {};
|
||||
struct backlight_device *bdev;
|
||||
u32 source;
|
||||
int ret;
|
||||
|
||||
ret = wmi_brightness_notify(wdev, WMI_BRIGHTNESS_METHOD_SOURCE,
|
||||
WMI_BRIGHTNESS_MODE_GET, &source);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* This driver is only to be used when brightness control is handled
|
||||
* by the EC; otherwise, the GPU driver(s) should control brightness.
|
||||
*/
|
||||
if (source != WMI_BRIGHTNESS_SOURCE_EC)
|
||||
/* drivers/acpi/video_detect.c also checks that SOURCE == EC */
|
||||
if (acpi_video_get_backlight_type() != acpi_backlight_nvidia_wmi_ec)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
@ -191,8 +119,6 @@ static int nvidia_wmi_ec_backlight_probe(struct wmi_device *wdev, const void *ct
|
||||
return PTR_ERR_OR_ZERO(bdev);
|
||||
}
|
||||
|
||||
#define WMI_BRIGHTNESS_GUID "603E9613-EF25-4338-A3D0-C46177516DB7"
|
||||
|
||||
static const struct wmi_device_id nvidia_wmi_ec_backlight_id_table[] = {
|
||||
{ .guid_string = WMI_BRIGHTNESS_GUID },
|
||||
{ }
|
||||
|
@ -356,23 +356,13 @@ struct samsung_laptop {
|
||||
};
|
||||
|
||||
struct samsung_quirks {
|
||||
bool broken_acpi_video;
|
||||
bool four_kbd_backlight_levels;
|
||||
bool enable_kbd_backlight;
|
||||
bool use_native_backlight;
|
||||
bool lid_handling;
|
||||
};
|
||||
|
||||
static struct samsung_quirks samsung_unknown = {};
|
||||
|
||||
static struct samsung_quirks samsung_broken_acpi_video = {
|
||||
.broken_acpi_video = true,
|
||||
};
|
||||
|
||||
static struct samsung_quirks samsung_use_native_backlight = {
|
||||
.use_native_backlight = true,
|
||||
};
|
||||
|
||||
static struct samsung_quirks samsung_np740u3e = {
|
||||
.four_kbd_backlight_levels = true,
|
||||
.enable_kbd_backlight = true,
|
||||
@ -1540,76 +1530,6 @@ static const struct dmi_system_id samsung_dmi_table[] __initconst = {
|
||||
},
|
||||
},
|
||||
/* Specific DMI ids for laptop with quirks */
|
||||
{
|
||||
.callback = samsung_dmi_matched,
|
||||
.ident = "N150P",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N150P"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N150P"),
|
||||
},
|
||||
.driver_data = &samsung_use_native_backlight,
|
||||
},
|
||||
{
|
||||
.callback = samsung_dmi_matched,
|
||||
.ident = "N145P/N250P/N260P",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
|
||||
},
|
||||
.driver_data = &samsung_use_native_backlight,
|
||||
},
|
||||
{
|
||||
.callback = samsung_dmi_matched,
|
||||
.ident = "N150/N210/N220",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
|
||||
},
|
||||
.driver_data = &samsung_broken_acpi_video,
|
||||
},
|
||||
{
|
||||
.callback = samsung_dmi_matched,
|
||||
.ident = "NF110/NF210/NF310",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
|
||||
},
|
||||
.driver_data = &samsung_broken_acpi_video,
|
||||
},
|
||||
{
|
||||
.callback = samsung_dmi_matched,
|
||||
.ident = "X360",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "X360"),
|
||||
},
|
||||
.driver_data = &samsung_broken_acpi_video,
|
||||
},
|
||||
{
|
||||
.callback = samsung_dmi_matched,
|
||||
.ident = "N250P",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N250P"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N250P"),
|
||||
},
|
||||
.driver_data = &samsung_use_native_backlight,
|
||||
},
|
||||
{
|
||||
.callback = samsung_dmi_matched,
|
||||
.ident = "NC210",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
|
||||
},
|
||||
.driver_data = &samsung_broken_acpi_video,
|
||||
},
|
||||
{
|
||||
.callback = samsung_dmi_matched,
|
||||
.ident = "730U3E/740U3E",
|
||||
@ -1654,15 +1574,8 @@ static int __init samsung_init(void)
|
||||
samsung->handle_backlight = true;
|
||||
samsung->quirks = quirks;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
if (samsung->quirks->broken_acpi_video)
|
||||
acpi_video_set_dmi_backlight_type(acpi_backlight_vendor);
|
||||
if (samsung->quirks->use_native_backlight)
|
||||
acpi_video_set_dmi_backlight_type(acpi_backlight_native);
|
||||
|
||||
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
|
||||
samsung->handle_backlight = false;
|
||||
#endif
|
||||
|
||||
ret = samsung_platform_init(samsung);
|
||||
if (ret)
|
||||
|
@ -271,14 +271,6 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = {
|
||||
{ KE_END, 0 },
|
||||
};
|
||||
|
||||
/*
|
||||
* List of models which have a broken acpi-video backlight interface and thus
|
||||
* need to use the toshiba (vendor) interface instead.
|
||||
*/
|
||||
static const struct dmi_system_id toshiba_vendor_backlight_dmi[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Utility
|
||||
*/
|
||||
@ -2881,14 +2873,6 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell acpi-video-detect code to prefer vendor backlight on all
|
||||
* systems with transflective backlight and on dmi matched systems.
|
||||
*/
|
||||
if (dev->tr_backlight_supported ||
|
||||
dmi_check_system(toshiba_vendor_backlight_dmi))
|
||||
acpi_video_set_dmi_backlight_type(acpi_backlight_vendor);
|
||||
|
||||
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
|
||||
return 0;
|
||||
|
||||
|
@ -48,15 +48,18 @@ enum acpi_backlight_type {
|
||||
acpi_backlight_video,
|
||||
acpi_backlight_vendor,
|
||||
acpi_backlight_native,
|
||||
acpi_backlight_nvidia_wmi_ec,
|
||||
acpi_backlight_apple_gmux,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACPI_VIDEO)
|
||||
extern int acpi_video_register(void);
|
||||
extern void acpi_video_unregister(void);
|
||||
extern void acpi_video_register_backlight(void);
|
||||
extern int acpi_video_get_edid(struct acpi_device *device, int type,
|
||||
int device_id, void **edid);
|
||||
extern enum acpi_backlight_type acpi_video_get_backlight_type(void);
|
||||
extern void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type);
|
||||
extern bool acpi_video_backlight_use_native(void);
|
||||
/*
|
||||
* Note: The value returned by acpi_video_handles_brightness_key_presses()
|
||||
* may change over time and should not be cached.
|
||||
@ -68,6 +71,7 @@ extern int acpi_video_get_levels(struct acpi_device *device,
|
||||
#else
|
||||
static inline int acpi_video_register(void) { return -ENODEV; }
|
||||
static inline void acpi_video_unregister(void) { return; }
|
||||
static inline void acpi_video_register_backlight(void) { return; }
|
||||
static inline int acpi_video_get_edid(struct acpi_device *device, int type,
|
||||
int device_id, void **edid)
|
||||
{
|
||||
@ -77,8 +81,9 @@ static inline enum acpi_backlight_type acpi_video_get_backlight_type(void)
|
||||
{
|
||||
return acpi_backlight_vendor;
|
||||
}
|
||||
static inline void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type)
|
||||
static inline bool acpi_video_backlight_use_native(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
static inline bool acpi_video_handles_brightness_key_presses(void)
|
||||
{
|
||||
|
76
include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h
Normal file
76
include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __PLATFORM_DATA_X86_NVIDIA_WMI_EC_BACKLIGHT_H
|
||||
#define __PLATFORM_DATA_X86_NVIDIA_WMI_EC_BACKLIGHT_H
|
||||
|
||||
#define WMI_BRIGHTNESS_GUID "603E9613-EF25-4338-A3D0-C46177516DB7"
|
||||
|
||||
/**
|
||||
* enum wmi_brightness_method - WMI method IDs
|
||||
* @WMI_BRIGHTNESS_METHOD_LEVEL: Get/Set EC brightness level status
|
||||
* @WMI_BRIGHTNESS_METHOD_SOURCE: Get/Set EC Brightness Source
|
||||
*/
|
||||
enum wmi_brightness_method {
|
||||
WMI_BRIGHTNESS_METHOD_LEVEL = 1,
|
||||
WMI_BRIGHTNESS_METHOD_SOURCE = 2,
|
||||
WMI_BRIGHTNESS_METHOD_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wmi_brightness_mode - Operation mode for WMI-wrapped method
|
||||
* @WMI_BRIGHTNESS_MODE_GET: Get the current brightness level/source.
|
||||
* @WMI_BRIGHTNESS_MODE_SET: Set the brightness level.
|
||||
* @WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL: Get the maximum brightness level. This
|
||||
* is only valid when the WMI method is
|
||||
* %WMI_BRIGHTNESS_METHOD_LEVEL.
|
||||
*/
|
||||
enum wmi_brightness_mode {
|
||||
WMI_BRIGHTNESS_MODE_GET = 0,
|
||||
WMI_BRIGHTNESS_MODE_SET = 1,
|
||||
WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL = 2,
|
||||
WMI_BRIGHTNESS_MODE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wmi_brightness_source - Backlight brightness control source selection
|
||||
* @WMI_BRIGHTNESS_SOURCE_GPU: Backlight brightness is controlled by the GPU.
|
||||
* @WMI_BRIGHTNESS_SOURCE_EC: Backlight brightness is controlled by the
|
||||
* system's Embedded Controller (EC).
|
||||
* @WMI_BRIGHTNESS_SOURCE_AUX: Backlight brightness is controlled over the
|
||||
* DisplayPort AUX channel.
|
||||
*/
|
||||
enum wmi_brightness_source {
|
||||
WMI_BRIGHTNESS_SOURCE_GPU = 1,
|
||||
WMI_BRIGHTNESS_SOURCE_EC = 2,
|
||||
WMI_BRIGHTNESS_SOURCE_AUX = 3,
|
||||
WMI_BRIGHTNESS_SOURCE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wmi_brightness_args - arguments for the WMI-wrapped ACPI method
|
||||
* @mode: Pass in an &enum wmi_brightness_mode value to select between
|
||||
* getting or setting a value.
|
||||
* @val: In parameter for value to set when using %WMI_BRIGHTNESS_MODE_SET
|
||||
* mode. Not used in conjunction with %WMI_BRIGHTNESS_MODE_GET or
|
||||
* %WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL mode.
|
||||
* @ret: Out parameter returning retrieved value when operating in
|
||||
* %WMI_BRIGHTNESS_MODE_GET or %WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL
|
||||
* mode. Not used in %WMI_BRIGHTNESS_MODE_SET mode.
|
||||
* @ignored: Padding; not used. The ACPI method expects a 24 byte params struct.
|
||||
*
|
||||
* This is the parameters structure for the WmiBrightnessNotify ACPI method as
|
||||
* wrapped by WMI. The value passed in to @val or returned by @ret will be a
|
||||
* brightness value when the WMI method ID is %WMI_BRIGHTNESS_METHOD_LEVEL, or
|
||||
* an &enum wmi_brightness_source value with %WMI_BRIGHTNESS_METHOD_SOURCE.
|
||||
*/
|
||||
struct wmi_brightness_args {
|
||||
u32 mode;
|
||||
u32 val;
|
||||
u32 ret;
|
||||
u32 ignored[3];
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user