Skip to content

Commit 39a0b86

Browse files
author
Herton R. Krzesinski
committed
Merge: Enable Nvidia backlight EC support to resolve backlight control issues
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/2857 The backlight of the laptop equipped with Nvidia hybrid graphic can't be configured and the user got a black screen when the system resumes working from the suspend mode. To resolve this, the Nvidia backlight EC driver should be backported to rhel from the upstream kernel. Dell had tested on Precision 7780 and reported the backport worked. A patch of filter_module.sh from Fedora was picked to avoid the dependency problem while compiling the kernel. The ACPI_VIDEO module has a dependency on the symbol wmi_evaluate_method. It needs to be added to otherwise it will cause compile errors. Build: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=54324872 Tested: Dell partner tested it on Dell Precision 7780 The system configurations are: - BIOS: 1.4.0 - Display mode: Hybrid Mode - Nvidia driver: 525.116.04 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2185526 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2221211 Signed-off-by: Kate Hsuan <hpa@redhat.com> Approved-by: Prarit Bhargava <prarit@redhat.com> Approved-by: David Arcari <darcari@redhat.com> Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
2 parents e5d248c + 10f29fd commit 39a0b86

File tree

10 files changed

+286
-1
lines changed

10 files changed

+286
-1
lines changed

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13656,6 +13656,13 @@ S: Maintained
1365613656
F: drivers/video/fbdev/nvidia/
1365713657
F: drivers/video/fbdev/riva/
1365813658

13659+
NVIDIA WMI EC BACKLIGHT DRIVER
13660+
M: Daniel Dadap <ddadap@nvidia.com>
13661+
L: platform-driver-x86@vger.kernel.org
13662+
S: Supported
13663+
F: drivers/platform/x86/nvidia-wmi-ec-backlight.c
13664+
F: include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h
13665+
1365913666
NVM EXPRESS DRIVER
1366013667
M: Keith Busch <kbusch@kernel.org>
1366113668
M: Jens Axboe <axboe@fb.com>

drivers/acpi/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ config ACPI_VIDEO
209209
tristate "Video"
210210
depends on BACKLIGHT_CLASS_DEVICE
211211
depends on INPUT
212+
depends on ACPI_WMI || !X86
212213
select THERMAL
213214
help
214215
This driver implements the ACPI Extensions For Display Adapters

drivers/acpi/video_detect.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/dmi.h>
3333
#include <linux/module.h>
3434
#include <linux/pci.h>
35+
#include <linux/platform_data/x86/nvidia-wmi-ec-backlight.h>
3536
#include <linux/types.h>
3637
#include <linux/workqueue.h>
3738
#include <acpi/video.h>
@@ -49,6 +50,8 @@ static void acpi_video_parse_cmdline(void)
4950
acpi_backlight_cmdline = acpi_backlight_video;
5051
if (!strcmp("native", acpi_video_backlight_string))
5152
acpi_backlight_cmdline = acpi_backlight_native;
53+
if (!strcmp("nvidia_wmi_ec", acpi_video_backlight_string))
54+
acpi_backlight_cmdline = acpi_backlight_nvidia_wmi_ec;
5255
if (!strcmp("none", acpi_video_backlight_string))
5356
acpi_backlight_cmdline = acpi_backlight_none;
5457
}
@@ -75,6 +78,36 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
7578
return AE_OK;
7679
}
7780

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+
78111
/* Force to use vendor driver when the ACPI device is known to be
79112
* buggy */
80113
static int video_detect_force_vendor(const struct dmi_system_id *d)
@@ -608,6 +641,7 @@ static bool prefer_native_over_acpi_video(void)
608641
enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto_detect)
609642
{
610643
static DEFINE_MUTEX(init_mutex);
644+
static bool nvidia_wmi_ec_present;
611645
static bool native_available;
612646
static bool init_done;
613647
static long video_caps;
@@ -620,6 +654,7 @@ enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto
620654
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
621655
ACPI_UINT32_MAX, find_video, NULL,
622656
&video_caps, NULL);
657+
nvidia_wmi_ec_present = nvidia_wmi_ec_supported();
623658
init_done = true;
624659
}
625660
if (native)
@@ -640,6 +675,10 @@ enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto
640675
if (acpi_backlight_dmi != acpi_backlight_undef)
641676
return acpi_backlight_dmi;
642677

678+
/* Special cases such as nvidia_wmi_ec and apple gmux. */
679+
if (nvidia_wmi_ec_present)
680+
return acpi_backlight_nvidia_wmi_ec;
681+
643682
if (auto_detect)
644683
*auto_detect = true;
645684

drivers/platform/x86/Kconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,22 @@ config PEAQ_WMI
113113
help
114114
Say Y here if you want to support WMI-based hotkeys on PEAQ 2-in-1s.
115115

116+
config NVIDIA_WMI_EC_BACKLIGHT
117+
tristate "EC Backlight Driver for Hybrid Graphics Notebook Systems"
118+
depends on ACPI_VIDEO
119+
depends on ACPI_WMI
120+
depends on BACKLIGHT_CLASS_DEVICE
121+
help
122+
This driver provides a sysfs backlight interface for notebook systems
123+
which are equipped with NVIDIA hybrid graphics and drive LCD backlight
124+
levels through the Embedded Controller (EC).
125+
126+
Say Y or M here if you want to control the backlight on a notebook
127+
system with an EC-driven backlight.
128+
129+
If you choose to compile this driver as a module the module will be
130+
called nvidia-wmi-ec-backlight.
131+
116132
config XIAOMI_WMI
117133
tristate "Xiaomi WMI key driver"
118134
depends on ACPI_WMI

drivers/platform/x86/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o
1313
obj-$(CONFIG_INTEL_WMI_SBL_FW_UPDATE) += intel-wmi-sbl-fw-update.o
1414
obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o
1515
obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
16+
obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o
1617
obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o
1718
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
1819
obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
4+
*/
5+
6+
#include <linux/acpi.h>
7+
#include <linux/backlight.h>
8+
#include <linux/mod_devicetable.h>
9+
#include <linux/module.h>
10+
#include <linux/platform_data/x86/nvidia-wmi-ec-backlight.h>
11+
#include <linux/types.h>
12+
#include <linux/wmi.h>
13+
#include <acpi/video.h>
14+
15+
static bool force;
16+
module_param(force, bool, 0444);
17+
MODULE_PARM_DESC(force, "Force loading (disable acpi_backlight=xxx checks");
18+
19+
/**
20+
* wmi_brightness_notify() - helper function for calling WMI-wrapped ACPI method
21+
* @w: Pointer to the struct wmi_device identified by %WMI_BRIGHTNESS_GUID
22+
* @id: The WMI method ID to call (e.g. %WMI_BRIGHTNESS_METHOD_LEVEL or
23+
* %WMI_BRIGHTNESS_METHOD_SOURCE)
24+
* @mode: The operation to perform on the method (e.g. %WMI_BRIGHTNESS_MODE_SET
25+
* or %WMI_BRIGHTNESS_MODE_GET)
26+
* @val: Pointer to a value passed in by the caller when @mode is
27+
* %WMI_BRIGHTNESS_MODE_SET, or a value passed out to caller when @mode
28+
* is %WMI_BRIGHTNESS_MODE_GET or %WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL.
29+
*
30+
* Returns 0 on success, or a negative error number on failure.
31+
*/
32+
static int wmi_brightness_notify(struct wmi_device *w, enum wmi_brightness_method id, enum wmi_brightness_mode mode, u32 *val)
33+
{
34+
struct wmi_brightness_args args = {
35+
.mode = mode,
36+
.val = 0,
37+
.ret = 0,
38+
};
39+
struct acpi_buffer buf = { (acpi_size)sizeof(args), &args };
40+
acpi_status status;
41+
42+
if (id < WMI_BRIGHTNESS_METHOD_LEVEL ||
43+
id >= WMI_BRIGHTNESS_METHOD_MAX ||
44+
mode < WMI_BRIGHTNESS_MODE_GET || mode >= WMI_BRIGHTNESS_MODE_MAX)
45+
return -EINVAL;
46+
47+
if (mode == WMI_BRIGHTNESS_MODE_SET)
48+
args.val = *val;
49+
50+
status = wmidev_evaluate_method(w, 0, id, &buf, &buf);
51+
if (ACPI_FAILURE(status)) {
52+
dev_err(&w->dev, "EC backlight control failed: %s\n",
53+
acpi_format_exception(status));
54+
return -EIO;
55+
}
56+
57+
if (mode != WMI_BRIGHTNESS_MODE_SET)
58+
*val = args.ret;
59+
60+
return 0;
61+
}
62+
63+
static int nvidia_wmi_ec_backlight_update_status(struct backlight_device *bd)
64+
{
65+
struct wmi_device *wdev = bl_get_data(bd);
66+
67+
return wmi_brightness_notify(wdev, WMI_BRIGHTNESS_METHOD_LEVEL,
68+
WMI_BRIGHTNESS_MODE_SET,
69+
&bd->props.brightness);
70+
}
71+
72+
static int nvidia_wmi_ec_backlight_get_brightness(struct backlight_device *bd)
73+
{
74+
struct wmi_device *wdev = bl_get_data(bd);
75+
u32 level;
76+
int ret;
77+
78+
ret = wmi_brightness_notify(wdev, WMI_BRIGHTNESS_METHOD_LEVEL,
79+
WMI_BRIGHTNESS_MODE_GET, &level);
80+
if (ret < 0)
81+
return ret;
82+
83+
return level;
84+
}
85+
86+
static const struct backlight_ops nvidia_wmi_ec_backlight_ops = {
87+
.update_status = nvidia_wmi_ec_backlight_update_status,
88+
.get_brightness = nvidia_wmi_ec_backlight_get_brightness,
89+
};
90+
91+
static int nvidia_wmi_ec_backlight_probe(struct wmi_device *wdev, const void *ctx)
92+
{
93+
struct backlight_properties props = {};
94+
struct backlight_device *bdev;
95+
int ret;
96+
97+
/* drivers/acpi/video_detect.c also checks that SOURCE == EC */
98+
if (!force && acpi_video_get_backlight_type() != acpi_backlight_nvidia_wmi_ec)
99+
return -ENODEV;
100+
101+
/*
102+
* Identify this backlight device as a firmware device so that it can
103+
* be prioritized over any exposed GPU-driven raw device(s).
104+
*/
105+
props.type = BACKLIGHT_FIRMWARE;
106+
107+
ret = wmi_brightness_notify(wdev, WMI_BRIGHTNESS_METHOD_LEVEL,
108+
WMI_BRIGHTNESS_MODE_GET_MAX_LEVEL,
109+
&props.max_brightness);
110+
if (ret)
111+
return ret;
112+
113+
ret = wmi_brightness_notify(wdev, WMI_BRIGHTNESS_METHOD_LEVEL,
114+
WMI_BRIGHTNESS_MODE_GET, &props.brightness);
115+
if (ret)
116+
return ret;
117+
118+
bdev = devm_backlight_device_register(&wdev->dev,
119+
"nvidia_wmi_ec_backlight",
120+
&wdev->dev, wdev,
121+
&nvidia_wmi_ec_backlight_ops,
122+
&props);
123+
return PTR_ERR_OR_ZERO(bdev);
124+
}
125+
126+
static const struct wmi_device_id nvidia_wmi_ec_backlight_id_table[] = {
127+
{ .guid_string = WMI_BRIGHTNESS_GUID },
128+
{ }
129+
};
130+
MODULE_DEVICE_TABLE(wmi, nvidia_wmi_ec_backlight_id_table);
131+
132+
static struct wmi_driver nvidia_wmi_ec_backlight_driver = {
133+
.driver = {
134+
.name = "nvidia-wmi-ec-backlight",
135+
},
136+
.probe = nvidia_wmi_ec_backlight_probe,
137+
.id_table = nvidia_wmi_ec_backlight_id_table,
138+
};
139+
module_wmi_driver(nvidia_wmi_ec_backlight_driver);
140+
141+
MODULE_AUTHOR("Daniel Dadap <ddadap@nvidia.com>");
142+
MODULE_DESCRIPTION("NVIDIA WMI EC Backlight driver");
143+
MODULE_LICENSE("GPL");

include/acpi/video.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ enum acpi_backlight_type {
4848
acpi_backlight_video,
4949
acpi_backlight_vendor,
5050
acpi_backlight_native,
51+
acpi_backlight_nvidia_wmi_ec,
5152
};
5253

5354
#if IS_ENABLED(CONFIG_ACPI_VIDEO)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_NVIDIA_WMI_EC_BACKLIGHT=m

redhat/rhel_files/filter-modules.sh.rhel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ netprots="6lowpan appletalk atm ax25 batman-adv bluetooth can dccp dsa ieee80215
3939

4040
drmdrvs="amd ast gma500 i2c i915 mgag200 nouveau radeon via "
4141

42-
singlemods="ntb_netdev iscsi_ibft iscsi_boot_sysfs megaraid pmcraid qedi qla1280 9pnet_rdma rpcrdma nvmet-rdma nvme-rdma hid-picolcd hid-prodikeys hwa-hc hwpoison-inject hid-sensor-hub target_core_user sbp_target cxgbit iw_cxgb3 iw_cxgb4 cxgb3i cxgb3i cxgb3i_ddp cxgb4i chcr chtls parport_serial ism regmap-sdw regmap-sdw-mbq arizona-micsupp hid-asus nct6775 ntc_thermistor"
42+
singlemods="ntb_netdev iscsi_ibft iscsi_boot_sysfs megaraid pmcraid qedi qla1280 9pnet_rdma rpcrdma nvmet-rdma nvme-rdma hid-picolcd hid-prodikeys hwa-hc hwpoison-inject hid-sensor-hub target_core_user sbp_target cxgbit iw_cxgb3 iw_cxgb4 cxgb3i cxgb3i cxgb3i_ddp cxgb4i chcr chtls parport_serial ism regmap-sdw regmap-sdw-mbq arizona-micsupp hid-asus nct6775 ntc_thermistor video"
4343

4444
# Grab the arch-specific filter list overrides
4545
source ./filter-$2.sh

0 commit comments

Comments
 (0)