Skip to content

Commit

Permalink
ACPI: video: Add Nvidia WMI EC brightness control detection (v3)
Browse files Browse the repository at this point in the history
On some new laptop designs a new Nvidia specific WMI interface is present
which gives info about panel brightness control and may allow controlling
the brightness through this interface when the embedded controller is used
for brightness control.

When this WMI interface is present and indicates that the EC is used,
then this interface should be used for brightness control.

Changes in v2:
- Use the new shared nvidia-wmi-ec-backlight.h header for the
  WMI firmware API definitions
- ACPI_VIDEO can now be enabled on non X86 too,
  adjust the Kconfig changes to match this.

Changes in v3:
- Use WMI_BRIGHTNESS_GUID define

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Daniel Dadap <ddadap@nvidia.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  • Loading branch information
jwrdegoede committed Sep 3, 2022
1 parent b39be9f commit fe7aebb
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/acpi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 37 additions & 0 deletions drivers/acpi/video_detect.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#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>
Expand Down Expand Up @@ -75,6 +76,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)
Expand Down Expand Up @@ -541,6 +572,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
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;
Expand All @@ -553,6 +585,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_video, NULL,
&video_caps, NULL);
nvidia_wmi_ec_present = nvidia_wmi_ec_supported();
init_done = true;
}
if (native)
Expand All @@ -570,6 +603,10 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
if (acpi_backlight_dmi != acpi_backlight_undef)
return acpi_backlight_dmi;

/* Special cases such as nvidia_wmi_ec and apple gmux. */
if (nvidia_wmi_ec_present)
return acpi_backlight_nvidia_wmi_ec;

/* On systems with ACPI video use either native or ACPI video. */
if (video_caps & ACPI_VIDEO_BACKLIGHT) {
/*
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/gma500/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions include/acpi/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ enum acpi_backlight_type {
acpi_backlight_video,
acpi_backlight_vendor,
acpi_backlight_native,
acpi_backlight_nvidia_wmi_ec,
};

#if IS_ENABLED(CONFIG_ACPI_VIDEO)
Expand Down

0 comments on commit fe7aebb

Please sign in to comment.