From 2600bfa3df9944562d43d1f17016832a6ffa3b38 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 15 Apr 2022 13:59:48 +0200 Subject: [PATCH 001/119] ACPI: video: Add acpi_video_backlight_use_native() helper ATM on x86 laptops where we want userspace to use the acpi_video backlight device we often register both the GPU's native backlight device and acpi_video's firmware acpi_video# backlight device. This relies on userspace preferring firmware type backlight devices over native ones, but registering 2 backlight devices for a single display really is undesirable. On x86 laptops where the native GPU backlight device should be used, the registering of other backlight devices is avoided by their drivers using acpi_video_get_backlight_type() and only registering their backlight if the return value matches their type. acpi_video_get_backlight_type() uses backlight_device_get_by_type(BACKLIGHT_RAW) to determine if a native driver is available and will never return native if this returns false. This means that the GPU's native backlight registering code cannot just call acpi_video_get_backlight_type() to determine if it should register its backlight, since acpi_video_get_backlight_type() will never return native until the native backlight has already registered. To fix this add a new internal native function parameter to acpi_video_get_backlight_type(), which when set to true will make acpi_video_get_backlight_type() behave as if a native backlight has already been registered. And add a new acpi_video_backlight_use_native() helper, which sets this to true, for use in native GPU backlight code. Changes in v2: - Replace adding a native parameter to acpi_video_get_backlight_type() with adding a new acpi_video_backlight_use_native() helper. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 24 ++++++++++++++++++++---- include/acpi/video.h | 5 +++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 5d7f38016a243..5f105eaa7d30e 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -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 @@ -571,9 +572,10 @@ static int acpi_video_backlight_notify(struct notifier_block *nb, * 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 native_available; static bool init_done; static long video_caps; @@ -593,6 +595,8 @@ enum acpi_backlight_type acpi_video_get_backlight_type(void) backlight_notifier_registered = true; init_done = true; } + if (native) + native_available = true; mutex_unlock(&init_mutex); if (acpi_backlight_cmdline != acpi_backlight_undef) @@ -604,13 +608,25 @@ enum acpi_backlight_type acpi_video_get_backlight_type(void) if (!(video_caps & ACPI_VIDEO_BACKLIGHT)) return acpi_backlight_vendor; - if (acpi_osi_is_win8() && backlight_device_get_by_type(BACKLIGHT_RAW)) + if (acpi_osi_is_win8() && + (native_available || backlight_device_get_by_type(BACKLIGHT_RAW))) return acpi_backlight_native; return acpi_backlight_video; } + +enum acpi_backlight_type acpi_video_get_backlight_type(void) +{ + return __acpi_video_get_backlight_type(false); +} EXPORT_SYMBOL(acpi_video_get_backlight_type); +bool acpi_video_backlight_use_native(void) +{ + return __acpi_video_get_backlight_type(true) == acpi_backlight_native; +} +EXPORT_SYMBOL(acpi_video_backlight_use_native); + /* * Set the preferred backlight interface type based on DMI info. * This function allows DMI blacklists to be implemented by external diff --git a/include/acpi/video.h b/include/acpi/video.h index db8548ff03cef..4705e339c252c 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -56,6 +56,7 @@ extern void acpi_video_unregister(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 bool acpi_video_backlight_use_native(void); extern void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type); /* * Note: The value returned by acpi_video_handles_brightness_key_presses() @@ -77,6 +78,10 @@ static inline enum acpi_backlight_type acpi_video_get_backlight_type(void) { return acpi_backlight_vendor; } +static inline bool acpi_video_backlight_use_native(void) +{ + return true; +} static inline void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type) { } From b1d36e73cc1c68d28f63cbd14767d0d0861147e0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 15 Apr 2022 21:55:35 +0200 Subject: [PATCH 002/119] drm/i915: Don't register backlight when another backlight should be used (v2) Before this commit when we want userspace to use the acpi_video backlight device we register both the GPU's native backlight device and acpi_video's firmware acpi_video# backlight device. This relies on userspace preferring firmware type backlight devices over native ones. Registering 2 backlight devices for a single display really is undesirable, don't register the GPU's native backlight device when another backlight device should be used. Changes in v2: - Use drm_info(drm_dev, ...) for log messages Reviewed-by: Jani Nikula Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_backlight.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 110fc98ec280d..84639e9df5c9c 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -8,6 +8,8 @@ #include #include +#include + #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; From da11ef832972e311475fcba802398e720ed36c54 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 15 Apr 2022 22:22:41 +0200 Subject: [PATCH 003/119] drm/amdgpu: Don't register backlight when another backlight should be used (v3) Before this commit when we want userspace to use the acpi_video backlight device we register both the GPU's native backlight device and acpi_video's firmware acpi_video# backlight device. This relies on userspace preferring firmware type backlight devices over native ones. Registering 2 backlight devices for a single display really is undesirable, don't register the GPU's native backlight device when another backlight device should be used. Changes in v2: - To avoid linker errors when amdgpu is builtin and video_detect.c is in a module, select ACPI_VIDEO and its deps if ACPI is enabled. When ACPI is disabled, ACPI_VIDEO is also always disabled, ensuring the stubs from acpi/video.h will be used. Changes in v3: - Use drm_info(drm_dev, "...") to log messages - ACPI_VIDEO can now be enabled on non X86 too, adjust the Kconfig changes to match this. Acked-by: Alex Deucher Signed-off-by: Hans de Goede --- drivers/gpu/drm/Kconfig | 7 +++++++ drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | 7 +++++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 6c2256e8474be..a9139c6c3a091 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -273,6 +273,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. diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index fa7421afb9a6a..b4e3cedceaf8a 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -26,6 +26,8 @@ #include +#include + #include #include #include "amdgpu.h" @@ -184,6 +186,11 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) return; + if (!acpi_video_backlight_use_native()) { + drm_info(dev, "Skipping amdgpu atom DIG backlight registration\n"); + return; + } + pdata = kmalloc(sizeof(struct amdgpu_backlight_privdata), GFP_KERNEL); if (!pdata) { DRM_ERROR("Memory allocation failed\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8660d93cc4055..a64baff041a7e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -89,6 +89,8 @@ #include #include +#include + #include "ivsrcid/dcn/irqsrcs_dcn_1_0.h" #include "dcn/dcn_1_0_offset.h" @@ -4055,6 +4057,11 @@ 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"); + return; + } + props.max_brightness = AMDGPU_MAX_BL_LEVEL; props.brightness = AMDGPU_MAX_BL_LEVEL; props.type = BACKLIGHT_RAW; From 1eb67781117ca2095f0dbede79f22f6b2ffa3189 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 15 Apr 2022 22:24:21 +0200 Subject: [PATCH 004/119] drm/radeon: Don't register backlight when another backlight should be used (v3) Before this commit when we want userspace to use the acpi_video backlight device we register both the GPU's native backlight device and acpi_video's firmware acpi_video# backlight device. This relies on userspace preferring firmware type backlight devices over native ones. Registering 2 backlight devices for a single display really is undesirable, don't register the GPU's native backlight device when another backlight device should be used. Changes in v2: - To avoid linker errors when amdgpu is builtin and video_detect.c is in a module, select ACPI_VIDEO and its deps if ACPI is enabled. When ACPI is disabled, ACPI_VIDEO is also always disabled, ensuring the stubs from acpi/video.h will be used. Changes in v3: - Use drm_info(drm_dev, "...") to log messages - ACPI_VIDEO can now be enabled on non X86 too, adjust the Kconfig changes to match this. Acked-by: Alex Deucher Signed-off-by: Hans de Goede --- drivers/gpu/drm/Kconfig | 7 +++++++ drivers/gpu/drm/radeon/atombios_encoders.c | 7 +++++++ drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index a9139c6c3a091..8cafe63c98fcb 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -248,6 +248,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 diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index c93040e60d040..2b01edea8fe8a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -32,6 +32,8 @@ #include #include +#include + #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"); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 1a66fb969ee75..0cd32c65456c2 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -33,6 +33,8 @@ #include #include +#include + #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"); From 7f908d332dc48a12436725ae326d6143a1a02c1c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 15 Apr 2022 22:25:01 +0200 Subject: [PATCH 005/119] drm/nouveau: Don't register backlight when another backlight should be used (v2) Before this commit when we want userspace to use the acpi_video backlight device we register both the GPU's native backlight device and acpi_video's firmware acpi_video# backlight device. This relies on userspace preferring firmware type backlight devices over native ones. Registering 2 backlight devices for a single display really is undesirable, don't register the GPU's native backlight device when another backlight device should be used. Changes in v2: - Add nouveau_acpi_video_backlight_use_native() wrapper to avoid unresolved symbol errors on non X86 Reviewed-by: Lyude Paul Signed-off-by: Hans de Goede --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 5 +++++ drivers/gpu/drm/nouveau/nouveau_acpi.h | 2 ++ drivers/gpu/drm/nouveau/nouveau_backlight.c | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 6140db756d063..1592c9cd77501 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -386,3 +386,8 @@ 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(); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h index 330f9b837066b..3c666c30dfcaa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -11,6 +11,7 @@ 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); #else static inline bool nouveau_is_optimus(void) { return false; }; static inline bool nouveau_is_v1_dsm(void) { return false; }; @@ -18,6 +19,7 @@ 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; } #endif #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index a2141d3d9b1d2..d2b8f8c13db48 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -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; From a2fc3c899bb091ec69cd74d4d69d71f8b2acdc11 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 28 Apr 2022 14:45:35 +0200 Subject: [PATCH 006/119] ACPI: video: Drop backlight_device_get_by_type() call from acpi_video_get_backlight_type() All x86/ACPI kms drivers which register native/BACKLIGHT_RAW type backlight devices call acpi_video_backlight_use_native() now. This sets __acpi_video_get_backlight_type()'s internal static native_available flag. This makes the backlight_device_get_by_type(BACKLIGHT_RAW) check unnecessary. Relying on the cached native_available value not only is simpler, it will also work correctly in cases where then native backlight registration was skipped because of acpi_video_backlight_use_native() returning false. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 5f105eaa7d30e..385eb49c763f4 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -608,8 +608,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) if (!(video_caps & ACPI_VIDEO_BACKLIGHT)) return acpi_backlight_vendor; - if (acpi_osi_is_win8() && - (native_available || backlight_device_get_by_type(BACKLIGHT_RAW))) + if (acpi_osi_is_win8() && native_available) return acpi_backlight_native; return acpi_backlight_video; From c1af8bec569dd6b8d874c14455ab02398c3d34cd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 28 Apr 2022 17:53:51 +0200 Subject: [PATCH 007/119] ACPI: video: Remove acpi_video_bus from list before tearing it down Move the list_del removing an acpi_video_bus from video_bus_head on teardown to before the teardown is done, to avoid code iterating over the video_bus_head list seeing acpi_video_bus objects on there which are (partly) torn down already. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/acpi_video.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 5cbe2196176db..cde8ffa9f0b85 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -2111,14 +2111,14 @@ 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); From 038a8191ae7a636586a4415b001cece831ab7019 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 29 Apr 2022 13:29:31 +0200 Subject: [PATCH 008/119] ACPI: video: Simplify acpi_video_unregister_backlight() When acpi_video_register() has not run yet the video_bus_head will be empty, so there is no need to check the register_count flag first. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/acpi_video.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index cde8ffa9f0b85..8545bf94866f0 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -2257,14 +2257,10 @@ void acpi_video_unregister_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_unregister_backlight(video); + mutex_unlock(&video_list_lock); } bool acpi_video_handles_brightness_key_presses(void) From 3dbc80a3e4c55c4a5b89ef207bed7b7de36157b4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 28 Apr 2022 17:41:46 +0200 Subject: [PATCH 009/119] ACPI: video: Make backlight class device registration a separate step (v2) On x86/ACPI boards the acpi_video driver will usually initialize before the kms driver (except i915). This causes /sys/class/backlight/acpi_video0 to show up and then the kms driver registers its own native backlight device after which the drivers/acpi/video_detect.c code unregisters the acpi_video0 device (when acpi_video_get_backlight_type()==native). This means that userspace briefly sees 2 devices and the disappearing of acpi_video0 after a brief time confuses the systemd backlight level save/restore code, see e.g.: https://bbs.archlinux.org/viewtopic.php?id=269920 To fix this make backlight class device registration a separate step done by a new acpi_video_register_backlight() function. The intend is for this to be called by the drm/kms driver *after* it is done setting up its own native backlight device. So that acpi_video_get_backlight_type() knows if a native backlight will be available or not at acpi_video backlight registration time, avoiding the add + remove dance. Note the new acpi_video_register_backlight() function is also called from a delayed work to ensure that the acpi_video backlight devices does get registered if necessary even if there is no drm/kms driver or when it is disabled. Changes in v2: - Make register_backlight_delay a module parameter, mainly so that it can be disabled by Nvidia binary driver users Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/acpi_video.c | 50 ++++++++++++++++++++++++++++++++++++--- include/acpi/video.h | 2 ++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 8545bf94866f0..09dd86f86cf33 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -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,6 +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); +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); void acpi_video_detect_exit(void); /* @@ -1859,8 +1872,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 +2097,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; @@ -2125,6 +2140,11 @@ static int acpi_video_bus_remove(struct acpi_device *device) 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 +2255,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 +2277,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,6 +2286,17 @@ void acpi_video_unregister(void) } EXPORT_SYMBOL(acpi_video_unregister); +void acpi_video_register_backlight(void) +{ + struct acpi_video_bus *video; + + 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); + void acpi_video_unregister_backlight(void) { struct acpi_video_bus *video; diff --git a/include/acpi/video.h b/include/acpi/video.h index 4705e339c252c..0625806d3bbd7 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -53,6 +53,7 @@ enum acpi_backlight_type { #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); @@ -69,6 +70,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) { From 6cb634d0dc850cc1ae54868de7815df53e64a465 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 29 Apr 2022 13:00:15 +0200 Subject: [PATCH 010/119] ACPI: video: Remove code to unregister acpi_video backlight when a native backlight registers Remove the code to unregister acpi_video backlight devices when a native backlight device gets registered later. Now that the acpi_video backlight device registration is a separate step which runs later, after the drm/kms driver is done setting up its own native backlight device, it is no longer necessary to monitor for a native (BACKLIGHT_RAW) device showing up later and to then unregister the acpi_video backlight device(s). Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/acpi_video.c | 2 -- drivers/acpi/video_detect.c | 36 ------------------------------------ 2 files changed, 38 deletions(-) diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 09dd86f86cf33..d1e41f30c0047 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -94,7 +94,6 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event); 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); -void acpi_video_detect_exit(void); /* * Indices in the _BCL method response: the first two items are special, @@ -2342,7 +2341,6 @@ static int __init acpi_video_init(void) static void __exit acpi_video_exit(void) { - acpi_video_detect_exit(); acpi_video_unregister(); } diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 385eb49c763f4..fb49b8f4523ae 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -38,10 +38,6 @@ 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; @@ -538,26 +534,6 @@ 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. @@ -587,12 +563,6 @@ 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); - 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; init_done = true; } if (native) @@ -639,9 +609,3 @@ void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type) 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); -} From 3c8b6a399e0eaa6ab839bba2ce9a2bc57e6708d6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 30 Apr 2022 15:54:36 +0200 Subject: [PATCH 011/119] drm/i915: Call acpi_video_register_backlight() (v3) On machins without an i915 opregion the acpi_video driver immediately probes the ACPI video bus and used to also immediately register acpi_video# backlight devices when supported. Once the drm/kms driver then loaded later and possibly registered a native backlight device then the drivers/acpi/video_detect.c code unregistered the acpi_video0 device to avoid there being 2 backlight devices (when acpi_video_get_backlight_type()==native). This means that userspace used to briefly see 2 devices and the disappearing of acpi_video0 after a brief time confuses the systemd backlight level save/restore code, see e.g.: https://bbs.archlinux.org/viewtopic.php?id=269920 To fix this the ACPI video code has been modified to make backlight class device registration a separate step, relying on the drm/kms driver to ask for the acpi_video backlight registration after it is done setting up its native backlight device. Add a call to the new acpi_video_register_backlight() after the i915 calls acpi_video_register() (after setting up the i915 opregion) so that the acpi_video backlight devices get registered on systems where the i915 native backlight device is not registered. Changes in v2: -Only call acpi_video_register_backlight() when a panel is detected Changes in v3: -Add a new intel_acpi_video_register() helper which checks if a panel is present and then calls acpi_video_register_backlight() Reviewed-by: Jani Nikula Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_acpi.c | 27 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_acpi.h | 3 +++ drivers/gpu/drm/i915/display/intel_display.c | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c index e78430001f077..9df78e7caa2bd 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.c +++ b/drivers/gpu/drm/i915/display/intel_acpi.c @@ -7,6 +7,7 @@ #include #include +#include #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); +} diff --git a/drivers/gpu/drm/i915/display/intel_acpi.h b/drivers/gpu/drm/i915/display/intel_acpi.h index 4a760a2baed9f..6a0007452f95c 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.h +++ b/drivers/gpu/drm/i915/display/intel_acpi.h @@ -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__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index fc5d94862ef32..6a1c15e6ce7ff 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -9084,7 +9084,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); From c053383813fd17296db99cea78e058ed4d53019c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 30 Apr 2022 14:29:00 +0200 Subject: [PATCH 012/119] drm/nouveau: Register ACPI video backlight when nv_backlight registration fails (v2) Typically the acpi_video driver will initialize before nouveau, which used to cause /sys/class/backlight/acpi_video0 to get registered and then nouveau would register its own nv_backlight device later. After which the drivers/acpi/video_detect.c code unregistered the acpi_video0 device to avoid there being 2 backlight devices. This means that userspace used to briefly see 2 devices and the disappearing of acpi_video0 after a brief time confuses the systemd backlight level save/restore code, see e.g.: https://bbs.archlinux.org/viewtopic.php?id=269920 To fix this the ACPI video code has been modified to make backlight class device registration a separate step, relying on the drm/kms driver to ask for the acpi_video backlight registration after it is done setting up its native backlight device. Add a call to the new acpi_video_register_backlight() when native backlight device registration has failed / was skipped to ensure that there is a backlight device available before the drm_device gets registered with userspace. Changes in v2: - Add nouveau_acpi_video_register_backlight() wrapper to avoid unresolved symbol errors on non X86 Reviewed-by: Lyude Paul Signed-off-by: Hans de Goede --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 5 +++++ drivers/gpu/drm/nouveau/nouveau_acpi.h | 2 ++ drivers/gpu/drm/nouveau/nouveau_backlight.c | 7 +++++++ 3 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 1592c9cd77501..8cf096f841a90 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -391,3 +391,8 @@ 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(); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h index 3c666c30dfcaa..e39dd8b94b8b2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -12,6 +12,7 @@ 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; }; @@ -20,6 +21,7 @@ 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 diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index d2b8f8c13db48..a614582779cae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -436,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; } From c0f50c5de93b8afb2281009a33c124e82973e457 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 May 2022 11:32:33 +0200 Subject: [PATCH 013/119] drm/amdgpu: Register ACPI video backlight when skipping amdgpu backlight registration Typically the acpi_video driver will initialize before amdgpu, which used to cause /sys/class/backlight/acpi_video0 to get registered and then amdgpu would register its own amdgpu_bl# device later. After which the drivers/acpi/video_detect.c code unregistered the acpi_video0 device to avoid there being 2 backlight devices. This means that userspace used to briefly see 2 devices and the disappearing of acpi_video0 after a brief time confuses the systemd backlight level save/restore code, see e.g.: https://bbs.archlinux.org/viewtopic.php?id=269920 To fix this the ACPI video code has been modified to make backlight class device registration a separate step, relying on the drm/kms driver to ask for the acpi_video backlight registration after it is done setting up its native backlight device. Add a call to the new acpi_video_register_backlight() when amdgpu skips registering its own backlight device because of either the firmware_flags or the acpi_video_get_backlight_type() return value. This ensures that if the acpi_video backlight device should be used, it will be available before the amdgpu drm_device gets registered with userspace. Acked-by: Alex Deucher Signed-off-by: Hans de Goede --- drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | 9 +++++++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index b4e3cedceaf8a..6be9ac2b9c5bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -184,11 +184,11 @@ 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"); - return; + goto register_acpi_backlight; } pdata = kmalloc(sizeof(struct amdgpu_backlight_privdata), GFP_KERNEL); @@ -225,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 diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a64baff041a7e..3f456978dca7d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4059,6 +4059,8 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) 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; } From 5e0e33f92ea5d891ea37fbc5119031024c154805 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 May 2022 16:04:17 +0200 Subject: [PATCH 014/119] drm/radeon: Register ACPI video backlight when skipping radeon backlight registration Typically the acpi_video driver will initialize before radeon, which used to cause /sys/class/backlight/acpi_video0 to get registered and then radeon would register its own radeon_bl# device later. After which the drivers/acpi/video_detect.c code unregistered the acpi_video0 device to avoid there being 2 backlight devices. This means that userspace used to briefly see 2 devices and the disappearing of acpi_video0 after a brief time confuses the systemd backlight level save/restore code, see e.g.: https://bbs.archlinux.org/viewtopic.php?id=269920 To fix this the ACPI video code has been modified to make backlight class device registration a separate step, relying on the drm/kms driver to ask for the acpi_video backlight registration after it is done setting up its native backlight device. Add a call to the new acpi_video_register_backlight() when radeon skips registering its own backlight device because of e.g. the firmware_flags or the acpi_video_get_backlight_type() return value. This ensures that if the acpi_video backlight device should be used, it will be available before the radeon drm_device gets registered with userspace. Acked-by: Alex Deucher Signed-off-by: Hans de Goede --- drivers/gpu/drm/radeon/radeon_encoders.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 46549d5179ee9..c1cbebb51be18 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -30,6 +30,8 @@ #include #include +#include + #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 From 3db2aeb121b9c54f52c399b8905c2bbbf201b7b5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 17 Aug 2022 14:03:32 +0200 Subject: [PATCH 015/119] platform/x86: nvidia-wmi-ec-backlight: Move fw interface definitions to a header (v2) Move the WMI interface definitions to a header, so that the definitions can be shared with drivers/acpi/video_detect.c . Changes in v2: - Add missing Nvidia copyright header - Move WMI_BRIGHTNESS_GUID to nvidia-wmi-ec-backlight.h as well Suggested-by: Daniel Dadap Reviewed-by: Daniel Dadap Signed-off-by: Hans de Goede --- MAINTAINERS | 1 + .../platform/x86/nvidia-wmi-ec-backlight.c | 68 +---------------- .../x86/nvidia-wmi-ec-backlight.h | 76 +++++++++++++++++++ 3 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h diff --git a/MAINTAINERS b/MAINTAINERS index 8a5012ba6ff98..8d59c6e9b4db0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14526,6 +14526,7 @@ M: Daniel Dadap 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 diff --git a/drivers/platform/x86/nvidia-wmi-ec-backlight.c b/drivers/platform/x86/nvidia-wmi-ec-backlight.c index 61e37194df703..be803e47eac0d 100644 --- a/drivers/platform/x86/nvidia-wmi-ec-backlight.c +++ b/drivers/platform/x86/nvidia-wmi-ec-backlight.c @@ -7,74 +7,10 @@ #include #include #include +#include #include #include -/** - * 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]; -}; - /** * wmi_brightness_notify() - helper function for calling WMI-wrapped ACPI method * @w: Pointer to the struct wmi_device identified by %WMI_BRIGHTNESS_GUID @@ -191,8 +127,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 }, { } diff --git a/include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h b/include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h new file mode 100644 index 0000000000000..23d60130272c4 --- /dev/null +++ b/include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h @@ -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 From b39be9f441f9d7320e6020bdf8ec1522d6c81d1e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 4 Jun 2022 14:38:24 +0200 Subject: [PATCH 016/119] ACPI: video: Refactor acpi_video_get_backlight_type() a bit Refactor acpi_video_get_backlight_type() so that the heuristics / detection steps are stricly in order of descending precedence. Also move the comments describing the steps to when the various steps are actually done, to avoid the comments getting out of sync with the code. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 39 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index fb49b8f4523ae..cc9d0d91e2688 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -537,16 +537,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = { /* * 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. */ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) { @@ -569,19 +559,36 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool 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; - - if (acpi_osi_is_win8() && native_available) - return acpi_backlight_native; + /* 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; + } - 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) From fe7aebb40d42bf8e830019d6f57c47cf7d85aa61 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 4 Jun 2022 14:06:18 +0200 Subject: [PATCH 017/119] ACPI: video: Add Nvidia WMI EC brightness control detection (v3) 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 Reviewed-by: Daniel Dadap Signed-off-by: Hans de Goede --- drivers/acpi/Kconfig | 1 + drivers/acpi/video_detect.c | 37 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/gma500/Kconfig | 2 ++ drivers/gpu/drm/i915/Kconfig | 2 ++ include/acpi/video.h | 1 + 5 files changed, 43 insertions(+) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 7802d8846a8d0..44ad4b6bd2346 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -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 diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index cc9d0d91e2688..4dc7fb865083f 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -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) @@ -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; @@ -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) @@ -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) { /* diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig index 0cff20265f979..807b989e3c775 100644 --- a/drivers/gpu/drm/gma500/Kconfig +++ b/drivers/gpu/drm/gma500/Kconfig @@ -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 diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 7ae3b7d67fcfc..3efce05d7b57c 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -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 diff --git a/include/acpi/video.h b/include/acpi/video.h index 0625806d3bbd7..91578e77ac4e1 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -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) From 21245df307cbee9e04d5b4aac3fd04334f6b45dc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 4 Jun 2022 15:21:51 +0200 Subject: [PATCH 018/119] ACPI: video: Add Apple GMUX brightness control detection On Apple laptops with an Apple GMUX using this for brightness control, should take precedence of any other brightness control methods. Add apple-gmux detection to acpi_video_get_backlight_type() using the already existing apple_gmux_present() helper function. This will allow removig the (ab)use of: acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); Inside the apple-gmux driver. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 4 ++++ include/acpi/video.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 4dc7fb865083f..be2fc43418af3 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -607,6 +608,9 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) if (nvidia_wmi_ec_present) return acpi_backlight_nvidia_wmi_ec; + if (apple_gmux_present()) + return acpi_backlight_apple_gmux; + /* On systems with ACPI video use either native or ACPI video. */ if (video_caps & ACPI_VIDEO_BACKLIGHT) { /* diff --git a/include/acpi/video.h b/include/acpi/video.h index 91578e77ac4e1..dbd48cb8bd231 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -49,6 +49,7 @@ enum acpi_backlight_type { acpi_backlight_vendor, acpi_backlight_native, acpi_backlight_nvidia_wmi_ec, + acpi_backlight_apple_gmux, }; #if IS_ENABLED(CONFIG_ACPI_VIDEO) From 8d0ca287fd8cdc8110f5e441ec14874158f32a0f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 17 Aug 2022 14:37:21 +0200 Subject: [PATCH 019/119] platform/x86: nvidia-wmi-ec-backlight: Use acpi_video_get_backlight_type() Add an acpi_video_get_backlight_type() == acpi_backlight_nvidia_wmi_ec check. This will make nvidia-wmi-ec-backlight properly honor the user selecting a different backlight driver through the acpi_backlight=... kernel commandline option. Since the auto-detect code check for nvidia-wmi-ec-backlight in drivers/acpi/video_detect.c already checks that the WMI advertised brightness-source is the embedded controller, this new check makes it unnecessary for nvidia_wmi_ec_backlight_probe() to check this itself. Suggested-by: Daniel Dadap Reviewed-by: Daniel Dadap Signed-off-by: Hans de Goede --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/nvidia-wmi-ec-backlight.c | 14 +++----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f2f98e942cf29..0cc5ac35fc570 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -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 diff --git a/drivers/platform/x86/nvidia-wmi-ec-backlight.c b/drivers/platform/x86/nvidia-wmi-ec-backlight.c index be803e47eac0d..baccdf6585382 100644 --- a/drivers/platform/x86/nvidia-wmi-ec-backlight.c +++ b/drivers/platform/x86/nvidia-wmi-ec-backlight.c @@ -10,6 +10,7 @@ #include #include #include +#include /** * wmi_brightness_notify() - helper function for calling WMI-wrapped ACPI method @@ -87,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; /* From 4f04c7dc83fd4339b00421174edc8556b6bac2b1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 4 Jun 2022 15:25:39 +0200 Subject: [PATCH 020/119] platform/x86: apple-gmux: Stop calling acpi/video.h functions Now that acpi_video_get_backlight_type() has apple-gmux detection (using apple_gmux_present()), it is no longer necessary for the apple-gmux code to manually remove possibly conflicting drivers. So remove the handling for this from the apple-gmux driver. Signed-off-by: Hans de Goede --- drivers/platform/x86/apple-gmux.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index ffe98a18440b3..ca33df7ea550e 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -21,7 +21,6 @@ #include #include #include -#include #include /** @@ -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(); } From a2ed70d0ecb11b7eb3ff14ed897cd0995c86651d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 4 Jun 2022 16:18:05 +0200 Subject: [PATCH 021/119] platform/x86: toshiba_acpi: Stop using acpi_video_set_dmi_backlight_type() acpi_video_set_dmi_backlight_type() is troublesome because it may end up getting called after other backlight drivers have already called acpi_video_get_backlight_type() resulting in the other drivers already being registered even though they should not. In case of the acpi_video backlight, acpi_video_set_dmi_backlight_type() actually calls acpi_video_unregister_backlight() since that is often probed earlier, leading to userspace seeing the acpi_video0 class device being briefly available, leading to races in userspace where udev probe-rules try to access the device and it is already gone. In case of toshiba_acpi there are no DMI quirks to move to acpi/video_detect.c, but it also (ab)uses it for transflective displays. Adding transflective display support to video_detect.c would be quite involved. But luckily there are only 2 known models with a transflective display, so we can just add DMI quirks for those. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 19 +++++++++++++++++++ drivers/platform/x86/toshiba_acpi.c | 16 ---------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index be2fc43418af3..74e2087c8ff05 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -190,6 +190,25 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, + /* + * 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 diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 0fc9e8b8827bd..030dc37d50b82 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -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; From 0172df18dc4309a7052cbb37a6939f7a8b0735d5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 4 Jun 2022 18:28:52 +0200 Subject: [PATCH 022/119] platform/x86: acer-wmi: Move backlight DMI quirks to acpi/video_detect.c Move the backlight DMI quirks to acpi/video_detect.c, so that the driver no longer needs to call acpi_video_set_dmi_backlight_type(). acpi_video_set_dmi_backlight_type() is troublesome because it may end up getting called after other backlight drivers have already called acpi_video_get_backlight_type() resulting in the other drivers already being registered even though they should not. Note that even though the DMI quirk table name was video_vendor_dmi_table, 5/6 quirks were actually quirks to use the GPU native backlight. These 5 quirks also had a callback in their dmi_system_id entry which disabled the acer-wmi vendor driver; and any DMI match resulted in: acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); which disabled the acpi_video driver, so only the native driver was left. The new entries for these 5/6 devices correctly marks these as needing the native backlight driver. Also note that other changes in this series change the native backlight drivers to no longer unconditionally register their backlight. Instead these drivers now do this check: if (acpi_video_get_backlight_type(false) != acpi_backlight_native) return 0; /* bail */ which without this patch would have broken these 5/6 "special" quirks. Since I had to look at all the commits adding the quirks anyways, to make sure that I understood the code correctly, I've also added links to the various original bugzillas for these quirks to the new entries. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 53 ++++++++++++++++++++++++++ drivers/platform/x86/acer-wmi.c | 66 --------------------------------- 2 files changed, 53 insertions(+), 66 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 74e2087c8ff05..6a2523bc02bad 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -149,6 +149,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "X360"), }, }, + { + /* https://bugzilla.redhat.com/show_bug.cgi?id=1128309 */ + .callback = video_detect_force_vendor, + /* Acer KAV80 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"), + }, + }, { .callback = video_detect_force_vendor, /* Asus UL30VT */ @@ -437,6 +446,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, @@ -447,6 +491,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "BA51_MV"), }, }, + { + /* 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 */ diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index e0230ea0cb7ee..b933a5165edbf 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -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; From 2603c681e0f63581b2c7821728d5be2cdee8cb9f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 5 Jun 2022 17:26:54 +0200 Subject: [PATCH 023/119] platform/x86: asus-wmi: Drop DMI chassis-type check from backlight handling Remove this check from the asus-wmi backlight handling: /* 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); This acpi_video_set_dmi_backlight_type(acpi_backlight_vendor) call must be removed because other changes in this series change the native backlight drivers to no longer unconditionally register their backlight. Instead these drivers now do this check: if (acpi_video_get_backlight_type(false) != acpi_backlight_native) return 0; /* bail */ So leaving this in place can break things on laptops with a broken DMI chassis-type, which would have GPU native brightness control before the addition of the acpi_video_get_backlight_type() != native check. Removing this should be ok now, since the ACPI video code has improved heuristics for this itself now (which includes a chassis-type check). Signed-off-by: Hans de Goede --- drivers/platform/x86/asus-wmi.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 89b604e04d7f6..301166a5697da 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -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,12 +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); From 52796b304a517b002300bbb67074b38a6003fd7a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 18 Jun 2022 17:15:24 +0200 Subject: [PATCH 024/119] platform/x86: asus-wmi: Move acpi_backlight=vendor quirks to ACPI video_detect.c Remove the asus-wmi quirk_entry.wmi_backlight_power quirk-flag, which called acpi_video_set_dmi_backlight_type(acpi_backlight_vendor) and replace it with acpi/video_detect.c video_detect_dmi_table[] entries using the video_detect_force_vendor callback. acpi_video_set_dmi_backlight_type() is troublesome because it may end up getting called after other backlight drivers have already called acpi_video_get_backlight_type() resulting in the other drivers already being registered even though they should not. Note no entries are dropped from the dmi_system_id table in asus-nb-wmi.c. This is because the entries using the removed wmi_backlight_power flag also use other model specific quirks from the asus-wmi quirk_entry struct. So the quirk_asus_x55u struct and the entries pointing to it cannot be dropped. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 40 ++++++++++++++++++++++++++++++ drivers/platform/x86/asus-nb-wmi.c | 7 ------ drivers/platform/x86/asus-wmi.c | 3 --- drivers/platform/x86/asus-wmi.h | 1 - drivers/platform/x86/eeepc-wmi.c | 25 +------------------ 5 files changed, 41 insertions(+), 35 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 6a2523bc02bad..d893313fe1a0d 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -174,6 +174,46 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), }, }, + { + .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 */ diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 478dd300b9c9a..810a94557a859 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -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, }; @@ -147,11 +145,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, }, { diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 301166a5697da..5cf9d9aff1640 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -3634,9 +3634,6 @@ static int asus_wmi_add(struct platform_device *pdev) if (asus->driver->quirks->wmi_force_als_set) asus_wmi_set_als(); - 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); diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index b302415bf1d95..30770e4113013 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -29,7 +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; diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index ce86d84ee796d..32d9f0ba6be3f 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -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, From 1e3344d6f2b329ca064b3016bc33d7f33ed7ba0e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 18 Jun 2022 17:44:58 +0200 Subject: [PATCH 025/119] platform/x86: asus-wmi: Move acpi_backlight=native quirks to ACPI video_detect.c Remove the asus-wmi quirk_entry.wmi_backlight_native quirk-flag, which called acpi_video_set_dmi_backlight_type(acpi_backlight_native) and replace it with acpi/video_detect.c video_detect_dmi_table[] entries using the video_detect_force_native callback. acpi_video_set_dmi_backlight_type() is troublesome because it may end up getting called after other backlight drivers have already called acpi_video_get_backlight_type() resulting in the other drivers already being registered even though they should not. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 8 ++++++++ drivers/platform/x86/asus-nb-wmi.c | 14 -------------- drivers/platform/x86/asus-wmi.c | 3 --- drivers/platform/x86/asus-wmi.h | 1 - 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index d893313fe1a0d..a09089e7fada8 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -564,6 +564,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "GA503"), }, }, + { + .callback = video_detect_force_native, + /* Asus UX303UB */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"), + }, + }, /* * Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a * working native and video interface. However the default detection diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 810a94557a859..bbfed85051ee7 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -97,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, @@ -372,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", diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 5cf9d9aff1640..434249ac47a5c 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -3634,9 +3634,6 @@ static int asus_wmi_add(struct platform_device *pdev) if (asus->driver->quirks->wmi_force_als_set) asus_wmi_set_als(); - 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); diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index 30770e4113013..f30252efe1db0 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -29,7 +29,6 @@ struct quirk_entry { bool hotplug_wireless; bool scalar_panel_brightness; bool store_backlight_power; - bool wmi_backlight_native; bool wmi_backlight_set_devstate; bool wmi_force_als_set; bool use_kbd_dock_devid; From 8991d7d9add0d9a711db692458d950050b38307b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 18 Jun 2022 19:01:05 +0200 Subject: [PATCH 026/119] platform/x86: samsung-laptop: Move acpi_backlight=[vendor|native] quirks to ACPI video_detect.c acpi_video_set_dmi_backlight_type() is troublesome because it may end up getting called after other backlight drivers have already called acpi_video_get_backlight_type() resulting in the other drivers already being registered even though they should not. Move all the acpi_backlight=[vendor|native] quirks from samsung-laptop to drivers/acpi/video_detect.c . Note the X360 -> acpi_backlight=native quirk is not moved because that already was present in drivers/acpi/video_detect.c . Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 54 +++++++++++++++++ drivers/platform/x86/samsung-laptop.c | 87 --------------------------- 2 files changed, 54 insertions(+), 87 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index a09089e7fada8..3861d4121172e 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -222,6 +222,33 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"), }, }, + { + .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 */ @@ -572,6 +599,33 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"), }, }, + { + .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, + /* 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, + /* Samsung N250P */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), + DMI_MATCH(DMI_BOARD_NAME, "N250P"), + }, + }, /* * Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a * working native and video interface. However the default detection diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index c187dcdf82f0b..cc30cf08f32da 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -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) From 77ab9d4d44cd235322d2f30b1c4026302c3ce8c6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 20 Jun 2022 11:49:57 +0200 Subject: [PATCH 027/119] ACPI: video: Remove acpi_video_set_dmi_backlight_type() acpi_video_set_dmi_backlight_type() is troublesome because it may end up getting called after other backlight drivers have already called acpi_video_get_backlight_type() resulting in the other drivers already being registered even though they should not. In case of the acpi_video backlight, acpi_video_set_dmi_backlight_type() actually calls acpi_video_unregister_backlight() since that is often probed earlier, leading to userspace seeing the acpi_video0 class device being briefly available, leading to races in userspace where udev probe-rules try to access the device and it is already gone. All callers have been fixed to no longer call it, so remove acpi_video_set_dmi_backlight_type() now. This means we now also no longer need acpi_video_unregister_backlight() for the remove acpi_video backlight after it was wrongly registered hack, so remove that too. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/acpi_video.c | 10 ---------- drivers/acpi/video_detect.c | 16 ---------------- include/acpi/video.h | 4 ---- 3 files changed, 30 deletions(-) diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index d1e41f30c0047..a7c3d11e0dac7 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -2296,16 +2296,6 @@ void acpi_video_register_backlight(void) } EXPORT_SYMBOL(acpi_video_register_backlight); -void acpi_video_unregister_backlight(void) -{ - struct acpi_video_bus *video; - - 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); -} - bool acpi_video_handles_brightness_key_presses(void) { return may_report_brightness_keys && diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 3861d4121172e..67a0211c07b45 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -38,8 +38,6 @@ #include #include -void acpi_video_unregister_backlight(void); - static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef; static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef; @@ -817,17 +815,3 @@ bool acpi_video_backlight_use_native(void) return __acpi_video_get_backlight_type(true) == acpi_backlight_native; } EXPORT_SYMBOL(acpi_video_backlight_use_native); - -/* - * 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) -{ - 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); diff --git a/include/acpi/video.h b/include/acpi/video.h index dbd48cb8bd231..a275c35e5249d 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -60,7 +60,6 @@ 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 bool acpi_video_backlight_use_native(void); -extern void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type); /* * Note: The value returned by acpi_video_handles_brightness_key_presses() * may change over time and should not be cached. @@ -86,9 +85,6 @@ static inline bool acpi_video_backlight_use_native(void) { return true; } -static inline void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type) -{ -} static inline bool acpi_video_handles_brightness_key_presses(void) { return false; From de6f3121dc6b2226b85a91b1fe2ac2d08a8b5248 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 18 Jun 2022 19:06:51 +0200 Subject: [PATCH 028/119] ACPI: video: Drop "Samsung X360" acpi_backlight=native quirk acpi_backlight=native is the default for the "Samsung X360", but as the comment explains the quirk was still necessary because even briefly registering the acpi_video0 backlight; and then unregistering it once the native driver showed up, was leading to issues. After the "ACPI: video: Make backlight class device registration a separate step" patch from earlier in this patch-series, we no longer briefly register the acpi_video0 backlight on systems where the native driver should be used. So this is no longer an issue an the quirk is no longer needed. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 67a0211c07b45..af2833b57b8be 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -132,21 +132,6 @@ 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(). - */ - { - .callback = video_detect_force_vendor, - /* X360 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), - DMI_MATCH(DMI_PRODUCT_NAME, "X360"), - DMI_MATCH(DMI_BOARD_NAME, "X360"), - }, - }, { /* https://bugzilla.redhat.com/show_bug.cgi?id=1128309 */ .callback = video_detect_force_vendor, From 10212754a0d2c4b4ae951c04f154a82dd2a1f9c4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 18 Jun 2022 19:15:22 +0200 Subject: [PATCH 029/119] ACPI: video: Drop NL5x?U, PF4NU1F and PF5?U?? acpi_backlight=native quirks acpi_backlight=native is the default for these, but as the comment explains the quirk was still necessary because even briefly registering the acpi_video0 backlight; and then unregistering it once the native driver showed up, was leading to issues. After the "ACPI: video: Make backlight class device registration a separate step" patch from earlier in this patch-series, we no longer briefly register the acpi_video0 backlight on systems where the native driver should be used. So this is no longer an issue an the quirks are no longer needed. Link: https://bugzilla.kernel.org/show_bug.cgi?id=215683 Tested-by: Werner Sembach Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 92 +------------------------------------ 1 file changed, 1 insertion(+), 91 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index af2833b57b8be..789d5913c1788 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -609,97 +609,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "N250P"), }, }, - /* - * 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, - .ident = "Clevo NL5xRU", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), - DMI_MATCH(DMI_BOARD_NAME, "AURA1501"), - }, - }, - { - .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, - .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"), - }, - }, + /* * Desktops which falsely report a backlight and which our heuristics * for this do not catch. From c2d6920e9877c8298502ec6163a93ab0db1dd761 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 18 Jun 2022 19:19:51 +0200 Subject: [PATCH 030/119] ACPI: video: Fix indentation of video_detect_dmi_table[] entries The video_detect_dmi_table[] uses an unusual indentation for before the ".name = ..." named struct initializers. Instead of being indented with an extra tab compared to the previous line's '{' these are indented to with only a single space to allow for long DMI_MATCH() lines without wrapping. But over time some entries did not event have the single space indent in front of the ".name = ..." lines. Make things consistent by using a single space indent for these lines everywhere. Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 789d5913c1788..db2474fe58ac0 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -142,17 +142,17 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, { - .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"), }, @@ -198,9 +198,9 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, { - .callback = video_detect_force_vendor, - /* GIGABYTE GB-BXBT-2807 */ - .matches = { + .callback = video_detect_force_vendor, + /* GIGABYTE GB-BXBT-2807 */ + .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"), }, @@ -233,17 +233,17 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, { - .callback = video_detect_force_vendor, - /* Sony VPCEH3U1E */ - .matches = { + .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"), }, @@ -551,25 +551,25 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, { - .callback = video_detect_force_native, - /* ASUSTeK COMPUTER INC. GA401 */ - .matches = { + .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"), }, From 4f96b1bc156e7076f6efedc2a76a8c7e897c7977 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 11 Jul 2022 13:49:34 +0200 Subject: [PATCH 031/119] drm/todo: Add entry about dealing with brightness control on devices with > 1 panel Add an entry summarizing the discussion about dealing with brightness control on devices with more then 1 internal panel. The original discussion can be found here: https://lore.kernel.org/dri-devel/20220517152331.16217-1-hdegoede@redhat.com/ Reviewed-by: Lyude Paul Signed-off-by: Hans de Goede --- Documentation/gpu/todo.rst | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 513b20ccef1e1..7ff89559b3b73 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -715,6 +715,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 =========== From e73f57b70a214ab730ac9c7910b85ad372841673 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 9 Sep 2022 11:31:16 +0200 Subject: [PATCH 032/119] drm/sun4i: tv: Include drm_atomic.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit ec491291dc94 ("drm/sun4i: tv: Merge mode_set into atomic_enable") has introduced a call to drm_atomic_get_new_crtc_state(), but didn't include drm_atomic.h. On CONFIG_OF systems, this is fine because drm_atomic.h is included by drm_of.h through drm_bridge.h. However, whenever CONFIG_OF isn't set, we end up with a compilation error. Fixes: ec491291dc94 ("drm/sun4i: tv: Merge mode_set into atomic_enable") Reported-by: kernel test robot Reported-by: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220909093116.4141982-1-maxime@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_tv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index 74ff5ad6a8b99..c65f0a89b6b06 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include From e8523f53bf09d274da04e64e24841b4f83f98bca Mon Sep 17 00:00:00 2001 From: Guo Zhengkui Date: Tue, 17 May 2022 13:02:06 +0800 Subject: [PATCH 033/119] drm: omapdrm: dss: replace ternary operator with max() Fix the following coccicheck warning: drivers/gpu/drm/omapdrm/dss/dispc.c:2454:21-22: WARNING opportunity for max() Signed-off-by: Guo Zhengkui Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20220517050208.121488-1-guozhengkui@vivo.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index c4de142cc85bf..0ee344ebcd1cd 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2451,7 +2451,7 @@ static int dispc_ovl_calc_scaling_44xx(struct dispc_device *dispc, *decim_x = DIV_ROUND_UP(width, in_width_max); - *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min; + *decim_x = max(*decim_x, decim_x_min); if (*decim_x > *x_predecim) return -EINVAL; From 8b42057e62120813ebe9274f508fa785b7cab33a Mon Sep 17 00:00:00 2001 From: Liang He Date: Fri, 22 Jul 2022 22:43:48 +0800 Subject: [PATCH 034/119] drm/omap: dss: Fix refcount leak bugs In dss_init_ports() and __dss_uninit_ports(), we should call of_node_put() for the reference returned by of_graph_get_port_by_id() in fail path or when it is not used anymore. Fixes: 09bffa6e5192 ("drm: omap: use common OF graph helpers") Signed-off-by: Liang He Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20220722144348.1306569-1-windhl@126.com --- drivers/gpu/drm/omapdrm/dss/dss.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 0399f3390a0ad..c4febb8619103 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1176,6 +1176,7 @@ static void __dss_uninit_ports(struct dss_device *dss, unsigned int num_ports) default: break; } + of_node_put(port); } } @@ -1208,11 +1209,13 @@ static int dss_init_ports(struct dss_device *dss) default: break; } + of_node_put(port); } return 0; error: + of_node_put(port); __dss_uninit_ports(dss, i); return r; } From a99509ba6d1a406c2af2666b5f896898c54878b6 Mon Sep 17 00:00:00 2001 From: ye xingchen Date: Wed, 10 Aug 2022 06:27:38 +0000 Subject: [PATCH 035/119] drm/omap: dmm_tiler:Remove the print function dev_err() From the coccinelle check: ./drivers/gpu/drm/omapdrm/omap_dmm_tiler.c Error:line 817 is redundant because platform_get_irq() already prints an error So,remove the unnecessary print function dev_err() Reported-by: Zeal Robot Signed-off-by: ye xingchen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20220810062738.13554-1-ye.xingchen@zte.com.cn --- drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index ac869acf80eac..61a27dd7392ea 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -813,10 +813,8 @@ static int omap_dmm_probe(struct platform_device *dev) } omap_dmm->irq = platform_get_irq(dev, 0); - if (omap_dmm->irq < 0) { - dev_err(&dev->dev, "failed to get IRQ resource\n"); + if (omap_dmm->irq < 0) goto fail; - } omap_dmm->dev = &dev->dev; From 51865139511ea9e5193248d7ab686f206399adfc Mon Sep 17 00:00:00 2001 From: Jilin Yuan Date: Wed, 24 Aug 2022 21:04:50 +0800 Subject: [PATCH 036/119] drm/tidss: fix repeated words in comments Delete the redundant word 'to'. Signed-off-by: Jilin Yuan Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20220824130450.41703-1-yuanjilin@cdjrlc.com --- drivers/gpu/drm/tidss/tidss_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tidss/tidss_kms.c b/drivers/gpu/drm/tidss/tidss_kms.c index b61db8f279e94..afb2879980c6c 100644 --- a/drivers/gpu/drm/tidss/tidss_kms.c +++ b/drivers/gpu/drm/tidss/tidss_kms.c @@ -70,7 +70,7 @@ static int tidss_atomic_check(struct drm_device *ddev, * changes. This is needed for updating the plane positions in * tidss_crtc_position_planes() which is called from * crtc_atomic_enable() and crtc_atomic_flush(). We have an - * extra flag to to mark x,y-position changes and together + * extra flag to mark x,y-position changes and together * with zpos_changed the condition recognizes all the above * cases. */ From fe53d167129e19ce01c056d85262427146cacf88 Mon Sep 17 00:00:00 2001 From: wangjianli Date: Thu, 8 Sep 2022 20:36:16 +0800 Subject: [PATCH 037/119] drm/rockchip: vop: fix repeated words in comment Delete the redundant word 'in'. Signed-off-by: wangjianli Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20220908123616.19195-1-wangjianli@cdjrlc.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index bdd48f87d098e..fab7109109977 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1188,7 +1188,7 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, * * Key points: * - * - DRM works in in kHz. + * - DRM works in kHz. * - Clock framework works in Hz. * - Rockchip's clock driver picks the clock rate that is the * same _OR LOWER_ than the one requested. From 1c3b502e4327e8e24e617a6f922df72870c0cb5f Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Tue, 6 Sep 2022 12:48:19 -0500 Subject: [PATCH 038/119] dt-bindings: display: rockchip-dsi: add rk3568 compatible The rk3568 uses the same dw-mipi-dsi controller as previous Rockchip SOCs, so add a compatible string for it. Signed-off-by: Chris Morgan Acked-by: Rob Herring Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20220906174823.28561-2-macroalpha82@gmail.com --- .../bindings/display/rockchip/dw_mipi_dsi_rockchip.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt index 39792f051d2dd..9a223df8530c0 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt @@ -8,6 +8,7 @@ Required properties: "rockchip,px30-mipi-dsi", "snps,dw-mipi-dsi" "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi" "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi" + "rockchip,rk3568-mipi-dsi", "snps,dw-mipi-dsi" - reg: Represent the physical address range of the controller. - interrupts: Represent the controller's interrupt to the CPU(s). - clocks, clock-names: Phandles to the controller's pll reference From f3aaa6125b6f1532d3276d705b1a3791f18a872a Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Tue, 6 Sep 2022 12:48:21 -0500 Subject: [PATCH 039/119] drm/rockchip: dsi: add rk3568 support Add the compatible and GRF definitions for the RK3568 soc. Signed-off-by: Chris Morgan Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20220906174823.28561-4-macroalpha82@gmail.com --- .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 110e83aad9bb4..bf6948125b841 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -179,6 +179,23 @@ #define RK3399_TXRX_SRC_SEL_ISP0 BIT(4) #define RK3399_TXRX_TURNREQUEST GENMASK(3, 0) +#define RK3568_GRF_VO_CON2 0x0368 +#define RK3568_DSI0_SKEWCALHS (0x1f << 11) +#define RK3568_DSI0_FORCETXSTOPMODE (0xf << 4) +#define RK3568_DSI0_TURNDISABLE BIT(2) +#define RK3568_DSI0_FORCERXMODE BIT(0) + +/* + * Note these registers do not appear in the datasheet, they are + * however present in the BSP driver which is where these values + * come from. Name GRF_VO_CON3 is assumed. + */ +#define RK3568_GRF_VO_CON3 0x36c +#define RK3568_DSI1_SKEWCALHS (0x1f << 11) +#define RK3568_DSI1_FORCETXSTOPMODE (0xf << 4) +#define RK3568_DSI1_TURNDISABLE BIT(2) +#define RK3568_DSI1_FORCERXMODE BIT(0) + #define HIWORD_UPDATE(val, mask) (val | (mask) << 16) enum { @@ -735,8 +752,9 @@ static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi) static void dw_mipi_dsi_rockchip_set_lcdsel(struct dw_mipi_dsi_rockchip *dsi, int mux) { - regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg, - mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big); + if (dsi->cdata->lcdsel_grf_reg < 0) + regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg, + mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big); } static int @@ -963,6 +981,8 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev, DRM_DEV_ERROR(dev, "Failed to create drm encoder\n"); goto out_pll_clk; } + rockchip_drm_encoder_set_crtc_endpoint_id(&dsi->encoder, + dev->of_node, 0, 0); ret = dw_mipi_dsi_bind(dsi->dmd, &dsi->encoder.encoder); if (ret) { @@ -1612,6 +1632,30 @@ static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = { { /* sentinel */ } }; +static const struct rockchip_dw_dsi_chip_data rk3568_chip_data[] = { + { + .reg = 0xfe060000, + .lcdsel_grf_reg = -1, + .lanecfg1_grf_reg = RK3568_GRF_VO_CON2, + .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI0_SKEWCALHS | + RK3568_DSI0_FORCETXSTOPMODE | + RK3568_DSI0_TURNDISABLE | + RK3568_DSI0_FORCERXMODE), + .max_data_lanes = 4, + }, + { + .reg = 0xfe070000, + .lcdsel_grf_reg = -1, + .lanecfg1_grf_reg = RK3568_GRF_VO_CON3, + .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI1_SKEWCALHS | + RK3568_DSI1_FORCETXSTOPMODE | + RK3568_DSI1_TURNDISABLE | + RK3568_DSI1_FORCERXMODE), + .max_data_lanes = 4, + }, + { /* sentinel */ } +}; + static const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = { { .compatible = "rockchip,px30-mipi-dsi", @@ -1622,6 +1666,9 @@ static const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = { }, { .compatible = "rockchip,rk3399-mipi-dsi", .data = &rk3399_chip_data, + }, { + .compatible = "rockchip,rk3568-mipi-dsi", + .data = &rk3568_chip_data, }, { /* sentinel */ } }; From 6da75526fc9edf940c12a785cc2fdeaf22101cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Wed, 31 Aug 2022 23:56:07 +0200 Subject: [PATCH 040/119] drm/format: Use appropriate types in expect/assert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_format_info_* functions don't return bool, and the info variable is a pointer. Expecting non-NULL info will cause the test to crash if it is NULL in checks that follow (which dereference it). Use appropriate KUNIT_EXPECT/KUNIT_ASSERT variants. Signed-off-by: Michał Winiarski Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20220831215608.349269-1-michal.winiarski@intel.com --- drivers/gpu/drm/tests/drm_format_test.c | 152 ++++++++++++------------ 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_format_test.c b/drivers/gpu/drm/tests/drm_format_test.c index afb4bca721879..0efa88bf56a9d 100644 --- a/drivers/gpu/drm/tests/drm_format_test.c +++ b/drivers/gpu/drm/tests/drm_format_test.c @@ -14,40 +14,40 @@ static void igt_check_drm_format_block_width(struct kunit *test) const struct drm_format_info *info = NULL; /* Test invalid arguments */ - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 1)); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 0); /* Test 1 plane format */ info = drm_format_info(DRM_FORMAT_XRGB4444); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 1)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); /* Test 2 planes format */ info = drm_format_info(DRM_FORMAT_NV12); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 0)); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 1)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 2)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 2), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); /* Test 3 planes format */ info = drm_format_info(DRM_FORMAT_YUV422); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 0)); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 1)); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 2)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 3)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 2), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 3), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); /* Test a tiled format */ info = drm_format_info(DRM_FORMAT_X0L0); - KUNIT_EXPECT_TRUE(test, info); + KUNIT_ASSERT_NOT_NULL(test, info); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 2); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 1)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); } static void igt_check_drm_format_block_height(struct kunit *test) @@ -55,40 +55,40 @@ static void igt_check_drm_format_block_height(struct kunit *test) const struct drm_format_info *info = NULL; /* Test invalid arguments */ - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 1)); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 0); /* Test 1 plane format */ info = drm_format_info(DRM_FORMAT_XRGB4444); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 1)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 0); /* Test 2 planes format */ info = drm_format_info(DRM_FORMAT_NV12); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 0)); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 1)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 2)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 2), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); /* Test 3 planes format */ info = drm_format_info(DRM_FORMAT_YUV422); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 0)); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 1)); - KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 2)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 3)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 2), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 3), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); /* Test a tiled format */ info = drm_format_info(DRM_FORMAT_X0L0); - KUNIT_EXPECT_TRUE(test, info); + KUNIT_ASSERT_NOT_NULL(test, info); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 2); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 1)); - KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); } static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) @@ -96,16 +96,16 @@ static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) const struct drm_format_info *info = NULL; /* Test invalid arguments */ - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); /* Test 1 plane 8 bits per pixel format */ info = drm_format_info(DRM_FORMAT_RGB332); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 1); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 2); @@ -121,10 +121,10 @@ static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) /* Test 1 plane 16 bits per pixel format */ info = drm_format_info(DRM_FORMAT_XRGB4444); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 2); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 4); @@ -140,10 +140,10 @@ static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) /* Test 1 plane 24 bits per pixel format */ info = drm_format_info(DRM_FORMAT_RGB888); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 3); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 6); @@ -159,10 +159,10 @@ static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) /* Test 1 plane 32 bits per pixel format */ info = drm_format_info(DRM_FORMAT_ABGR8888); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 4); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 8); @@ -183,11 +183,11 @@ static void igt_check_drm_format_min_pitch_for_multi_planar(struct kunit *test) /* Test 2 planes format */ info = drm_format_info(DRM_FORMAT_NV12); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 2, 0)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 1); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 1), 2); @@ -214,12 +214,12 @@ static void igt_check_drm_format_min_pitch_for_multi_planar(struct kunit *test) /* Test 3 planes 8 bits per pixel format */ info = drm_format_info(DRM_FORMAT_YUV422); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 2, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 3, 0)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 3, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 1); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 1), 1); @@ -262,10 +262,10 @@ static void igt_check_drm_format_min_pitch_for_tiled_format(struct kunit *test) /* Test tiled format */ info = drm_format_info(DRM_FORMAT_X0L2); - KUNIT_EXPECT_TRUE(test, info); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); - KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 2); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 4); From 0173ce114dc4df73e0ee3e1eafea156b7b26e719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Wed, 31 Aug 2022 23:56:08 +0200 Subject: [PATCH 041/119] drm/format: Split into more granular test cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While we have multiple test cases, most of them check multiple conditions, calling the function that is tested multiple times with different arguments (with comments that indicate test case boundary). This usually means that it can be easily converted into multiple test cases. Passing output: ============================================================ ================= drm_format (18 subtests) ================= [PASSED] drm_format_block_width_invalid [PASSED] drm_format_block_width_one_plane [PASSED] drm_format_block_width_two_plane [PASSED] drm_format_block_width_three_plane [PASSED] drm_format_block_width_tiled [PASSED] drm_format_block_height_invalid [PASSED] drm_format_block_height_one_plane [PASSED] drm_format_block_height_two_plane [PASSED] drm_format_block_height_three_plane [PASSED] drm_format_block_height_tiled [PASSED] drm_format_min_pitch_invalid [PASSED] drm_format_min_pitch_one_plane_8bpp [PASSED] drm_format_min_pitch_one_plane_16bpp [PASSED] drm_format_min_pitch_one_plane_24bpp [PASSED] drm_format_min_pitch_one_plane_32bpp [PASSED] drm_format_min_pitch_two_plane [PASSED] drm_format_min_pitch_three_plane_8bpp [PASSED] drm_format_min_pitch_tiled =================== [PASSED] drm_format ==================== ============================================================ Testing complete. Ran 18 tests: passed: 18 Signed-off-by: Michał Winiarski Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20220831215608.349269-2-michal.winiarski@intel.com --- drivers/gpu/drm/tests/drm_format_test.c | 156 ++++++++++++++++-------- 1 file changed, 108 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_format_test.c b/drivers/gpu/drm/tests/drm_format_test.c index 0efa88bf56a9d..1936d2d599087 100644 --- a/drivers/gpu/drm/tests/drm_format_test.c +++ b/drivers/gpu/drm/tests/drm_format_test.c @@ -9,100 +9,133 @@ #include -static void igt_check_drm_format_block_width(struct kunit *test) +static void drm_format_block_width_invalid(struct kunit *test) { const struct drm_format_info *info = NULL; - /* Test invalid arguments */ KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 0); +} + +static void drm_format_block_width_one_plane(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_XRGB4444); - /* Test 1 plane format */ - info = drm_format_info(DRM_FORMAT_XRGB4444); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); +} + +static void drm_format_block_width_two_plane(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_NV12); - /* Test 2 planes format */ - info = drm_format_info(DRM_FORMAT_NV12); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 2), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); +} + +static void drm_format_block_width_three_plane(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_YUV422); - /* Test 3 planes format */ - info = drm_format_info(DRM_FORMAT_YUV422); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 2), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 3), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); +} + +static void drm_format_block_width_tiled(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_X0L0); - /* Test a tiled format */ - info = drm_format_info(DRM_FORMAT_X0L0); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 2); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); } -static void igt_check_drm_format_block_height(struct kunit *test) +static void drm_format_block_height_invalid(struct kunit *test) { const struct drm_format_info *info = NULL; - /* Test invalid arguments */ KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 0); +} + +static void drm_format_block_height_one_plane(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_XRGB4444); - /* Test 1 plane format */ - info = drm_format_info(DRM_FORMAT_XRGB4444); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 0); +} + +static void drm_format_block_height_two_plane(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_NV12); - /* Test 2 planes format */ - info = drm_format_info(DRM_FORMAT_NV12); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 2), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); +} + +static void drm_format_block_height_three_plane(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_YUV422); - /* Test 3 planes format */ - info = drm_format_info(DRM_FORMAT_YUV422); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 2), 1); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 3), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); +} + +static void drm_format_block_height_tiled(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_X0L0); - /* Test a tiled format */ - info = drm_format_info(DRM_FORMAT_X0L0); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 2); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 0); KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); } -static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) +static void drm_format_min_pitch_invalid(struct kunit *test) { const struct drm_format_info *info = NULL; - /* Test invalid arguments */ KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); +} + +static void drm_format_min_pitch_one_plane_8bpp(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_RGB332); - /* Test 1 plane 8 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_RGB332); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); @@ -118,10 +151,14 @@ static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) (uint64_t)UINT_MAX); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), (uint64_t)(UINT_MAX - 1)); +} + +static void drm_format_min_pitch_one_plane_16bpp(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_XRGB4444); - /* Test 1 plane 16 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_XRGB4444); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); @@ -137,10 +174,14 @@ static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) (uint64_t)UINT_MAX * 2); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), (uint64_t)(UINT_MAX - 1) * 2); +} + +static void drm_format_min_pitch_one_plane_24bpp(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_RGB888); - /* Test 1 plane 24 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_RGB888); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); @@ -154,12 +195,16 @@ static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 2013); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX), (uint64_t)UINT_MAX * 3); - KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX - 1), (uint64_t)(UINT_MAX - 1) * 3); +} + +static void drm_format_min_pitch_one_plane_32bpp(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_ABGR8888); - /* Test 1 plane 32 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_ABGR8888); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); @@ -173,17 +218,16 @@ static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 2684); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX), (uint64_t)UINT_MAX * 4); - KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX - 1), (uint64_t)(UINT_MAX - 1) * 4); } -static void igt_check_drm_format_min_pitch_for_multi_planar(struct kunit *test) +static void drm_format_min_pitch_two_plane(struct kunit *test) { - const struct drm_format_info *info = NULL; + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_NV12); - /* Test 2 planes format */ - info = drm_format_info(DRM_FORMAT_NV12); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); @@ -211,10 +255,14 @@ static void igt_check_drm_format_min_pitch_for_multi_planar(struct kunit *test) (uint64_t)(UINT_MAX - 1)); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2), (uint64_t)(UINT_MAX - 1)); +} + +static void drm_format_min_pitch_three_plane_8bpp(struct kunit *test) +{ + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_YUV422); - /* Test 3 planes 8 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_YUV422); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 0), 0); @@ -256,13 +304,12 @@ static void igt_check_drm_format_min_pitch_for_multi_planar(struct kunit *test) (uint64_t)(UINT_MAX - 1) / 2); } -static void igt_check_drm_format_min_pitch_for_tiled_format(struct kunit *test) +static void drm_format_min_pitch_tiled(struct kunit *test) { - const struct drm_format_info *info = NULL; + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_X0L2); - /* Test tiled format */ - info = drm_format_info(DRM_FORMAT_X0L2); KUNIT_ASSERT_NOT_NULL(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, -1, 0), 0); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); @@ -281,12 +328,25 @@ static void igt_check_drm_format_min_pitch_for_tiled_format(struct kunit *test) } static struct kunit_case drm_format_tests[] = { - KUNIT_CASE(igt_check_drm_format_block_width), - KUNIT_CASE(igt_check_drm_format_block_height), - KUNIT_CASE(igt_check_drm_format_min_pitch_for_single_plane), - KUNIT_CASE(igt_check_drm_format_min_pitch_for_multi_planar), - KUNIT_CASE(igt_check_drm_format_min_pitch_for_tiled_format), - { } + KUNIT_CASE(drm_format_block_width_invalid), + KUNIT_CASE(drm_format_block_width_one_plane), + KUNIT_CASE(drm_format_block_width_two_plane), + KUNIT_CASE(drm_format_block_width_three_plane), + KUNIT_CASE(drm_format_block_width_tiled), + KUNIT_CASE(drm_format_block_height_invalid), + KUNIT_CASE(drm_format_block_height_one_plane), + KUNIT_CASE(drm_format_block_height_two_plane), + KUNIT_CASE(drm_format_block_height_three_plane), + KUNIT_CASE(drm_format_block_height_tiled), + KUNIT_CASE(drm_format_min_pitch_invalid), + KUNIT_CASE(drm_format_min_pitch_one_plane_8bpp), + KUNIT_CASE(drm_format_min_pitch_one_plane_16bpp), + KUNIT_CASE(drm_format_min_pitch_one_plane_24bpp), + KUNIT_CASE(drm_format_min_pitch_one_plane_32bpp), + KUNIT_CASE(drm_format_min_pitch_two_plane), + KUNIT_CASE(drm_format_min_pitch_three_plane_8bpp), + KUNIT_CASE(drm_format_min_pitch_tiled), + {} }; static struct kunit_suite drm_format_test_suite = { From 6d6e732835db92e66c28dbcf258a7e3d3c71420d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 11:51:04 +0200 Subject: [PATCH 042/119] drm/udl: Restore display mode on resume Restore the display mode whne resuming from suspend. Currently, the display remains dark. On resume, the CRTC's mode does not change, but the 'active' flag changes to 'true'. Taking this into account when considering a mode switch restores the display mode. The bug is reproducable by using Gnome with udl and observing the adapter's suspend/resume behavior. Actually, the whole check added in udl_simple_display_pipe_enable() about the crtc_state->mode_changed was bogus. We should drop the whole check and always apply the mode change in this function. [ tiwai -- Drop the mode_changed check entirely instead, per Daniel's suggestion ] Fixes: 997d33c35618 ("drm/udl: Inline DPMS code into CRTC enable and disable functions") Cc: Suggested-by: Daniel Vetter Reviewed-by: Daniel Vetter Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-2-tiwai@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 169110d8fc2e1..34ce5b43c5dbd 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -382,9 +382,6 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, udl_handle_damage(fb, &shadow_plane_state->data[0], 0, 0, fb->width, fb->height); - if (!crtc_state->mode_changed) - return; - /* enable display */ udl_crtc_write_mode_to_hw(crtc); } From 1ceef996c99f1e8a44df8714fcf12822353ac488 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 8 Sep 2022 11:51:05 +0200 Subject: [PATCH 043/119] drm/udl: Add reset_resume Implement the reset_resume callback of struct usb_driver. Set the standard channel when called. Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Signed-off-by: Takashi Iwai Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-3-tiwai@suse.de --- drivers/gpu/drm/udl/udl_drv.c | 11 +++++++++++ drivers/gpu/drm/udl/udl_drv.h | 1 + drivers/gpu/drm/udl/udl_main.c | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 5703277c6f527..0ba88e5472a9f 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -32,6 +32,16 @@ static int udl_usb_resume(struct usb_interface *interface) return drm_mode_config_helper_resume(dev); } +static int udl_usb_reset_resume(struct usb_interface *interface) +{ + struct drm_device *dev = usb_get_intfdata(interface); + struct udl_device *udl = to_udl(dev); + + udl_select_std_channel(udl); + + return drm_mode_config_helper_resume(dev); +} + /* * FIXME: Dma-buf sharing requires DMA support by the importing device. * This function is a workaround to make USB devices work as well. @@ -140,6 +150,7 @@ static struct usb_driver udl_driver = { .disconnect = udl_usb_disconnect, .suspend = udl_usb_suspend, .resume = udl_usb_resume, + .reset_resume = udl_usb_reset_resume, .id_table = id_table, }; module_usb_driver(udl_driver); diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 28aaf75d71cf0..37c14b0ff1fc7 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -95,6 +95,7 @@ int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr, u32 byte_offset, u32 device_byte_offset, u32 byte_width); int udl_drop_usb(struct drm_device *dev); +int udl_select_std_channel(struct udl_device *udl); #define CMD_WRITE_RAW8 "\xAF\x60" /**< 8 bit raw write command. */ #define CMD_WRITE_RL8 "\xAF\x61" /**< 8 bit run length command. */ diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index fdafbf8f3c3cb..7d1e6bbc165c5 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -92,7 +92,7 @@ static int udl_parse_vendor_descriptor(struct udl_device *udl) /* * Need to ensure a channel is selected before submitting URBs */ -static int udl_select_std_channel(struct udl_device *udl) +int udl_select_std_channel(struct udl_device *udl) { static const u8 set_def_chn[] = {0x57, 0xCD, 0xDC, 0xA7, 0x1C, 0x88, 0x5E, 0x15, From 0a80005d3c5fea0a21fa6553724c171495ece9b5 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 8 Sep 2022 11:51:06 +0200 Subject: [PATCH 044/119] drm/udl: Enable damage clipping Call drm_plane_enable_fb_damage_clips() and give userspace a chance of minimizing the updated display area. Signed-off-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-4-tiwai@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 34ce5b43c5dbd..b2377b7064829 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -480,6 +480,7 @@ int udl_modeset_init(struct drm_device *dev) format_count, NULL, connector); if (ret) return ret; + drm_plane_enable_fb_damage_clips(&udl->display_pipe.plane); drm_mode_config_reset(dev); From ed9605a66b62f27513aba1d95f7d470c4abda29f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 11:51:07 +0200 Subject: [PATCH 045/119] Revert "drm/udl: Kill pending URBs at suspend and disconnect" This reverts the recent fix commit e25d5954264d ("drm/udl: Kill pending URBs at suspend and disconnect") as it turned out to lead to potential hangup at a disconnection, and it doesn't help much for suspend/resume problem, either. Acked-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-5-tiwai@suse.de --- drivers/gpu/drm/udl/udl_drv.h | 2 -- drivers/gpu/drm/udl/udl_main.c | 25 +++---------------------- drivers/gpu/drm/udl/udl_modeset.c | 2 -- 3 files changed, 3 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 37c14b0ff1fc7..5923d2e02bc88 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -39,7 +39,6 @@ struct urb_node { struct urb_list { struct list_head list; - struct list_head in_flight; spinlock_t lock; wait_queue_head_t sleep; int available; @@ -85,7 +84,6 @@ static inline struct urb *udl_get_urb(struct drm_device *dev) int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len); int udl_sync_pending_urbs(struct drm_device *dev); -void udl_kill_pending_urbs(struct drm_device *dev); void udl_urb_completion(struct urb *urb); int udl_init(struct udl_device *udl); diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 7d1e6bbc165c5..a9f6b710b254e 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -135,7 +135,7 @@ void udl_urb_completion(struct urb *urb) urb->transfer_buffer_length = udl->urbs.size; /* reset to actual */ spin_lock_irqsave(&udl->urbs.lock, flags); - list_move(&unode->entry, &udl->urbs.list); + list_add_tail(&unode->entry, &udl->urbs.list); udl->urbs.available++; spin_unlock_irqrestore(&udl->urbs.lock, flags); @@ -180,7 +180,6 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) retry: udl->urbs.size = size; INIT_LIST_HEAD(&udl->urbs.list); - INIT_LIST_HEAD(&udl->urbs.in_flight); init_waitqueue_head(&udl->urbs.sleep); udl->urbs.count = 0; @@ -247,7 +246,7 @@ struct urb *udl_get_urb_timeout(struct drm_device *dev, long timeout) } unode = list_first_entry(&udl->urbs.list, struct urb_node, entry); - list_move(&unode->entry, &udl->urbs.in_flight); + list_del_init(&unode->entry); udl->urbs.available--; unlock: @@ -281,7 +280,7 @@ int udl_sync_pending_urbs(struct drm_device *dev) spin_lock_irq(&udl->urbs.lock); /* 2 seconds as a sane timeout */ if (!wait_event_lock_irq_timeout(udl->urbs.sleep, - list_empty(&udl->urbs.in_flight), + udl->urbs.available == udl->urbs.count, udl->urbs.lock, msecs_to_jiffies(2000))) ret = -ETIMEDOUT; @@ -289,23 +288,6 @@ int udl_sync_pending_urbs(struct drm_device *dev) return ret; } -/* kill pending URBs */ -void udl_kill_pending_urbs(struct drm_device *dev) -{ - struct udl_device *udl = to_udl(dev); - struct urb_node *unode; - - spin_lock_irq(&udl->urbs.lock); - while (!list_empty(&udl->urbs.in_flight)) { - unode = list_first_entry(&udl->urbs.in_flight, - struct urb_node, entry); - spin_unlock_irq(&udl->urbs.lock); - usb_kill_urb(unode->urb); - spin_lock_irq(&udl->urbs.lock); - } - spin_unlock_irq(&udl->urbs.lock); -} - int udl_init(struct udl_device *udl) { struct drm_device *dev = &udl->drm; @@ -354,7 +336,6 @@ int udl_drop_usb(struct drm_device *dev) { struct udl_device *udl = to_udl(dev); - udl_kill_pending_urbs(dev); udl_free_urb_list(dev); put_device(udl->dmadev); udl->dmadev = NULL; diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index b2377b7064829..cbdda2d8b8829 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -394,8 +394,6 @@ udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) struct urb *urb; char *buf; - udl_kill_pending_urbs(dev); - urb = udl_get_urb(dev); if (!urb) return; From 53593515ec1a4a5afaaa88fd4522bc4c2d7f5d9b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 11:51:08 +0200 Subject: [PATCH 046/119] drm/udl: Suppress error print for -EPROTO at URB completion The driver may receive -EPROTO at the URB completion when the device gets disconnected, and it's a normal situation. Suppress the error print for that, too. Signed-off-by: Takashi Iwai Acked-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-6-tiwai@suse.de --- drivers/gpu/drm/udl/udl_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index a9f6b710b254e..6aed6e0f669c1 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -126,6 +126,7 @@ void udl_urb_completion(struct urb *urb) if (urb->status) { if (!(urb->status == -ENOENT || urb->status == -ECONNRESET || + urb->status == -EPROTO || urb->status == -ESHUTDOWN)) { DRM_ERROR("%s - nonzero write bulk status received: %d\n", __func__, urb->status); From 2a07a5ddb135e4bd15bf6468b7d2daa4deeaf07d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 11:51:09 +0200 Subject: [PATCH 047/119] drm/udl: Increase the default URB list size to 20 It seems that the current size (4) for the URB list is too small on some devices, and it resulted in the occasional stalls. Increase the default URB list size to 20 for working around it. Acked-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-7-tiwai@suse.de --- drivers/gpu/drm/udl/udl_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 6aed6e0f669c1..2b7eafd48ec21 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -20,7 +20,7 @@ #define NR_USB_REQUEST_CHANNEL 0x12 #define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE) -#define WRITES_IN_FLIGHT (4) +#define WRITES_IN_FLIGHT (20) #define MAX_VENDOR_DESCRIPTOR_SIZE 256 static int udl_parse_vendor_descriptor(struct udl_device *udl) From aeb76f97fcf5bf6c094c62ac5cc22a1949751236 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 11:51:10 +0200 Subject: [PATCH 048/119] drm/udl: Drop unneeded alignment The alignment of damaged area was needed for the original udlfb driver that tried to trim the superfluous copies between front and backend buffers and handle data in long int. It's not the case for udl DRM driver, hence we can omit the whole unneeded alignment, as well as the dead code. Acked-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-8-tiwai@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 28 +-------------------- drivers/gpu/drm/udl/udl_transfer.c | 40 ------------------------------ 2 files changed, 1 insertion(+), 67 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index cbdda2d8b8829..c9b837ac26a78 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -242,28 +242,6 @@ static long udl_log_cpp(unsigned int cpp) return __ffs(cpp); } -static int udl_aligned_damage_clip(struct drm_rect *clip, int x, int y, - int width, int height) -{ - int x1, x2; - - if (WARN_ON_ONCE(x < 0) || - WARN_ON_ONCE(y < 0) || - WARN_ON_ONCE(width < 0) || - WARN_ON_ONCE(height < 0)) - return -EINVAL; - - x1 = ALIGN_DOWN(x, sizeof(unsigned long)); - x2 = ALIGN(width + (x - x1), sizeof(unsigned long)) + x1; - - clip->x1 = x1; - clip->y1 = y; - clip->x2 = x2; - clip->y2 = y + height; - - return 0; -} - static int udl_handle_damage(struct drm_framebuffer *fb, const struct iosys_map *map, int x, int y, int width, int height) @@ -281,11 +259,7 @@ static int udl_handle_damage(struct drm_framebuffer *fb, return ret; log_bpp = ret; - ret = udl_aligned_damage_clip(&clip, x, y, width, height); - if (ret) - return ret; - else if ((clip.x2 > fb->width) || (clip.y2 > fb->height)) - return -EINVAL; + drm_rect_init(&clip, x, y, width, height); ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); if (ret) diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index 176ef2a6a7313..a431208dda858 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -25,46 +25,6 @@ #define MIN_RAW_PIX_BYTES 2 #define MIN_RAW_CMD_BYTES (RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES) -/* - * Trims identical data from front and back of line - * Sets new front buffer address and width - * And returns byte count of identical pixels - * Assumes CPU natural alignment (unsigned long) - * for back and front buffer ptrs and width - */ -#if 0 -static int udl_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes) -{ - int j, k; - const unsigned long *back = (const unsigned long *) bback; - const unsigned long *front = (const unsigned long *) *bfront; - const int width = *width_bytes / sizeof(unsigned long); - int identical = width; - int start = width; - int end = width; - - for (j = 0; j < width; j++) { - if (back[j] != front[j]) { - start = j; - break; - } - } - - for (k = width - 1; k > j; k--) { - if (back[k] != front[k]) { - end = k+1; - break; - } - } - - identical = start + (width - end); - *bfront = (u8 *) &front[start]; - *width_bytes = (end - start) * sizeof(unsigned long); - - return identical * sizeof(unsigned long); -} -#endif - static inline u16 pixel32_to_be16(const uint32_t pixel) { return (((pixel >> 3) & 0x001f) | From b13fa27a4b72caebe99bd483092479c3767453be Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 14:54:51 +0200 Subject: [PATCH 049/119] drm/udl: Pass rectangle directly to udl_handle_damage() Just for some code simplification. Suggested-by: Thomas Zimmermann Acked-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/87tu5iauw4.wl-tiwai@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index c9b837ac26a78..d5e20bf144bcb 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -244,14 +244,13 @@ static long udl_log_cpp(unsigned int cpp) static int udl_handle_damage(struct drm_framebuffer *fb, const struct iosys_map *map, - int x, int y, int width, int height) + const struct drm_rect *clip) { struct drm_device *dev = fb->dev; void *vaddr = map->vaddr; /* TODO: Use mapping abstraction properly */ int i, ret; char *cmd; struct urb *urb; - struct drm_rect clip; int log_bpp; ret = udl_log_cpp(fb->format->cpp[0]); @@ -259,8 +258,6 @@ static int udl_handle_damage(struct drm_framebuffer *fb, return ret; log_bpp = ret; - drm_rect_init(&clip, x, y, width, height); - ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); if (ret) return ret; @@ -272,11 +269,11 @@ static int udl_handle_damage(struct drm_framebuffer *fb, } cmd = urb->transfer_buffer; - for (i = clip.y1; i < clip.y2; i++) { + for (i = clip->y1; i < clip->y2; i++) { const int line_offset = fb->pitches[0] * i; - const int byte_offset = line_offset + (clip.x1 << log_bpp); - const int dev_byte_offset = (fb->width * i + clip.x1) << log_bpp; - const int byte_width = (clip.x2 - clip.x1) << log_bpp; + const int byte_offset = line_offset + (clip->x1 << log_bpp); + const int dev_byte_offset = (fb->width * i + clip->x1) << log_bpp; + const int byte_width = drm_rect_width(clip) << log_bpp; ret = udl_render_hline(dev, log_bpp, &urb, (char *)vaddr, &cmd, byte_offset, dev_byte_offset, byte_width); @@ -329,6 +326,7 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, struct udl_device *udl = to_udl(dev); struct drm_display_mode *mode = &crtc_state->mode; struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); + struct drm_rect clip = DRM_RECT_INIT(0, 0, fb->width, fb->height); char *buf; char *wrptr; int color_depth = UDL_COLOR_DEPTH_16BPP; @@ -354,7 +352,7 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, udl->mode_buf_len = wrptr - buf; - udl_handle_damage(fb, &shadow_plane_state->data[0], 0, 0, fb->width, fb->height); + udl_handle_damage(fb, &shadow_plane_state->data[0], &clip); /* enable display */ udl_crtc_write_mode_to_hw(crtc); @@ -396,8 +394,7 @@ udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, return; if (drm_atomic_helper_damage_merged(old_plane_state, state, &rect)) - udl_handle_damage(fb, &shadow_plane_state->data[0], rect.x1, rect.y1, - rect.x2 - rect.x1, rect.y2 - rect.y1); + udl_handle_damage(fb, &shadow_plane_state->data[0], &rect); } static const struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs = { From 046f4f0af7fd1fad06793d863d288c6b2cd84e99 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 11:51:12 +0200 Subject: [PATCH 050/119] drm/udl: Fix potential URB leaks A couple of error handlings forgot to process the URB completion. Those are both with WARN_ON() so should be visible, but we must fix them in anyway. Fixes: 7350b2a3fbc6 ("drm/udl: Replace BUG_ON() with WARN_ON()") Acked-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-10-tiwai@suse.de --- drivers/gpu/drm/udl/udl_main.c | 8 +++++--- drivers/gpu/drm/udl/udl_transfer.c | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 2b7eafd48ec21..de28eeff3155d 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -260,11 +260,13 @@ int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len) struct udl_device *udl = to_udl(dev); int ret; - if (WARN_ON(len > udl->urbs.size)) - return -EINVAL; - + if (WARN_ON(len > udl->urbs.size)) { + ret = -EINVAL; + goto error; + } urb->transfer_buffer_length = len; /* set to actual payload len */ ret = usb_submit_urb(urb, GFP_ATOMIC); + error: if (ret) { udl_urb_completion(urb); /* because no one else will */ DRM_ERROR("usb_submit_urb error %x\n", ret); diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index a431208dda858..b57844632dbd7 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -180,8 +180,11 @@ int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr, u8 *cmd = *urb_buf_ptr; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; - if (WARN_ON(!(log_bpp == 1 || log_bpp == 2))) + if (WARN_ON(!(log_bpp == 1 || log_bpp == 2))) { + /* need to finish URB at error from this function */ + udl_urb_completion(urb); return -EINVAL; + } line_start = (u8 *) (front + byte_offset); next_pixel = line_start; From c5c354a3a4728045e1342166394c615d75d45377 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 11:51:13 +0200 Subject: [PATCH 051/119] drm/udl: Fix inconsistent urbs.count value during udl_free_urb_list() In the current design, udl_get_urb() may be called asynchronously during the driver freeing its URL list via udl_free_urb_list(). The problem is that the sync is determined by comparing the urbs.count and urbs.available fields, while we clear urbs.count field only once after udl_free_urb_list() finishes, i.e. during udl_free_urb_list(), the state becomes inconsistent. For fixing this inconsistency and also for hardening the locking scheme, this patch does a slight refactoring of the code around udl_get_urb() and udl_free_urb_list(). Now urbs.count is updated in the same spinlock at extracting a URB from the list in udl_free_url_list(). Acked-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-11-tiwai@suse.de --- drivers/gpu/drm/udl/udl_drv.h | 8 +------ drivers/gpu/drm/udl/udl_main.c | 42 +++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 5923d2e02bc88..d943684b5bbb2 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -74,13 +74,7 @@ static inline struct usb_device *udl_to_usb_device(struct udl_device *udl) int udl_modeset_init(struct drm_device *dev); struct drm_connector *udl_connector_init(struct drm_device *dev); -struct urb *udl_get_urb_timeout(struct drm_device *dev, long timeout); - -#define GET_URB_TIMEOUT HZ -static inline struct urb *udl_get_urb(struct drm_device *dev) -{ - return udl_get_urb_timeout(dev, GET_URB_TIMEOUT); -} +struct urb *udl_get_urb(struct drm_device *dev); int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len); int udl_sync_pending_urbs(struct drm_device *dev); diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index de28eeff3155d..16aa4a655e7f7 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -23,6 +23,8 @@ #define WRITES_IN_FLIGHT (20) #define MAX_VENDOR_DESCRIPTOR_SIZE 256 +static struct urb *udl_get_urb_locked(struct udl_device *udl, long timeout); + static int udl_parse_vendor_descriptor(struct udl_device *udl) { struct usb_device *udev = udl_to_usb_device(udl); @@ -146,15 +148,17 @@ void udl_urb_completion(struct urb *urb) static void udl_free_urb_list(struct drm_device *dev) { struct udl_device *udl = to_udl(dev); - int count = udl->urbs.count; struct urb_node *unode; struct urb *urb; DRM_DEBUG("Waiting for completes and freeing all render urbs\n"); /* keep waiting and freeing, until we've got 'em all */ - while (count--) { - urb = udl_get_urb_timeout(dev, MAX_SCHEDULE_TIMEOUT); + while (udl->urbs.count) { + spin_lock_irq(&udl->urbs.lock); + urb = udl_get_urb_locked(udl, MAX_SCHEDULE_TIMEOUT); + udl->urbs.count--; + spin_unlock_irq(&udl->urbs.lock); if (WARN_ON(!urb)) break; unode = urb->context; @@ -164,7 +168,8 @@ static void udl_free_urb_list(struct drm_device *dev) usb_free_urb(urb); kfree(unode); } - udl->urbs.count = 0; + + wake_up_all(&udl->urbs.sleep); } static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) @@ -228,33 +233,44 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) return udl->urbs.count; } -struct urb *udl_get_urb_timeout(struct drm_device *dev, long timeout) +static struct urb *udl_get_urb_locked(struct udl_device *udl, long timeout) { - struct udl_device *udl = to_udl(dev); - struct urb_node *unode = NULL; + struct urb_node *unode; - if (!udl->urbs.count) - return NULL; + assert_spin_locked(&udl->urbs.lock); /* Wait for an in-flight buffer to complete and get re-queued */ - spin_lock_irq(&udl->urbs.lock); if (!wait_event_lock_irq_timeout(udl->urbs.sleep, + !udl->urbs.count || !list_empty(&udl->urbs.list), udl->urbs.lock, timeout)) { DRM_INFO("wait for urb interrupted: available: %d\n", udl->urbs.available); - goto unlock; + return NULL; } + if (!udl->urbs.count) + return NULL; + unode = list_first_entry(&udl->urbs.list, struct urb_node, entry); list_del_init(&unode->entry); udl->urbs.available--; -unlock: - spin_unlock_irq(&udl->urbs.lock); return unode ? unode->urb : NULL; } +#define GET_URB_TIMEOUT HZ +struct urb *udl_get_urb(struct drm_device *dev) +{ + struct udl_device *udl = to_udl(dev); + struct urb *urb; + + spin_lock_irq(&udl->urbs.lock); + urb = udl_get_urb_locked(udl, GET_URB_TIMEOUT); + spin_unlock_irq(&udl->urbs.lock); + return urb; +} + int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len) { struct udl_device *udl = to_udl(dev); From 2c2705bd09730dba6017b26897a2bcd3c5d21557 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 11:51:14 +0200 Subject: [PATCH 052/119] drm/udl: Don't re-initialize stuff at retrying the URB list allocation udl_alloc_urb_list() retires the allocation if there is no enough room left, and it reinitializes the stuff unnecessarily such as the linked list head and the waitqueue, which could be harmful. Those should be outside the retry loop. Acked-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-12-tiwai@suse.de --- drivers/gpu/drm/udl/udl_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 16aa4a655e7f7..829edb60a987d 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -182,15 +182,14 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) struct usb_device *udev = udl_to_usb_device(udl); spin_lock_init(&udl->urbs.lock); - -retry: - udl->urbs.size = size; INIT_LIST_HEAD(&udl->urbs.list); - init_waitqueue_head(&udl->urbs.sleep); udl->urbs.count = 0; udl->urbs.available = 0; +retry: + udl->urbs.size = size; + while (udl->urbs.count * size < wanted_size) { unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL); if (!unode) From fa47573b04a35078953be5f81a78f22c96358817 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2022 11:51:15 +0200 Subject: [PATCH 053/119] drm/udl: Sync pending URBs at the end of suspend It's better to perform the sync at the very last of the suspend instead of the pipe-disable function, so that we can catch all pending URBs (if any). While we're at it, drop the error code from udl_sync_pending_urb() since we basically ignore it; instead, give a clear error message indicating a problem. Acked-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220908095115.23396-13-tiwai@suse.de --- drivers/gpu/drm/udl/udl_drv.c | 8 +++++++- drivers/gpu/drm/udl/udl_drv.h | 2 +- drivers/gpu/drm/udl/udl_main.c | 6 ++---- drivers/gpu/drm/udl/udl_modeset.c | 2 -- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 0ba88e5472a9f..91effdcefb6d5 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -21,8 +21,14 @@ static int udl_usb_suspend(struct usb_interface *interface, pm_message_t message) { struct drm_device *dev = usb_get_intfdata(interface); + int ret; - return drm_mode_config_helper_suspend(dev); + ret = drm_mode_config_helper_suspend(dev); + if (ret) + return ret; + + udl_sync_pending_urbs(dev); + return 0; } static int udl_usb_resume(struct usb_interface *interface) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index d943684b5bbb2..b4cc7cc568c74 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -77,7 +77,7 @@ struct drm_connector *udl_connector_init(struct drm_device *dev); struct urb *udl_get_urb(struct drm_device *dev); int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len); -int udl_sync_pending_urbs(struct drm_device *dev); +void udl_sync_pending_urbs(struct drm_device *dev); void udl_urb_completion(struct urb *urb); int udl_init(struct udl_device *udl); diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 829edb60a987d..061cb88c08a21 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -290,10 +290,9 @@ int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len) } /* wait until all pending URBs have been processed */ -int udl_sync_pending_urbs(struct drm_device *dev) +void udl_sync_pending_urbs(struct drm_device *dev) { struct udl_device *udl = to_udl(dev); - int ret = 0; spin_lock_irq(&udl->urbs.lock); /* 2 seconds as a sane timeout */ @@ -301,9 +300,8 @@ int udl_sync_pending_urbs(struct drm_device *dev) udl->urbs.available == udl->urbs.count, udl->urbs.lock, msecs_to_jiffies(2000))) - ret = -ETIMEDOUT; + drm_err(dev, "Timeout for syncing pending URBs\n"); spin_unlock_irq(&udl->urbs.lock); - return ret; } int udl_init(struct udl_device *udl) diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index d5e20bf144bcb..ec6876f449f31 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -377,8 +377,6 @@ udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) buf = udl_dummy_render(buf); udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer); - - udl_sync_pending_urbs(dev); } static void From aaa65520280e96dc47fa5065b74bddff30279abe Mon Sep 17 00:00:00 2001 From: Harshit Mogalapalli Date: Thu, 8 Sep 2022 03:56:23 -0700 Subject: [PATCH 054/119] drm/vkms: fix variable dereferenced before check warning Smatch warns: drivers/gpu/drm/vkms/vkms_plane.c:110 vkms_plane_atomic_update() warn: variable dereferenced before check 'fb' (see line 108) Fix the warning by moving the dereference after the NULL check. Fixes: 8ba1648567e2 ("drm: vkms: Refactor the plane composer to accept new formats") Signed-off-by: Harshit Mogalapalli Reviewed-by: Melissa Wen Signed-off-by: Melissa Wen Link: https://patchwork.freedesktop.org/patch/msgid/20220908105623.72777-1-harshit.m.mogalapalli@oracle.com --- drivers/gpu/drm/vkms/vkms_plane.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index f4319066adcc9..c3a845220e10c 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -105,11 +105,12 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, struct drm_shadow_plane_state *shadow_plane_state; struct drm_framebuffer *fb = new_state->fb; struct vkms_frame_info *frame_info; - u32 fmt = fb->format->format; + u32 fmt; if (!new_state->crtc || !fb) return; + fmt = fb->format->format; vkms_plane_state = to_vkms_plane_state(new_state); shadow_plane_state = &vkms_plane_state->base; From d25654b3fad9906ca80912701fd4bd6e2419f54d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 5 Sep 2022 16:16:45 +0200 Subject: [PATCH 055/119] drm/probe-helper: Add drm_connector_helper_get_modes_fixed() Add drm_connector_helper_get_modes_fixed(), which duplicates a single display mode for a connector. Convert drivers. v2: * rename 'static' and 'hw' to 'fixed' everywhere * fix typo 'there' to 'their' (Sam) Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220905141648.22013-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_mipi_dbi.c | 20 +-------------- drivers/gpu/drm/drm_probe_helper.c | 40 ++++++++++++++++++++++++++++++ drivers/gpu/drm/tiny/repaper.c | 16 +----------- drivers/gpu/drm/tiny/simpledrm.c | 18 +------------- include/drm/drm_probe_helper.h | 3 +++ 5 files changed, 46 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 84abc3920b573..de2a5be67415b 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -415,26 +415,8 @@ EXPORT_SYMBOL(mipi_dbi_pipe_disable); static int mipi_dbi_connector_get_modes(struct drm_connector *connector) { struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(connector->dev); - struct drm_display_mode *mode; - mode = drm_mode_duplicate(connector->dev, &dbidev->mode); - if (!mode) { - DRM_ERROR("Failed to duplicate mode\n"); - return 0; - } - - if (mode->name[0] == '\0') - drm_mode_set_name(mode); - - mode->type |= DRM_MODE_TYPE_PREFERRED; - drm_mode_probed_add(connector, mode); - - if (mode->width_mm) { - connector->display_info.width_mm = mode->width_mm; - connector->display_info.height_mm = mode->height_mm; - } - - return 1; + return drm_connector_helper_get_modes_fixed(connector, &dbidev->mode); } static const struct drm_connector_helper_funcs mipi_dbi_connector_hfuncs = { diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index bb427c5a4f1f3..818150a1b3b04 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -1050,6 +1050,46 @@ int drm_connector_helper_get_modes_from_ddc(struct drm_connector *connector) } EXPORT_SYMBOL(drm_connector_helper_get_modes_from_ddc); +/** + * drm_connector_helper_get_modes_fixed - Duplicates a display mode for a connector + * @connector: the connector + * @fixed_mode: the display hardware's mode + * + * This function duplicates a display modes for a connector. Drivers for hardware + * that only supports a single fixed mode can use this function in their connector's + * get_modes helper. + * + * Returns: + * The number of created modes. + */ +int drm_connector_helper_get_modes_fixed(struct drm_connector *connector, + const struct drm_display_mode *fixed_mode) +{ + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(dev, fixed_mode); + if (!mode) { + drm_err(dev, "Failed to duplicate mode " DRM_MODE_FMT "\n", + DRM_MODE_ARG(fixed_mode)); + return 0; + } + + if (mode->name[0] == '\0') + drm_mode_set_name(mode); + + mode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + + if (mode->width_mm) + connector->display_info.width_mm = mode->width_mm; + if (mode->height_mm) + connector->display_info.height_mm = mode->height_mm; + + return 1; +} +EXPORT_SYMBOL(drm_connector_helper_get_modes_fixed); + /** * drm_connector_helper_get_modes - Read EDID and update connector. * @connector: The connector diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index c4c1be3ac0b86..01fbd00411fc9 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -839,22 +839,8 @@ static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = { static int repaper_connector_get_modes(struct drm_connector *connector) { struct repaper_epd *epd = drm_to_epd(connector->dev); - struct drm_display_mode *mode; - mode = drm_mode_duplicate(connector->dev, epd->mode); - if (!mode) { - DRM_ERROR("Failed to duplicate mode\n"); - return 0; - } - - drm_mode_set_name(mode); - mode->type |= DRM_MODE_TYPE_PREFERRED; - drm_mode_probed_add(connector, mode); - - connector->display_info.width_mm = mode->width_mm; - connector->display_info.height_mm = mode->height_mm; - - return 1; + return drm_connector_helper_get_modes_fixed(connector, epd->mode); } static const struct drm_connector_helper_funcs repaper_connector_hfuncs = { diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index a81f91814595b..c79576844ec0c 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -620,24 +620,8 @@ static const struct drm_encoder_funcs simpledrm_encoder_funcs = { static int simpledrm_connector_helper_get_modes(struct drm_connector *connector) { struct simpledrm_device *sdev = simpledrm_device_of_dev(connector->dev); - struct drm_display_mode *mode; - mode = drm_mode_duplicate(connector->dev, &sdev->mode); - if (!mode) - return 0; - - if (mode->name[0] == '\0') - drm_mode_set_name(mode); - - mode->type |= DRM_MODE_TYPE_PREFERRED; - drm_mode_probed_add(connector, mode); - - if (mode->width_mm) - connector->display_info.width_mm = mode->width_mm; - if (mode->height_mm) - connector->display_info.height_mm = mode->height_mm; - - return 1; + return drm_connector_helper_get_modes_fixed(connector, &sdev->mode); } static const struct drm_connector_helper_funcs simpledrm_connector_helper_funcs = { diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h index 8075e02aa8654..d261838a7790e 100644 --- a/include/drm/drm_probe_helper.h +++ b/include/drm/drm_probe_helper.h @@ -7,6 +7,7 @@ struct drm_connector; struct drm_device; +struct drm_display_mode; struct drm_modeset_acquire_ctx; int drm_helper_probe_single_connector_modes(struct drm_connector @@ -27,6 +28,8 @@ void drm_kms_helper_poll_enable(struct drm_device *dev); bool drm_kms_helper_is_poll_worker(void); int drm_connector_helper_get_modes_from_ddc(struct drm_connector *connector); +int drm_connector_helper_get_modes_fixed(struct drm_connector *connector, + const struct drm_display_mode *fixed_mode); int drm_connector_helper_get_modes(struct drm_connector *connector); #endif From 216b9bbaeaea96b7f05c220f61855d174be972d8 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 5 Sep 2022 16:16:46 +0200 Subject: [PATCH 056/119] drm/probe-helper: Add drm_crtc_helper_mode_valid_fixed() Add drm_crtc_helper_mode_valid_fixed(), which validates a given mode against a display hardware's mode. Convert simpledrm and use it in a few other drivers with static modes. v4: * remove empty line after opening brace v2: * rename 'static' and 'hw' to 'fixed' everywhere Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220905141648.22013-3-tzimmermann@suse.de --- drivers/gpu/drm/drm_mipi_dbi.c | 18 +++++++++++++++ drivers/gpu/drm/drm_probe_helper.c | 24 ++++++++++++++++++++ drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 1 + drivers/gpu/drm/tiny/hx8357d.c | 1 + drivers/gpu/drm/tiny/ili9163.c | 1 + drivers/gpu/drm/tiny/ili9341.c | 1 + drivers/gpu/drm/tiny/ili9486.c | 1 + drivers/gpu/drm/tiny/mi0283qt.c | 1 + drivers/gpu/drm/tiny/panel-mipi-dbi.c | 1 + drivers/gpu/drm/tiny/repaper.c | 10 ++++++++ drivers/gpu/drm/tiny/simpledrm.c | 10 +------- drivers/gpu/drm/tiny/st7735r.c | 1 + include/drm/drm_mipi_dbi.h | 2 ++ include/drm/drm_probe_helper.h | 8 +++++-- 14 files changed, 69 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index de2a5be67415b..a6ac565808765 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -309,6 +309,24 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) drm_dev_exit(idx); } +/** + * mipi_dbi_pipe_mode_valid - MIPI DBI mode-valid helper + * @pipe: Simple display pipe + * @mode: The mode to test + * + * This function validates a given display mode against the MIPI DBI's hardware + * display. Drivers can use this as their &drm_simple_display_pipe_funcs->mode_valid + * callback. + */ +enum drm_mode_status mipi_dbi_pipe_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode) +{ + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); + + return drm_crtc_helper_mode_valid_fixed(&pipe->crtc, mode, &dbidev->mode); +} +EXPORT_SYMBOL(mipi_dbi_pipe_mode_valid); + /** * mipi_dbi_pipe_update - Display pipe update helper * @pipe: Simple display pipe diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 818150a1b3b04..69b0b2b9cc1c5 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -1014,6 +1014,30 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) } EXPORT_SYMBOL(drm_helper_hpd_irq_event); +/** + * drm_crtc_helper_mode_valid_fixed - Validates a display mode + * @crtc: the crtc + * @mode: the mode to validate + * @fixed_mode: the display hardware's mode + * + * Returns: + * MODE_OK on success, or another mode-status code otherwise. + */ +enum drm_mode_status drm_crtc_helper_mode_valid_fixed(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *fixed_mode) +{ + if (mode->hdisplay != fixed_mode->hdisplay && mode->vdisplay != fixed_mode->vdisplay) + return MODE_ONE_SIZE; + else if (mode->hdisplay != fixed_mode->hdisplay) + return MODE_ONE_WIDTH; + else if (mode->vdisplay != fixed_mode->vdisplay) + return MODE_ONE_HEIGHT; + + return MODE_OK; +} +EXPORT_SYMBOL(drm_crtc_helper_mode_valid_fixed); + /** * drm_connector_helper_get_modes_from_ddc - Updates the connector's EDID * property from the connector's diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index 7da09e34385d3..39dc40cf681f0 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -576,6 +576,7 @@ static void ili9341_dbi_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs ili9341_dbi_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = ili9341_dbi_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index 57f229a785bf8..48c24aa8c28a1 100644 --- a/drivers/gpu/drm/tiny/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -181,6 +181,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = yx240qv29_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c index 86439e50e304f..9a1a5943bee01 100644 --- a/drivers/gpu/drm/tiny/ili9163.c +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -100,6 +100,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs ili9163_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = yx240qv29_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index b8826a0b086bf..69b265e78096b 100644 --- a/drivers/gpu/drm/tiny/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -137,6 +137,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = yx240qv29_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c index a5b433a8e0d8a..c80028bb1d110 100644 --- a/drivers/gpu/drm/tiny/ili9486.c +++ b/drivers/gpu/drm/tiny/ili9486.c @@ -150,6 +150,7 @@ static void waveshare_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs waveshare_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = waveshare_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index 27f1bd4da2f4e..bc522fb3d94d1 100644 --- a/drivers/gpu/drm/tiny/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -141,6 +141,7 @@ static void mi0283qt_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = mi0283qt_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c index a76fefa8adbc8..955a61d628e7c 100644 --- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c +++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c @@ -212,6 +212,7 @@ static void panel_mipi_dbi_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs panel_mipi_dbi_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = panel_mipi_dbi_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 01fbd00411fc9..e62f4d16b2c6b 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -621,6 +621,15 @@ static void power_off(struct repaper_epd *epd) gpiod_set_value_cansleep(epd->discharge, 0); } +static enum drm_mode_status repaper_pipe_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode) +{ + struct drm_crtc *crtc = &pipe->crtc; + struct repaper_epd *epd = drm_to_epd(crtc->dev); + + return drm_crtc_helper_mode_valid_fixed(crtc, mode, epd->mode); +} + static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) @@ -831,6 +840,7 @@ static void repaper_pipe_update(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = { + .mode_valid = repaper_pipe_mode_valid, .enable = repaper_pipe_enable, .disable = repaper_pipe_disable, .update = repaper_pipe_update, diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index c79576844ec0c..5bed4d564104b 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -570,15 +570,7 @@ static enum drm_mode_status simpledrm_crtc_helper_mode_valid(struct drm_crtc *cr { struct simpledrm_device *sdev = simpledrm_device_of_dev(crtc->dev); - if (mode->hdisplay != sdev->mode.hdisplay && - mode->vdisplay != sdev->mode.vdisplay) - return MODE_ONE_SIZE; - else if (mode->hdisplay != sdev->mode.hdisplay) - return MODE_ONE_WIDTH; - else if (mode->vdisplay != sdev->mode.vdisplay) - return MODE_ONE_HEIGHT; - - return MODE_OK; + return drm_crtc_helper_mode_valid_fixed(crtc, mode, &sdev->mode); } static int simpledrm_crtc_helper_atomic_check(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index d2042a0f02dd3..c36ba08acda18 100644 --- a/drivers/gpu/drm/tiny/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -133,6 +133,7 @@ static void st7735r_pipe_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs st7735r_pipe_funcs = { + .mode_valid = mipi_dbi_pipe_mode_valid, .enable = st7735r_pipe_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h index dad2f187b64b1..14eaecb1825c1 100644 --- a/include/drm/drm_mipi_dbi.h +++ b/include/drm/drm_mipi_dbi.h @@ -155,6 +155,8 @@ int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev, int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, const struct drm_simple_display_pipe_funcs *funcs, const struct drm_display_mode *mode, unsigned int rotation); +enum drm_mode_status mipi_dbi_pipe_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode); void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_plane_state *old_state); void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev, diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h index d261838a7790e..5880daa146240 100644 --- a/include/drm/drm_probe_helper.h +++ b/include/drm/drm_probe_helper.h @@ -3,11 +3,11 @@ #ifndef __DRM_PROBE_HELPER_H__ #define __DRM_PROBE_HELPER_H__ -#include +#include struct drm_connector; +struct drm_crtc; struct drm_device; -struct drm_display_mode; struct drm_modeset_acquire_ctx; int drm_helper_probe_single_connector_modes(struct drm_connector @@ -27,6 +27,10 @@ void drm_kms_helper_poll_disable(struct drm_device *dev); void drm_kms_helper_poll_enable(struct drm_device *dev); bool drm_kms_helper_is_poll_worker(void); +enum drm_mode_status drm_crtc_helper_mode_valid_fixed(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *fixed_mode); + int drm_connector_helper_get_modes_from_ddc(struct drm_connector *connector); int drm_connector_helper_get_modes_fixed(struct drm_connector *connector, const struct drm_display_mode *fixed_mode); From 385d1bba890f9b94322ca7fdfa778311f1ea0813 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 5 Sep 2022 16:16:47 +0200 Subject: [PATCH 057/119] drm/modes: Add initializer macro DRM_MODE_INIT() The macro DRM_MODE_INIT() initializes an instance of struct drm_display_mode with typical parameters. Convert simpledrm and also update the macro DRM_SIMPLE_MODE(). v3: * fix DRM_MODE_INIT() docs (kernel test robot) Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220905141648.22013-4-tzimmermann@suse.de --- drivers/gpu/drm/tiny/simpledrm.c | 23 ++++++++------------- include/drm/drm_modes.h | 35 +++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 5bed4d564104b..404290760c601 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -30,16 +30,6 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 -/* - * Assume a monitor resolution of 96 dpi to - * get a somewhat reasonable screen size. - */ -#define RES_MM(d) \ - (((d) * 254ul) / (96ul * 10ul)) - -#define SIMPLEDRM_MODE(hd, vd) \ - DRM_SIMPLE_MODE(hd, vd, RES_MM(hd), RES_MM(vd)) - /* * Helpers for simplefb */ @@ -641,10 +631,15 @@ static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = { static struct drm_display_mode simpledrm_mode(unsigned int width, unsigned int height) { - struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) }; - - mode.clock = mode.hdisplay * mode.vdisplay * 60 / 1000 /* kHz */; - drm_mode_set_name(&mode); + /* + * Assume a monitor resolution of 96 dpi to + * get a somewhat reasonable screen size. + */ + const struct drm_display_mode mode = { + DRM_MODE_INIT(60, width, height, + DRM_MODE_RES_MM(width, 96ul), + DRM_MODE_RES_MM(height, 96ul)) + }; return mode; } diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index a80ae9639e969..b0c680e6f6707 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -138,6 +138,35 @@ enum drm_mode_status { .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \ .vscan = (vs), .flags = (f) +/** + * DRM_MODE_RES_MM - Calculates the display size from resolution and DPI + * @res: The resolution in pixel + * @dpi: The number of dots per inch + */ +#define DRM_MODE_RES_MM(res, dpi) \ + (((res) * 254ul) / ((dpi) * 10ul)) + +#define __DRM_MODE_INIT(pix, hd, vd, hd_mm, vd_mm) \ + .type = DRM_MODE_TYPE_DRIVER, .clock = (pix), \ + .hdisplay = (hd), .hsync_start = (hd), .hsync_end = (hd), \ + .htotal = (hd), .vdisplay = (vd), .vsync_start = (vd), \ + .vsync_end = (vd), .vtotal = (vd), .width_mm = (hd_mm), \ + .height_mm = (vd_mm) + +/** + * DRM_MODE_INIT - Initialize display mode + * @hz: Vertical refresh rate in Hertz + * @hd: Horizontal resolution, width + * @vd: Vertical resolution, height + * @hd_mm: Display width in millimeters + * @vd_mm: Display height in millimeters + * + * This macro initializes a &drm_display_mode that contains information about + * refresh rate, resolution and physical size. + */ +#define DRM_MODE_INIT(hz, hd, vd, hd_mm, vd_mm) \ + __DRM_MODE_INIT((hd) * (vd) * (hz) / 1000 /* kHz */, hd, vd, hd_mm, vd_mm) + /** * DRM_SIMPLE_MODE - Simple display mode * @hd: Horizontal resolution, width @@ -149,11 +178,7 @@ enum drm_mode_status { * resolution and physical size. */ #define DRM_SIMPLE_MODE(hd, vd, hd_mm, vd_mm) \ - .type = DRM_MODE_TYPE_DRIVER, .clock = 1 /* pass validation */, \ - .hdisplay = (hd), .hsync_start = (hd), .hsync_end = (hd), \ - .htotal = (hd), .vdisplay = (vd), .vsync_start = (vd), \ - .vsync_end = (vd), .vtotal = (vd), .width_mm = (hd_mm), \ - .height_mm = (vd_mm) + __DRM_MODE_INIT(1 /* pass validation */, hd, vd, hd_mm, vd_mm) #define CRTC_INTERLACE_HALVE_V (1 << 0) /* halve V values for interlacing */ #define CRTC_STEREO_DOUBLE (1 << 1) /* adjust timings for stereo modes */ From 4a85b0b51e211fba03c081e1e47f8871e4b3088f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 5 Sep 2022 16:16:48 +0200 Subject: [PATCH 058/119] drm/format-helper: Add drm_fb_build_fourcc_list() helper Add drm_fb_build_fourcc_list() function that builds a list of supported formats from native and emulated ones. Helpful for all drivers that do format conversion as part of their plane updates. Update current caller. v3: * improve warnings on ignored formats (Sam) v2: * use u32 instead of uint32_t (Sam) * print a warning if output array is too small (Sam) * comment fixes (Sam) Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220905141648.22013-5-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 108 ++++++++++++++++++++++++++++ drivers/gpu/drm/tiny/simpledrm.c | 47 ++---------- include/drm/drm_format_helper.h | 11 ++- 3 files changed, 123 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 56642816fdff0..4afc4ac27342f 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -793,3 +793,111 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc kfree(src32); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); + +static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc) +{ + const uint32_t *fourccs_end = fourccs + nfourccs; + + while (fourccs < fourccs_end) { + if (*fourccs == fourcc) + return true; + ++fourccs; + } + return false; +} + +/** + * drm_fb_build_fourcc_list - Filters a list of supported color formats against + * the device's native formats + * @dev: DRM device + * @native_fourccs: 4CC codes of natively supported color formats + * @native_nfourccs: The number of entries in @native_fourccs + * @driver_fourccs: 4CC codes of all driver-supported color formats + * @driver_nfourccs: The number of entries in @driver_fourccs + * @fourccs_out: Returns 4CC codes of supported color formats + * @nfourccs_out: The number of available entries in @fourccs_out + * + * This function create a list of supported color format from natively + * supported formats and the emulated formats. + * At a minimum, most userspace programs expect at least support for + * XRGB8888 on the primary plane. Devices that have to emulate the + * format, and possibly others, can use drm_fb_build_fourcc_list() to + * create a list of supported color formats. The returned list can + * be handed over to drm_universal_plane_init() et al. Native formats + * will go before emulated formats. Other heuristics might be applied + * to optimize the order. Formats near the beginning of the list are + * usually preferred over formats near the end of the list. + * + * Returns: + * The number of color-formats 4CC codes returned in @fourccs_out. + */ +size_t drm_fb_build_fourcc_list(struct drm_device *dev, + const u32 *native_fourccs, size_t native_nfourccs, + const u32 *driver_fourccs, size_t driver_nfourccs, + u32 *fourccs_out, size_t nfourccs_out) +{ + u32 *fourccs = fourccs_out; + const u32 *fourccs_end = fourccs_out + nfourccs_out; + bool found_native = false; + size_t i; + + /* + * The device's native formats go first. + */ + + for (i = 0; i < native_nfourccs; ++i) { + u32 fourcc = native_fourccs[i]; + + if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { + continue; /* skip duplicate entries */ + } else if (fourccs == fourccs_end) { + drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc); + continue; /* end of available output buffer */ + } + + drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc); + + if (!found_native) + found_native = is_listed_fourcc(driver_fourccs, driver_nfourccs, fourcc); + *fourccs = fourcc; + ++fourccs; + } + + /* + * The plane's atomic_update helper converts the framebuffer's color format + * to a native format when copying to device memory. + * + * If there is not a single format supported by both, device and + * driver, the native formats are likely not supported by the conversion + * helpers. Therefore *only* support the native formats and add a + * conversion helper ASAP. + */ + if (!found_native) { + drm_warn(dev, "Format conversion helpers required to add extra formats.\n"); + goto out; + } + + /* + * The extra formats, emulated by the driver, go second. + */ + + for (i = 0; (i < driver_nfourccs) && (fourccs < fourccs_end); ++i) { + u32 fourcc = driver_fourccs[i]; + + if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { + continue; /* skip duplicate and native entries */ + } else if (fourccs == fourccs_end) { + drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc); + continue; /* end of available output buffer */ + } + + drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc); + + *fourccs = fourcc; + ++fourccs; + } + +out: + return fourccs - fourccs_out; +} +EXPORT_SYMBOL(drm_fb_build_fourcc_list); diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 404290760c601..777ccd2508717 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -644,45 +644,6 @@ static struct drm_display_mode simpledrm_mode(unsigned int width, return mode; } -static const uint32_t *simpledrm_device_formats(struct simpledrm_device *sdev, - size_t *nformats_out) -{ - struct drm_device *dev = &sdev->dev; - size_t i; - - if (sdev->nformats) - goto out; /* don't rebuild list on recurring calls */ - - /* native format goes first */ - sdev->formats[0] = sdev->format->format; - sdev->nformats = 1; - - /* default formats go second */ - for (i = 0; i < ARRAY_SIZE(simpledrm_primary_plane_formats); ++i) { - if (simpledrm_primary_plane_formats[i] == sdev->format->format) - continue; /* native format already went first */ - sdev->formats[sdev->nformats] = simpledrm_primary_plane_formats[i]; - sdev->nformats++; - } - - /* - * TODO: The simpledrm driver converts framebuffers to the native - * format when copying them to device memory. If there are more - * formats listed than supported by the driver, the native format - * is not supported by the conversion helpers. Therefore *only* - * support the native format and add a conversion helper ASAP. - */ - if (drm_WARN_ONCE(dev, i != sdev->nformats, - "format conversion helpers required for %p4cc", - &sdev->format->format)) { - sdev->nformats = 1; - } - -out: - *nformats_out = sdev->nformats; - return sdev->formats; -} - static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev) { @@ -699,7 +660,6 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, struct drm_encoder *encoder; struct drm_connector *connector; unsigned long max_width, max_height; - const uint32_t *formats; size_t nformats; int ret; @@ -811,11 +771,14 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, /* Primary plane */ - formats = simpledrm_device_formats(sdev, &nformats); + nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, + simpledrm_primary_plane_formats, + ARRAY_SIZE(simpledrm_primary_plane_formats), + sdev->formats, ARRAY_SIZE(sdev->formats)); primary_plane = &sdev->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &simpledrm_primary_plane_funcs, - formats, nformats, + sdev->formats, nformats, simpledrm_primary_plane_format_modifiers, DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index caa1811943357..eb5c98cf82b8f 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -6,11 +6,15 @@ #ifndef __LINUX_DRM_FORMAT_HELPER_H #define __LINUX_DRM_FORMAT_HELPER_H -struct iosys_map; +#include + +struct drm_device; struct drm_format_info; struct drm_framebuffer; struct drm_rect; +struct iosys_map; + unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info *format, const struct drm_rect *clip); @@ -44,4 +48,9 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); +size_t drm_fb_build_fourcc_list(struct drm_device *dev, + const u32 *native_fourccs, size_t native_nfourccs, + const u32 *extra_fourccs, size_t extra_nfourccs, + u32 *fourccs_out, size_t nfourccs_out); + #endif /* __LINUX_DRM_FORMAT_HELPER_H */ From f2912237eb922bf2d4ebf13f3f5f1b25070f1e52 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 5 Sep 2022 18:22:41 +0200 Subject: [PATCH 059/119] drm/aperture: Fix some kerneldoc comments Reword some kerneldoc comments for the DRM aperture handling code. Signed-off-by: Thierry Reding Signed-off-by: Thomas Zimmermann Acked-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220905162241.391226-1-thierry.reding@gmail.com --- drivers/gpu/drm/drm_aperture.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c index fdb7d5c17ba15..3b8fdeeafd53a 100644 --- a/drivers/gpu/drm/drm_aperture.c +++ b/drivers/gpu/drm/drm_aperture.c @@ -74,7 +74,7 @@ * given framebuffer memory. Ownership of the framebuffer memory is achieved * by calling devm_aperture_acquire_from_firmware(). On success, the driver * is the owner of the framebuffer range. The function fails if the - * framebuffer is already by another driver. See below for an example. + * framebuffer is already owned by another driver. See below for an example. * * .. code-block:: c * @@ -112,7 +112,7 @@ * * The generic driver is now subject to forced removal by other drivers. This * only works for platform drivers that support hot unplug. - * When a driver calls drm_aperture_remove_conflicting_framebuffers() et al + * When a driver calls drm_aperture_remove_conflicting_framebuffers() et al. * for the registered framebuffer range, the aperture helpers call * platform_device_unregister() and the generic driver unloads itself. It * may not access the device's registers, framebuffer memory, ROM, etc @@ -164,7 +164,7 @@ EXPORT_SYMBOL(devm_aperture_acquire_from_firmware); * @primary: also kick vga16fb if present * @req_driver: requesting DRM driver * - * This function removes graphics device drivers which use memory range described by + * This function removes graphics device drivers which use the memory range described by * @base and @size. * * Returns: @@ -182,8 +182,8 @@ EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers); * @pdev: PCI device * @req_driver: requesting DRM driver * - * This function removes graphics device drivers using memory range configured - * for any of @pdev's memory bars. The function assumes that PCI device with + * This function removes graphics device drivers using the memory range configured + * for any of @pdev's memory bars. The function assumes that a PCI device with * shadowed ROM drives a primary display and so kicks out vga16fb. * * Returns: From e3d8d54cd6c5b29f3437f1f00b393267b84d650e Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Sat, 10 Sep 2022 18:48:16 -0400 Subject: [PATCH 060/119] drm/bridge: it6505: use drm_debug_enabled() in it6505_debug_print() As made mention of in commit 9f0ac028410f ("drm/print: rename drm_debug to __drm_debug to discourage use"), we shouldn't explicitly refer to __drm_debug in this context. So, use drm_debug_enabled() instead. Fixes: b5c84a9edcd4 ("drm/bridge: add it6505 driver") Signed-off-by: Hamza Mahfooz Reviewed-by: Jani Nikula Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220910224816.15058-1-someguy@effective-light.com --- drivers/gpu/drm/bridge/ite-it6505.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 2bb957cffd942..2767b70fa2cb8 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -563,7 +563,7 @@ static void it6505_debug_print(struct it6505 *it6505, unsigned int reg, struct device *dev = &it6505->client->dev; int val; - if (likely(!(__drm_debug & DRM_UT_DRIVER))) + if (!drm_debug_enabled(DRM_UT_DRIVER)) return; val = it6505_read(it6505, reg); From e798ba3374a139ee83253245656d5aa201552534 Mon Sep 17 00:00:00 2001 From: Robert Foss Date: Mon, 12 Sep 2022 13:38:57 +0200 Subject: [PATCH 061/119] Revert "dt-bindings: Add byteswap order to chrontel ch7033" As reported by Laurent in response to this commit[1], this functionality should not be implemented using the devicetree, because of this let's revert this series for now. This reverts commit a4be71430c76eca43679e8485085c230afa84460. [1] https://lore.kernel.org/all/20220902153906.31000-2-macroalpha82@gmail.com/ Signed-off-by: Robert Foss Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20220912113856.817188-2-robert.foss@linaro.org --- .../bindings/display/bridge/chrontel,ch7033.yaml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/chrontel,ch7033.yaml b/Documentation/devicetree/bindings/display/bridge/chrontel,ch7033.yaml index 984b90893583b..bb6289c7d375e 100644 --- a/Documentation/devicetree/bindings/display/bridge/chrontel,ch7033.yaml +++ b/Documentation/devicetree/bindings/display/bridge/chrontel,ch7033.yaml @@ -14,19 +14,6 @@ properties: compatible: const: chrontel,ch7033 - chrontel,byteswap: - $ref: /schemas/types.yaml#/definitions/uint8 - enum: - - 0 # BYTE_SWAP_RGB - - 1 # BYTE_SWAP_RBG - - 2 # BYTE_SWAP_GRB - - 3 # BYTE_SWAP_GBR - - 4 # BYTE_SWAP_BRG - - 5 # BYTE_SWAP_BGR - description: | - Set the byteswap value of the bridge. This is optional and if not - set value of BYTE_SWAP_BGR is used. - reg: maxItems: 1 description: I2C address of the device From 8c9c40ec83445b188fb6b59e119bf5c2de81b02d Mon Sep 17 00:00:00 2001 From: Robert Foss Date: Mon, 12 Sep 2022 13:38:59 +0200 Subject: [PATCH 062/119] Revert "drm/bridge: ti-sn65dsi86: Implement bridge connector operations for DP" As reported by Laurent in response to this commit[1], this functionality should not be implemented using the devicetree, because of this let's revert this series for now. This reverts commit c312b0df3b13e4c533743bb2c37fd1bc237368e5. [1] https://lore.kernel.org/all/20220902153906.31000-2-macroalpha82@gmail.com/ Signed-off-by: Robert Foss Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20220912113856.817188-3-robert.foss@linaro.org --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 28 --------------------------- 1 file changed, 28 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 3c3561942eb66..6e053e2af2299 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -69,7 +68,6 @@ #define BPP_18_RGB BIT(0) #define SN_HPD_DISABLE_REG 0x5C #define HPD_DISABLE BIT(0) -#define HPD_DEBOUNCED_STATE BIT(4) #define SN_GPIO_IO_REG 0x5E #define SN_GPIO_INPUT_SHIFT 4 #define SN_GPIO_OUTPUT_SHIFT 0 @@ -1160,33 +1158,10 @@ static void ti_sn_bridge_atomic_post_disable(struct drm_bridge *bridge, pm_runtime_put_sync(pdata->dev); } -static enum drm_connector_status ti_sn_bridge_detect(struct drm_bridge *bridge) -{ - struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); - int val = 0; - - pm_runtime_get_sync(pdata->dev); - regmap_read(pdata->regmap, SN_HPD_DISABLE_REG, &val); - pm_runtime_put_autosuspend(pdata->dev); - - return val & HPD_DEBOUNCED_STATE ? connector_status_connected - : connector_status_disconnected; -} - -static struct edid *ti_sn_bridge_get_edid(struct drm_bridge *bridge, - struct drm_connector *connector) -{ - struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); - - return drm_get_edid(connector, &pdata->aux.ddc); -} - static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .attach = ti_sn_bridge_attach, .detach = ti_sn_bridge_detach, .mode_valid = ti_sn_bridge_mode_valid, - .get_edid = ti_sn_bridge_get_edid, - .detect = ti_sn_bridge_detect, .atomic_pre_enable = ti_sn_bridge_atomic_pre_enable, .atomic_enable = ti_sn_bridge_atomic_enable, .atomic_disable = ti_sn_bridge_atomic_disable, @@ -1282,9 +1257,6 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP; - if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) - pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT; - drm_bridge_add(&pdata->bridge); ret = ti_sn_attach_host(pdata); From dd9b18e76f0434e47ee8f5243727c79a66a85243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Tue, 23 Aug 2022 14:29:17 +0300 Subject: [PATCH 063/119] drm: Use original src rect while initializing damage iterator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_plane_state->src might be modified by the driver. This is done e.g. in i915 driver when there is bigger framebuffer than the plane and there is some offset within framebuffer. I915 driver calculates separate offset and adjusts src rect coords to be relative to this offset. Damage clips are still relative to original src coords provided by user-space. This patch ensures original coordinates provided by user-space are used when initiliazing damage iterator. Signed-off-by: Jouni Högander Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220823112920.352563-2-jouni.hogander@intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/drm_damage_helper.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c index 937b699ac2a8f..d8b2955e88fd0 100644 --- a/drivers/gpu/drm/drm_damage_helper.c +++ b/drivers/gpu/drm/drm_damage_helper.c @@ -224,6 +224,7 @@ drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter, const struct drm_plane_state *old_state, const struct drm_plane_state *state) { + struct drm_rect src; memset(iter, 0, sizeof(*iter)); if (!state || !state->crtc || !state->fb || !state->visible) @@ -233,10 +234,12 @@ drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter, iter->num_clips = drm_plane_get_damage_clips_count(state); /* Round down for x1/y1 and round up for x2/y2 to catch all pixels */ - iter->plane_src.x1 = state->src.x1 >> 16; - iter->plane_src.y1 = state->src.y1 >> 16; - iter->plane_src.x2 = (state->src.x2 >> 16) + !!(state->src.x2 & 0xFFFF); - iter->plane_src.y2 = (state->src.y2 >> 16) + !!(state->src.y2 & 0xFFFF); + src = drm_plane_state_src(state); + + iter->plane_src.x1 = src.x1 >> 16; + iter->plane_src.y1 = src.y1 >> 16; + iter->plane_src.x2 = (src.x2 >> 16) + !!(src.x2 & 0xFFFF); + iter->plane_src.y2 = (src.y2 >> 16) + !!(src.y2 & 0xFFFF); if (!iter->clips || !drm_rect_equals(&state->src, &old_state->src)) { iter->clips = NULL; From b78e5d830f0db8e6d998cdc5a2b7b807cf463f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Tue, 23 Aug 2022 14:29:20 +0300 Subject: [PATCH 064/119] drm/tests: Set also mock plane src_x, src_y, src_w and src_h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to set also src_x, src_y, src_w and src_h for the mock plane. After fix for drm_atomic_helper_damage_iter_init we are using these when iterating damage_clips. Signed-off-by: Jouni Högander Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220823112920.352563-5-jouni.hogander@intel.com Reviewed-by: Mika Kahola Tested-by: Maíra Canal --- drivers/gpu/drm/tests/drm_damage_helper_test.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c index bf250bd08d7e1..c608ae06f0e31 100644 --- a/drivers/gpu/drm/tests/drm_damage_helper_test.c +++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c @@ -59,6 +59,11 @@ static int drm_damage_helper_init(struct kunit *test) static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2, int y2) { + state->src_x = x1; + state->src_y = y1; + state->src_w = x2 - x1; + state->src_h = y2 - y1; + state->src.x1 = x1; state->src.y1 = y1; state->src.x2 = x2; From 58009c256b1134a5257407f60fd37396dc99cbca Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 29 Aug 2022 15:47:24 +0200 Subject: [PATCH 065/119] drm/vc4: hdmi: Constify drm_display_mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't modify the drm_display_mode pointer we have in the driver in most places, so let's make them const. Reviewed-by: Ville Syrjälä Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220829134731.213478-2-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 16 ++++++++-------- drivers/gpu/drm/vc4/vc4_hdmi.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 4d3ff51ad2a85..773176d810a4e 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -335,7 +335,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) if (vc4_hdmi->disable_4kp60) { struct drm_device *drm = connector->dev; - struct drm_display_mode *mode; + const struct drm_display_mode *mode; list_for_each_entry(mode, &connector->probed_modes, head) { if (vc4_hdmi_mode_needs_scrambling(mode, 8, VC4_HDMI_OUTPUT_RGB)) { @@ -709,7 +709,7 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) } static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_display_info *display = &vc4_hdmi->connector.display_info; @@ -732,7 +732,7 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_device *drm = vc4_hdmi->connector.dev; - struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; + const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; unsigned long flags; int idx; @@ -1077,7 +1077,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *drm = vc4_hdmi->connector.dev; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; @@ -1141,7 +1141,7 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *drm = vc4_hdmi->connector.dev; const struct vc4_hdmi_connector_state *vc4_state = @@ -1303,7 +1303,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, drm_atomic_get_new_connector_state(state, connector); struct vc4_hdmi_connector_state *vc4_conn_state = conn_state_to_vc4_hdmi_conn_state(conn_state); - struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; + const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; unsigned long tmds_char_rate = vc4_conn_state->tmds_char_rate; unsigned long bvb_rate, hsm_rate; unsigned long flags; @@ -1416,7 +1416,7 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_device *drm = vc4_hdmi->connector.dev; struct drm_connector *connector = &vc4_hdmi->connector; - struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; + const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, connector); unsigned long flags; @@ -1445,7 +1445,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_device *drm = vc4_hdmi->connector.dev; - struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; + const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; struct drm_display_info *display = &vc4_hdmi->connector.display_info; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 99b0bc1297be8..79495ef79f09b 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -72,7 +72,7 @@ struct vc4_hdmi_variant { /* Callback to configure the video timings in the HDMI block */ void (*set_timings)(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); /* Callback to initialize the PHY according to the connector state */ void (*phy_init)(struct vc4_hdmi *vc4_hdmi, From d098a31fe0f867cb7c00a4206740e768b00d8550 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 29 Aug 2022 15:47:25 +0200 Subject: [PATCH 066/119] drm/vc4: hdmi: Remove unused argument in vc4_hdmi_supports_scrambling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even though vc4_hdmi_supports_scrambling takes a mode as an argument, it never uses it. Let's remove it. Reviewed-by: Ville Syrjälä Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220829134731.213478-3-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 773176d810a4e..d330598659944 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -708,8 +708,7 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) vc4_hdmi_set_hdr_infoframe(encoder); } -static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder, - const struct drm_display_mode *mode) +static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_display_info *display = &vc4_hdmi->connector.display_info; @@ -738,7 +737,7 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) lockdep_assert_held(&vc4_hdmi->mutex); - if (!vc4_hdmi_supports_scrambling(encoder, mode)) + if (!vc4_hdmi_supports_scrambling(encoder)) return; if (!vc4_hdmi_mode_needs_scrambling(mode, From da94e9c64c19a7fb2caa896628cb501a06cc3e96 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 29 Aug 2022 15:47:26 +0200 Subject: [PATCH 067/119] drm/vc4: hdmi: Remove mutex in detect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We recently introduced a new mutex to protect concurrent execution of ALSA and KMS hooks, and the concurrent access to some of vc4_hdmi fields. However, using it in the detect hook was creating a reentrency issue with CEC code. Indeed, calling cec_s_phys_addr_from_edid from detect might call the CEC adap_enable hook with the lock held, eventually resulting in a deadlock. Since we didn't really need to protect anything at the moment in the CEC code, the decision was made to ignore the mutex in those CEC hooks, working around the issue. However, we can have the same thing happening if we end up triggering a mode set from the detect callback, for example using drm_atomic_helper_connector_hdmi_reset_link(). Since we don't really need to protect anything in detect either, let's just drop the lock in detect, and add it again in CEC. Reviewed-by: Ville Syrjälä Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220829134731.213478-4-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 88 +++++++++++++--------------------- drivers/gpu/drm/vc4/vc4_hdmi.h | 10 +--- 2 files changed, 34 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index d330598659944..308f7440eb6af 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -279,7 +279,16 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); bool connected = false; - mutex_lock(&vc4_hdmi->mutex); + /* + * NOTE: This function should really take vc4_hdmi->mutex, but + * doing so results in reentrancy issues since + * cec_s_phys_addr_from_edid might call .adap_enable, which + * leads to that funtion being called with our mutex held. + * + * Concurrency isn't an issue at the moment since we don't share + * any state with any of the other frameworks so we can ignore + * the lock for now. + */ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); @@ -304,13 +313,11 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base); pm_runtime_put(&vc4_hdmi->pdev->dev); - mutex_unlock(&vc4_hdmi->mutex); return connector_status_connected; } cec_phys_addr_invalidate(vc4_hdmi->cec_adap); pm_runtime_put(&vc4_hdmi->pdev->dev); - mutex_unlock(&vc4_hdmi->mutex); return connector_status_disconnected; } @@ -320,14 +327,21 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) int ret = 0; struct edid *edid; - mutex_lock(&vc4_hdmi->mutex); + /* + * NOTE: This function should really take vc4_hdmi->mutex, but + * doing so results in reentrancy issues since + * cec_s_phys_addr_from_edid might call .adap_enable, which + * leads to that funtion being called with our mutex held. + * + * Concurrency isn't an issue at the moment since we don't share + * any state with any of the other frameworks so we can ignore + * the lock for now. + */ edid = drm_get_edid(connector, vc4_hdmi->ddc); cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); - if (!edid) { - ret = -ENODEV; - goto out; - } + if (!edid) + return -ENODEV; drm_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); @@ -345,9 +359,6 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) } } -out: - mutex_unlock(&vc4_hdmi->mutex); - return ret; } @@ -2666,17 +2677,6 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) int ret; int idx; - /* - * NOTE: This function should really take vc4_hdmi->mutex, but doing so - * results in a reentrancy since cec_s_phys_addr_from_edid() called in - * .detect or .get_modes might call .adap_enable, which leads to this - * function being called with that mutex held. - * - * Concurrency is not an issue for the moment since we don't share any - * state with KMS, so we can ignore the lock for now, but we need to - * keep it in mind if we were to change that assumption. - */ - if (!drm_dev_enter(drm, &idx)) /* * We can't return an error code, because the CEC @@ -2691,6 +2691,8 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) return ret; } + mutex_lock(&vc4_hdmi->mutex); + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); val = HDMI_READ(HDMI_CEC_CNTRL_5); @@ -2725,6 +2727,7 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + mutex_unlock(&vc4_hdmi->mutex); drm_dev_exit(idx); return 0; @@ -2745,16 +2748,7 @@ static int vc4_hdmi_cec_disable(struct cec_adapter *adap) */ return 0; - /* - * NOTE: This function should really take vc4_hdmi->mutex, but doing so - * results in a reentrancy since cec_s_phys_addr_from_edid() called in - * .detect or .get_modes might call .adap_enable, which leads to this - * function being called with that mutex held. - * - * Concurrency is not an issue for the moment since we don't share any - * state with KMS, so we can ignore the lock for now, but we need to - * keep it in mind if we were to change that assumption. - */ + mutex_lock(&vc4_hdmi->mutex); spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -2766,6 +2760,8 @@ static int vc4_hdmi_cec_disable(struct cec_adapter *adap) spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + mutex_unlock(&vc4_hdmi->mutex); + pm_runtime_put(&vc4_hdmi->pdev->dev); drm_dev_exit(idx); @@ -2788,17 +2784,6 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) unsigned long flags; int idx; - /* - * NOTE: This function should really take vc4_hdmi->mutex, but doing so - * results in a reentrancy since cec_s_phys_addr_from_edid() called in - * .detect or .get_modes might call .adap_enable, which leads to this - * function being called with that mutex held. - * - * Concurrency is not an issue for the moment since we don't share any - * state with KMS, so we can ignore the lock for now, but we need to - * keep it in mind if we were to change that assumption. - */ - if (!drm_dev_enter(drm, &idx)) /* * We can't return an error code, because the CEC @@ -2807,11 +2792,13 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) */ return 0; + mutex_lock(&vc4_hdmi->mutex); spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_CEC_CNTRL_1, (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) | (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + mutex_unlock(&vc4_hdmi->mutex); drm_dev_exit(idx); @@ -2828,17 +2815,6 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, unsigned int i; int idx; - /* - * NOTE: This function should really take vc4_hdmi->mutex, but doing so - * results in a reentrancy since cec_s_phys_addr_from_edid() called in - * .detect or .get_modes might call .adap_enable, which leads to this - * function being called with that mutex held. - * - * Concurrency is not an issue for the moment since we don't share any - * state with KMS, so we can ignore the lock for now, but we need to - * keep it in mind if we were to change that assumption. - */ - if (!drm_dev_enter(dev, &idx)) return -ENODEV; @@ -2848,6 +2824,8 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, return -ENOMEM; } + mutex_lock(&vc4_hdmi->mutex); + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); for (i = 0; i < msg->len; i += 4) @@ -2867,7 +2845,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, HDMI_WRITE(HDMI_CEC_CNTRL_1, val); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - + mutex_unlock(&vc4_hdmi->mutex); drm_dev_exit(idx); return 0; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 79495ef79f09b..db823efb25639 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -195,15 +195,7 @@ struct vc4_hdmi { /** * @mutex: Mutex protecting the driver access across multiple - * frameworks (KMS, ALSA). - * - * NOTE: While supported, CEC has been left out since - * cec_s_phys_addr_from_edid() might call .adap_enable and lead to a - * reentrancy issue between .get_modes (or .detect) and .adap_enable. - * Since we don't share any state between the CEC hooks and KMS', it's - * not a big deal. The only trouble might come from updating the CEC - * clock divider which might be affected by a modeset, but CEC should - * be resilient to that. + * frameworks (KMS, ALSA, CEC). */ struct mutex mutex; From c0895f80272cd4100a26129f4fb91a85bf6663a1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 29 Aug 2022 15:47:27 +0200 Subject: [PATCH 068/119] drm/vc4: hdmi: Simplify the hotplug handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our detect callback has a bunch of operations to perform depending on the current and last status of the connector, such a setting the CEC physical address or enabling the scrambling again. This is currently dealt with a bunch of if / else statetements that make it fairly difficult to read and extend. Let's move all that logic to a function of its own. Reviewed-by: Ville Syrjälä Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220829134731.213478-5-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 63 ++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 308f7440eb6af..93df3a8e6ed90 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -273,17 +273,50 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder); +static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, + enum drm_connector_status status) +{ + struct drm_connector *connector = &vc4_hdmi->connector; + struct edid *edid; + + /* + * NOTE: This function should really be called with + * vc4_hdmi->mutex held, but doing so results in reentrancy + * issues since cec_s_phys_addr_from_edid might call + * .adap_enable, which leads to that funtion being called with + * our mutex held. + * + * Concurrency isn't an issue at the moment since we don't share + * any state with any of the other frameworks so we can ignore + * the lock for now. + */ + + if (status == connector_status_disconnected) { + cec_phys_addr_invalidate(vc4_hdmi->cec_adap); + return; + } + + edid = drm_get_edid(connector, vc4_hdmi->ddc); + if (!edid) + return; + + cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); + kfree(edid); + + vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base.base); +} + static enum drm_connector_status vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) { struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); - bool connected = false; + enum drm_connector_status status = connector_status_disconnected; /* * NOTE: This function should really take vc4_hdmi->mutex, but * doing so results in reentrancy issues since - * cec_s_phys_addr_from_edid might call .adap_enable, which - * leads to that funtion being called with our mutex held. + * vc4_hdmi_handle_hotplug() can call into other functions that + * would take the mutex while it's held here. * * Concurrency isn't an issue at the moment since we don't share * any state with any of the other frameworks so we can ignore @@ -294,31 +327,17 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) if (vc4_hdmi->hpd_gpio) { if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) - connected = true; + status = connector_status_connected; } else { if (vc4_hdmi->variant->hp_detect && vc4_hdmi->variant->hp_detect(vc4_hdmi)) - connected = true; - } - - if (connected) { - if (connector->status != connector_status_connected) { - struct edid *edid = drm_get_edid(connector, vc4_hdmi->ddc); - - if (edid) { - cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); - kfree(edid); - } - } - - vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base); - pm_runtime_put(&vc4_hdmi->pdev->dev); - return connector_status_connected; + status = connector_status_connected; } - cec_phys_addr_invalidate(vc4_hdmi->cec_adap); + vc4_hdmi_handle_hotplug(vc4_hdmi, status); pm_runtime_put(&vc4_hdmi->pdev->dev); - return connector_status_disconnected; + + return status; } static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) From 165ba1aad164b7d5d5bc327fa511f6ef693b207b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 29 Aug 2022 15:47:28 +0200 Subject: [PATCH 069/119] drm/vc4: hdmi: Switch to detect_ctx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll need the locking context in future patch, so let's convert .detect to .detect_ctx. Reviewed-by: Ville Syrjälä Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220829134731.213478-6-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 93df3a8e6ed90..2f0d3438b0959 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -306,8 +306,9 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base.base); } -static enum drm_connector_status -vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) +static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force) { struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); enum drm_connector_status status = connector_status_disconnected; @@ -449,7 +450,6 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) } static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { - .detect = vc4_hdmi_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .reset = vc4_hdmi_connector_reset, .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state, @@ -457,6 +457,7 @@ static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { }; static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = { + .detect_ctx = vc4_hdmi_connector_detect_ctx, .get_modes = vc4_hdmi_connector_get_modes, .atomic_check = vc4_hdmi_connector_atomic_check, }; From d0133e7da26c5548f7e376149a6a225b4274dcb1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 29 Aug 2022 15:47:29 +0200 Subject: [PATCH 070/119] drm/vc4: hdmi: Move vc4_hdmi_supports_scrambling() around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll need it earlier in the driver, so let's move it next to the other scrambling-related helpers. Reviewed-by: Ville Syrjälä Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220829134731.213478-7-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 2f0d3438b0959..cc9c60d4facff 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -124,6 +124,23 @@ static unsigned long long vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, unsigned int bpc, enum vc4_hdmi_output_format fmt); +static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder) +{ + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_display_info *display = &vc4_hdmi->connector.display_info; + + lockdep_assert_held(&vc4_hdmi->mutex); + + if (!display->is_hdmi) + return false; + + if (!display->hdmi.scdc.supported || + !display->hdmi.scdc.scrambling.supported) + return false; + + return true; +} + static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode, unsigned int bpc, enum vc4_hdmi_output_format fmt) @@ -739,23 +756,6 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) vc4_hdmi_set_hdr_infoframe(encoder); } -static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder) -{ - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_display_info *display = &vc4_hdmi->connector.display_info; - - lockdep_assert_held(&vc4_hdmi->mutex); - - if (!display->is_hdmi) - return false; - - if (!display->hdmi.scdc.supported || - !display->hdmi.scdc.scrambling.supported) - return false; - - return true; -} - #define SCRAMBLING_POLLING_DELAY_MS 1000 static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) From 6bed2ea3cb3856edf37cca20753e689ee8774793 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 29 Aug 2022 15:47:30 +0200 Subject: [PATCH 071/119] drm/vc4: hdmi: Reset link on hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During a hotplug cycle (such as a TV going out of suspend, or when the cable is disconnected and reconnected), the expectation is that the same state used before the disconnection is reused until the next commit. However, the HDMI scrambling requires that some flags are set in the monitor, and those flags are very likely to be reset when the cable has been disconnected. This will thus result in a blank display, even if the display pipeline configuration hasn't been modified or is in the exact same state. The solution we've had so far is to enable the scrambling-related bits again on reconnection, but the HDMI 2.0 specification (Section 6.1.3.1 - Scrambling Control) requires that the scrambling enable bit is set before sending any scrambled video signal. Using that solution thus breaks that expectation. The solution used by i915 is to do a full modeset on the connector so that we disable the video signal, enable the scrambling bit, and enable the video signal again. As such, we took that code and plugged it into vc4. It probably could have been turned into an helper, but it proved to be difficult for several reasons: * i915 has fairly different structures than simpler KMS drivers such as vc4, so doing some code that works with both proved to be difficult; * Other simpler drivers could reuse some of it (tegra, dw-hdmi), but it would still require to move some parameters currently stored in private structure that are needed to compute whether the scrambling is needed or not, and then inform the driver that it needs to be enabled. Some of those parameters are already in core structures (drm_display_mode, drm_display_info, bpc), but the output format isnt't. Adding it is fairly challenging since unlike the TMDS char rate or mode, there's no consensus on what format to pick in drivers, so it's not possible to write some generic code that can depend on it. For these reasons, we chose to duplicate the code for now, until someone else really needs it as well, in which case we will be able to convert it into a generic helper. Reviewed-by: Ville Syrjälä Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220829134731.213478-8-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 104 ++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index cc9c60d4facff..b2d0a3c89fbbf 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -288,9 +288,103 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} #endif -static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder); +static int reset_pipe(struct drm_crtc *crtc, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + int ret; + + state = drm_atomic_state_alloc(crtc->dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = ctx; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto out; + } + + crtc_state->connectors_changed = true; + + ret = drm_atomic_commit(state); +out: + drm_atomic_state_put(state); + + return ret; +} + +static int vc4_hdmi_reset_link(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_device *drm = connector->dev; + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); + struct drm_encoder *encoder = &vc4_hdmi->encoder.base; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + bool scrambling_needed; + u8 config; + int ret; + + if (!connector) + return 0; + + ret = drm_modeset_lock(&drm->mode_config.connection_mutex, ctx); + if (ret) + return ret; + + conn_state = connector->state; + crtc = conn_state->crtc; + if (!crtc) + return 0; + + ret = drm_modeset_lock(&crtc->mutex, ctx); + if (ret) + return ret; + + crtc_state = crtc->state; + if (!crtc_state->active) + return 0; + + if (!vc4_hdmi_supports_scrambling(encoder)) + return 0; + + scrambling_needed = vc4_hdmi_mode_needs_scrambling(&vc4_hdmi->saved_adjusted_mode, + vc4_hdmi->output_bpc, + vc4_hdmi->output_format); + if (!scrambling_needed) + return 0; + + if (conn_state->commit && + !try_wait_for_completion(&conn_state->commit->hw_done)) + return 0; + + ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config); + if (ret < 0) { + drm_err(drm, "Failed to read TMDS config: %d\n", ret); + return 0; + } + + if (!!(config & SCDC_SCRAMBLING_ENABLE) == scrambling_needed) + return 0; + + /* + * HDMI 2.0 says that one should not send scrambled data + * prior to configuring the sink scrambling, and that + * TMDS clock/data transmission should be suspended when + * changing the TMDS clock rate in the sink. So let's + * just do a full modeset here, even though some sinks + * would be perfectly happy if were to just reconfigure + * the SCDC settings on the fly. + */ + return reset_pipe(crtc, ctx); +} static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, + struct drm_modeset_acquire_ctx *ctx, enum drm_connector_status status) { struct drm_connector *connector = &vc4_hdmi->connector; @@ -303,6 +397,10 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, * .adap_enable, which leads to that funtion being called with * our mutex held. * + * A similar situation occurs with + * drm_atomic_helper_connector_hdmi_reset_link() that will call + * into our KMS hooks if the scrambling was enabled. + * * Concurrency isn't an issue at the moment since we don't share * any state with any of the other frameworks so we can ignore * the lock for now. @@ -320,7 +418,7 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); kfree(edid); - vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base.base); + vc4_hdmi_reset_link(connector, ctx); } static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector, @@ -352,7 +450,7 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector, status = connector_status_connected; } - vc4_hdmi_handle_hotplug(vc4_hdmi, status); + vc4_hdmi_handle_hotplug(vc4_hdmi, ctx, status); pm_runtime_put(&vc4_hdmi->pdev->dev); return status; From 68ded02cb2c23f1aebf026196a793959bd0463dc Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 29 Aug 2022 15:47:31 +0200 Subject: [PATCH 072/119] drm/scdc: Document hotplug gotchas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's some interactions between the SCDC setup and the disconnection / reconnection of displays. Let's document it and a solution. Reviewed-by: Ville Syrjälä Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220829134731.213478-9-maxime@cerno.tech --- drivers/gpu/drm/display/drm_scdc_helper.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/display/drm_scdc_helper.c b/drivers/gpu/drm/display/drm_scdc_helper.c index 81881e81ceae0..c3ad4ab2b4569 100644 --- a/drivers/gpu/drm/display/drm_scdc_helper.c +++ b/drivers/gpu/drm/display/drm_scdc_helper.c @@ -35,6 +35,19 @@ * HDMI 2.0 specification. It is a point-to-point protocol that allows the * HDMI source and HDMI sink to exchange data. The same I2C interface that * is used to access EDID serves as the transport mechanism for SCDC. + * + * Note: The SCDC status is going to be lost when the display is + * disconnected. This can happen physically when the user disconnects + * the cable, but also when a display is switched on (such as waking up + * a TV). + * + * This is further complicated by the fact that, upon a disconnection / + * reconnection, KMS won't change the mode on its own. This means that + * one can't just rely on setting the SCDC status on enable, but also + * has to track the connector status changes using interrupts and + * restore the SCDC status. The typical solution for this is to trigger an + * empty modeset in drm_connector_helper_funcs.detect_ctx(), like what vc4 does + * in vc4_hdmi_reset_link(). */ #define SCDC_I2C_SLAVE_ADDRESS 0x54 From a2224f2d458a093486ede49e319a32f02d99ef16 Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Tue, 13 Sep 2022 10:48:42 +0800 Subject: [PATCH 073/119] drm/vmwgfx: remove unused vmw_bo_is_vmw_bo() declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vmw_bo_is_vmw_bo() has been removed since commit 298799a28264 ("drm/vmwgfx: Fix gem refcounting and memory evictions"), so remove it. Acked-by: Christian König Signed-off-by: Gaosheng Cui Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20220913024847.552254-2-cuigaosheng1@huawei.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index be19aa6e1f13f..09e2d738aa876 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -877,7 +877,6 @@ static inline void vmw_user_resource_noref_release(void) /** * Buffer object helper functions - vmwgfx_bo.c */ -extern bool vmw_bo_is_vmw_bo(struct ttm_buffer_object *bo); extern int vmw_bo_pin_in_placement(struct vmw_private *vmw_priv, struct vmw_buffer_object *bo, struct ttm_placement *placement, From b779e4b973b7001555efc9120a7f07e4ae554d9e Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Tue, 13 Sep 2022 10:48:43 +0800 Subject: [PATCH 074/119] drm/radeon/r600_cs: remove r600_cs_legacy_get_tiling_conf() declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit r600_cs_legacy_get_tiling_conf() has been removed since commit 8333f607a631 ("drm/radeon: remove UMS support"), so remove it. Acked-by: Christian König Signed-off-by: Gaosheng Cui Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20220913024847.552254-3-cuigaosheng1@huawei.com --- drivers/gpu/drm/radeon/r600_cs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 8be4799a98eff..638f861af80fa 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -34,8 +34,6 @@ #include "r600_reg_safe.h" static int r600_nomm; -extern void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size); - struct r600_cs_track { /* configuration we mirror so that we use same code btw kms/ums */ From 2b61e16a3c875f65e341c3769ef2c80b87cf45be Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Tue, 13 Sep 2022 10:48:44 +0800 Subject: [PATCH 075/119] drm/radeon: remove unused declarations for radeon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit radeon_combios_get_ext_tmds_info() has been removed since commit fcec570b27a4 ("drm/radeon/kms: add support for external tmds on legacy boards"). radeon_mst has been removed since commit 01ad1d9c2888 ("drm/radeon: Drop legacy MST support"). r600_hdmi_acr() has been removed since commit 64424d6e45ae ("radeon/audio: consolidate update_acr() functions (v2)"). So remove the declarations for them from header file. Acked-by: Christian König Signed-off-by: Gaosheng Cui Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20220913024847.552254-4-cuigaosheng1@huawei.com --- drivers/gpu/drm/radeon/radeon.h | 3 --- drivers/gpu/drm/radeon/radeon_mode.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 08f83bf2c3307..166c18d62f6d7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -116,7 +116,6 @@ extern int radeon_use_pflipirq; extern int radeon_bapm; extern int radeon_backlight; extern int radeon_auxch; -extern int radeon_mst; extern int radeon_uvd; extern int radeon_vce; extern int radeon_si_support; @@ -2950,8 +2949,6 @@ struct radeon_hdmi_acr { }; -extern struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock); - extern u32 r6xx_remap_render_backend(struct radeon_device *rdev, u32 tiling_pipe_num, u32 max_rb_num, diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 6a6a732042262..9f5be416454fa 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -874,7 +874,6 @@ extern struct radeon_encoder_tv_dac * radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder); extern struct radeon_encoder_lvds * radeon_combios_get_lvds_info(struct radeon_encoder *encoder); -extern void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder); extern struct radeon_encoder_tv_dac * radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder); extern struct radeon_encoder_primary_dac * From 04e6fcc1b374c28e53c1b3f8b60b935a056c369f Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Tue, 13 Sep 2022 10:48:45 +0800 Subject: [PATCH 076/119] drm/gma500: remove unused declarations in psb_intel_drv.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit psb_intel_sdvo_supports_hotplug(), psb_intel_sdvo_set_hotplug() and psb_intel_sdvo_find() have been removed since commit 871c60156dbe ("drm/gma500: Remove dead code"), so remove them. Acked-by: Christian König Signed-off-by: Gaosheng Cui Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20220913024847.552254-5-cuigaosheng1@huawei.com --- drivers/gpu/drm/gma500/psb_intel_drv.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 8ccba116821b5..8a1111fe714b5 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -197,8 +197,6 @@ extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level); extern void oaktrail_lvds_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); extern void oaktrail_wait_for_INTR_PKT_SENT(struct drm_device *dev); -extern void oaktrail_dsi_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev); struct gma_i2c_chan *oaktrail_lvds_i2c_init(struct drm_device *dev); extern void mid_dsi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int dsi_num); @@ -219,9 +217,6 @@ extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, int sdvoB); -extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector); -extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, - int enable); extern int intelfb_probe(struct drm_device *dev); extern int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); From 75cebd664d57a78af3e46c14bd2659df0a08847b Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Tue, 13 Sep 2022 10:48:46 +0800 Subject: [PATCH 077/119] drm/amd/pm: remove unused declarations in hardwaremanager.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit phm_is_hw_access_blocked() and phm_block_hw_access() has been removed since commit 698f88e697cc ("drm/amd/powerplay: delete dead code in powerplay"), so remove them. Acked-by: Christian König Signed-off-by: Gaosheng Cui Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20220913024847.552254-6-cuigaosheng1@huawei.com --- drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h index 6e0be60277057..01a7d66864f22 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h @@ -401,8 +401,6 @@ extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr); extern int phm_setup_asic(struct pp_hwmgr *hwmgr); extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr); extern int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr); -extern bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr); -extern int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block); extern int phm_set_power_state(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pcurrent_state, const struct pp_hw_power_state *pnew_power_state); From b167259a12f2c49e82cbd077499df85117177a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Sun, 11 Sep 2022 16:17:55 -0300 Subject: [PATCH 078/119] drm/tests: Split drm_framebuffer_create_test into parameterized tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The igt_check_drm_framebuffer_create is based on a loop that executes tests for all createbuffer_tests test cases. This could be better represented by parameterized tests, provided by KUnit. So, convert the igt_check_drm_framebuffer_create into parameterized tests. Signed-off-by: Maíra Canal Reviewed-by: Michał Winiarski Reviewed-by: David Gow Link: https://patchwork.freedesktop.org/patch/msgid/20220911191756.203118-1-mairacanal@riseup.net --- drivers/gpu/drm/tests/drm_framebuffer_test.c | 53 +++++++++++--------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_framebuffer_test.c b/drivers/gpu/drm/tests/drm_framebuffer_test.c index ec7a08ba40561..df235b7fdaa5c 100644 --- a/drivers/gpu/drm/tests/drm_framebuffer_test.c +++ b/drivers/gpu/drm/tests/drm_framebuffer_test.c @@ -25,7 +25,7 @@ struct drm_framebuffer_test { const char *name; }; -static struct drm_framebuffer_test createbuffer_tests[] = { +static const struct drm_framebuffer_test drm_framebuffer_create_cases[] = { { .buffer_created = 1, .name = "ABGR8888 normal sizes", .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_ABGR8888, .handles = { 1, 0, 0 }, .pitches = { 4 * 600, 0, 0 }, @@ -330,43 +330,50 @@ static struct drm_mode_config_funcs mock_config_funcs = { .fb_create = fb_create_mock, }; -static struct drm_device mock_drm_device = { - .mode_config = { - .min_width = MIN_WIDTH, - .max_width = MAX_WIDTH, - .min_height = MIN_HEIGHT, - .max_height = MAX_HEIGHT, - .funcs = &mock_config_funcs, - }, -}; +static int drm_framebuffer_test_init(struct kunit *test) +{ + struct drm_device *mock; + + mock = kunit_kzalloc(test, sizeof(*mock), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mock); -static int execute_drm_mode_fb_cmd2(struct drm_mode_fb_cmd2 *r) + mock->mode_config.min_width = MIN_WIDTH; + mock->mode_config.max_width = MAX_WIDTH; + mock->mode_config.min_height = MIN_HEIGHT; + mock->mode_config.max_height = MAX_HEIGHT; + mock->mode_config.funcs = &mock_config_funcs; + + test->priv = mock; + return 0; +} + +static void drm_test_framebuffer_create(struct kunit *test) { + const struct drm_framebuffer_test *params = test->param_value; + struct drm_device *mock = test->priv; int buffer_created = 0; - mock_drm_device.dev_private = &buffer_created; - drm_internal_framebuffer_create(&mock_drm_device, r, NULL); - return buffer_created; + mock->dev_private = &buffer_created; + drm_internal_framebuffer_create(mock, ¶ms->cmd, NULL); + KUNIT_EXPECT_EQ(test, params->buffer_created, buffer_created); } -static void igt_check_drm_framebuffer_create(struct kunit *test) +static void drm_framebuffer_test_to_desc(const struct drm_framebuffer_test *t, char *desc) { - int i = 0; - - for (i = 0; i < ARRAY_SIZE(createbuffer_tests); i++) { - KUNIT_EXPECT_EQ_MSG(test, createbuffer_tests[i].buffer_created, - execute_drm_mode_fb_cmd2(&createbuffer_tests[i].cmd), - "Test %d: \"%s\" failed\n", i, createbuffer_tests[i].name); - } + strcpy(desc, t->name); } +KUNIT_ARRAY_PARAM(drm_framebuffer_create, drm_framebuffer_create_cases, + drm_framebuffer_test_to_desc); + static struct kunit_case drm_framebuffer_tests[] = { - KUNIT_CASE(igt_check_drm_framebuffer_create), + KUNIT_CASE_PARAM(drm_test_framebuffer_create, drm_framebuffer_create_gen_params), { } }; static struct kunit_suite drm_framebuffer_test_suite = { .name = "drm_framebuffer", + .init = drm_framebuffer_test_init, .test_cases = drm_framebuffer_tests, }; From 961bcdf956a4645745407a5d919be8757549b062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Sun, 11 Sep 2022 16:17:56 -0300 Subject: [PATCH 079/119] drm/tests: Change "igt_" prefix to "drm_test_" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the introduction of KUnit, IGT is no longer the only option to run the DRM unit tests, as the tests can be run through kunit-tool or on real hardware with CONFIG_KUNIT. Therefore, remove the "igt_" prefix from the tests and replace it with the "drm_test_" prefix, making the tests' names independent from the tool used. Signed-off-by: Maíra Canal Acked-by: David Gow Acked-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220911191756.203118-2-mairacanal@riseup.net --- drivers/gpu/drm/tests/drm_buddy_test.c | 84 +++++----- .../gpu/drm/tests/drm_cmdline_parser_test.c | 156 +++++++++--------- .../gpu/drm/tests/drm_damage_helper_test.c | 84 +++++----- .../gpu/drm/tests/drm_dp_mst_helper_test.c | 8 +- .../gpu/drm/tests/drm_format_helper_test.c | 8 +- drivers/gpu/drm/tests/drm_format_test.c | 72 ++++---- drivers/gpu/drm/tests/drm_mm_test.c | 155 ++++++++--------- drivers/gpu/drm/tests/drm_plane_helper_test.c | 4 +- drivers/gpu/drm/tests/drm_rect_test.c | 16 +- 9 files changed, 294 insertions(+), 293 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c index d76f83833e755..7a2b2d6bc3fe9 100644 --- a/drivers/gpu/drm/tests/drm_buddy_test.c +++ b/drivers/gpu/drm/tests/drm_buddy_test.c @@ -13,7 +13,7 @@ #include "../lib/drm_random.h" -#define IGT_TIMEOUT(name__) \ +#define TIMEOUT(name__) \ unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT static unsigned int random_seed; @@ -24,7 +24,7 @@ static inline u64 get_size(int order, u64 chunk_size) } __printf(2, 3) -static bool __igt_timeout(unsigned long timeout, const char *fmt, ...) +static bool __timeout(unsigned long timeout, const char *fmt, ...) { va_list va; @@ -43,8 +43,8 @@ static bool __igt_timeout(unsigned long timeout, const char *fmt, ...) return true; } -static void __igt_dump_block(struct kunit *test, struct drm_buddy *mm, - struct drm_buddy_block *block, bool buddy) +static void __dump_block(struct kunit *test, struct drm_buddy *mm, + struct drm_buddy_block *block, bool buddy) { kunit_err(test, "block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%d buddy=%d\n", block->header, drm_buddy_block_state(block), @@ -52,20 +52,20 @@ static void __igt_dump_block(struct kunit *test, struct drm_buddy *mm, drm_buddy_block_size(mm, block), !block->parent, buddy); } -static void igt_dump_block(struct kunit *test, struct drm_buddy *mm, - struct drm_buddy_block *block) +static void dump_block(struct kunit *test, struct drm_buddy *mm, + struct drm_buddy_block *block) { struct drm_buddy_block *buddy; - __igt_dump_block(test, mm, block, false); + __dump_block(test, mm, block, false); buddy = drm_get_buddy(block); if (buddy) - __igt_dump_block(test, mm, buddy, true); + __dump_block(test, mm, buddy, true); } -static int igt_check_block(struct kunit *test, struct drm_buddy *mm, - struct drm_buddy_block *block) +static int check_block(struct kunit *test, struct drm_buddy *mm, + struct drm_buddy_block *block) { struct drm_buddy_block *buddy; unsigned int block_state; @@ -137,8 +137,8 @@ static int igt_check_block(struct kunit *test, struct drm_buddy *mm, return err; } -static int igt_check_blocks(struct kunit *test, struct drm_buddy *mm, - struct list_head *blocks, u64 expected_size, bool is_contiguous) +static int check_blocks(struct kunit *test, struct drm_buddy *mm, + struct list_head *blocks, u64 expected_size, bool is_contiguous) { struct drm_buddy_block *block; struct drm_buddy_block *prev; @@ -150,7 +150,7 @@ static int igt_check_blocks(struct kunit *test, struct drm_buddy *mm, total = 0; list_for_each_entry(block, blocks, link) { - err = igt_check_block(test, mm, block); + err = check_block(test, mm, block); if (!drm_buddy_block_is_allocated(block)) { kunit_err(test, "block not allocated\n"); @@ -190,16 +190,16 @@ static int igt_check_blocks(struct kunit *test, struct drm_buddy *mm, if (prev) { kunit_err(test, "prev block, dump:\n"); - igt_dump_block(test, mm, prev); + dump_block(test, mm, prev); } kunit_err(test, "bad block, dump:\n"); - igt_dump_block(test, mm, block); + dump_block(test, mm, block); return err; } -static int igt_check_mm(struct kunit *test, struct drm_buddy *mm) +static int check_mm(struct kunit *test, struct drm_buddy *mm) { struct drm_buddy_block *root; struct drm_buddy_block *prev; @@ -233,7 +233,7 @@ static int igt_check_mm(struct kunit *test, struct drm_buddy *mm) break; } - err = igt_check_block(test, mm, root); + err = check_block(test, mm, root); if (!drm_buddy_block_is_free(root)) { kunit_err(test, "root not free\n"); @@ -289,18 +289,18 @@ static int igt_check_mm(struct kunit *test, struct drm_buddy *mm) if (prev) { kunit_err(test, "prev root(%u), dump:\n", i - 1); - igt_dump_block(test, mm, prev); + dump_block(test, mm, prev); } if (root) { kunit_err(test, "bad root(%u), dump:\n", i); - igt_dump_block(test, mm, root); + dump_block(test, mm, root); } return err; } -static void igt_mm_config(u64 *size, u64 *chunk_size) +static void mm_config(u64 *size, u64 *chunk_size) { DRM_RND_STATE(prng, random_seed); u32 s, ms; @@ -321,7 +321,7 @@ static void igt_mm_config(u64 *size, u64 *chunk_size) *size = (u64)s << 12; } -static void igt_buddy_alloc_pathological(struct kunit *test) +static void drm_test_buddy_alloc_pathological(struct kunit *test) { u64 mm_size, size, start = 0; struct drm_buddy_block *block; @@ -402,7 +402,7 @@ static void igt_buddy_alloc_pathological(struct kunit *test) drm_buddy_fini(&mm); } -static void igt_buddy_alloc_smoke(struct kunit *test) +static void drm_test_buddy_alloc_smoke(struct kunit *test) { u64 mm_size, chunk_size, start = 0; unsigned long flags = 0; @@ -411,9 +411,9 @@ static void igt_buddy_alloc_smoke(struct kunit *test) int i; DRM_RND_STATE(prng, random_seed); - IGT_TIMEOUT(end_time); + TIMEOUT(end_time); - igt_mm_config(&mm_size, &chunk_size); + mm_config(&mm_size, &chunk_size); KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, chunk_size), "buddy_init failed\n"); @@ -430,7 +430,7 @@ static void igt_buddy_alloc_smoke(struct kunit *test) LIST_HEAD(tmp); int order, err; - KUNIT_ASSERT_FALSE_MSG(test, igt_check_mm(test, &mm), + KUNIT_ASSERT_FALSE_MSG(test, check_mm(test, &mm), "pre-mm check failed, abort\n"); order = max_order; @@ -466,19 +466,19 @@ static void igt_buddy_alloc_smoke(struct kunit *test) total += drm_buddy_block_size(&mm, block); - if (__igt_timeout(end_time, NULL)) { + if (__timeout(end_time, NULL)) { timeout = true; break; } } while (total < mm.size); if (!err) - err = igt_check_blocks(test, &mm, &blocks, total, false); + err = check_blocks(test, &mm, &blocks, total, false); drm_buddy_free_list(&mm, &blocks); if (!err) { - KUNIT_EXPECT_FALSE_MSG(test, igt_check_mm(test, &mm), + KUNIT_EXPECT_FALSE_MSG(test, check_mm(test, &mm), "post-mm check failed\n"); } @@ -492,7 +492,7 @@ static void igt_buddy_alloc_smoke(struct kunit *test) drm_buddy_fini(&mm); } -static void igt_buddy_alloc_pessimistic(struct kunit *test) +static void drm_test_buddy_alloc_pessimistic(struct kunit *test) { u64 mm_size, size, start = 0; struct drm_buddy_block *block, *bn; @@ -587,7 +587,7 @@ static void igt_buddy_alloc_pessimistic(struct kunit *test) drm_buddy_fini(&mm); } -static void igt_buddy_alloc_optimistic(struct kunit *test) +static void drm_test_buddy_alloc_optimistic(struct kunit *test) { u64 mm_size, size, start = 0; struct drm_buddy_block *block; @@ -633,7 +633,7 @@ static void igt_buddy_alloc_optimistic(struct kunit *test) drm_buddy_fini(&mm); } -static void igt_buddy_alloc_range(struct kunit *test) +static void drm_test_buddy_alloc_range(struct kunit *test) { unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION; u64 offset, size, rem, chunk_size, end; @@ -641,12 +641,12 @@ static void igt_buddy_alloc_range(struct kunit *test) struct drm_buddy mm; LIST_HEAD(blocks); - igt_mm_config(&size, &chunk_size); + mm_config(&size, &chunk_size); KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, size, chunk_size), "buddy_init failed"); - KUNIT_ASSERT_FALSE_MSG(test, igt_check_mm(test, &mm), + KUNIT_ASSERT_FALSE_MSG(test, check_mm(test, &mm), "pre-mm check failed, abort!"); rem = mm.size; @@ -671,7 +671,7 @@ static void igt_buddy_alloc_range(struct kunit *test) "alloc_range start offset mismatch, found=%llx, expected=%llx\n", drm_buddy_block_offset(block), offset); - KUNIT_ASSERT_FALSE(test, igt_check_blocks(test, &mm, &tmp, size, true)); + KUNIT_ASSERT_FALSE(test, check_blocks(test, &mm, &tmp, size, true)); list_splice_tail(&tmp, &blocks); @@ -686,12 +686,12 @@ static void igt_buddy_alloc_range(struct kunit *test) drm_buddy_free_list(&mm, &blocks); - KUNIT_EXPECT_FALSE_MSG(test, igt_check_mm(test, &mm), "post-mm check failed\n"); + KUNIT_EXPECT_FALSE_MSG(test, check_mm(test, &mm), "post-mm check failed\n"); drm_buddy_fini(&mm); } -static void igt_buddy_alloc_limit(struct kunit *test) +static void drm_test_buddy_alloc_limit(struct kunit *test) { u64 size = U64_MAX, start = 0; struct drm_buddy_block *block; @@ -735,12 +735,12 @@ static int drm_buddy_init_test(struct kunit *test) } static struct kunit_case drm_buddy_tests[] = { - KUNIT_CASE(igt_buddy_alloc_limit), - KUNIT_CASE(igt_buddy_alloc_range), - KUNIT_CASE(igt_buddy_alloc_optimistic), - KUNIT_CASE(igt_buddy_alloc_pessimistic), - KUNIT_CASE(igt_buddy_alloc_smoke), - KUNIT_CASE(igt_buddy_alloc_pathological), + KUNIT_CASE(drm_test_buddy_alloc_limit), + KUNIT_CASE(drm_test_buddy_alloc_range), + KUNIT_CASE(drm_test_buddy_alloc_optimistic), + KUNIT_CASE(drm_test_buddy_alloc_pessimistic), + KUNIT_CASE(drm_test_buddy_alloc_smoke), + KUNIT_CASE(drm_test_buddy_alloc_pathological), {} }; diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c index 09b806e275063..34790e7a3760c 100644 --- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c +++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c @@ -11,7 +11,7 @@ static const struct drm_connector no_connector = {}; -static void drm_cmdline_test_force_e_only(struct kunit *test) +static void drm_test_cmdline_force_e_only(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "e"; @@ -29,7 +29,7 @@ static void drm_cmdline_test_force_e_only(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); } -static void drm_cmdline_test_force_D_only_not_digital(struct kunit *test) +static void drm_test_cmdline_force_D_only_not_digital(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "D"; @@ -51,7 +51,7 @@ static const struct drm_connector connector_hdmi = { .connector_type = DRM_MODE_CONNECTOR_HDMIB, }; -static void drm_cmdline_test_force_D_only_hdmi(struct kunit *test) +static void drm_test_cmdline_force_D_only_hdmi(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "D"; @@ -73,7 +73,7 @@ static const struct drm_connector connector_dvi = { .connector_type = DRM_MODE_CONNECTOR_DVII, }; -static void drm_cmdline_test_force_D_only_dvi(struct kunit *test) +static void drm_test_cmdline_force_D_only_dvi(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "D"; @@ -91,7 +91,7 @@ static void drm_cmdline_test_force_D_only_dvi(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON_DIGITAL); } -static void drm_cmdline_test_force_d_only(struct kunit *test) +static void drm_test_cmdline_force_d_only(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "d"; @@ -109,7 +109,7 @@ static void drm_cmdline_test_force_d_only(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_OFF); } -static void drm_cmdline_test_res(struct kunit *test) +static void drm_test_cmdline_res(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480"; @@ -131,7 +131,7 @@ static void drm_cmdline_test_res(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_vesa(struct kunit *test) +static void drm_test_cmdline_res_vesa(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480M"; @@ -153,7 +153,7 @@ static void drm_cmdline_test_res_vesa(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_vesa_rblank(struct kunit *test) +static void drm_test_cmdline_res_vesa_rblank(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480MR"; @@ -175,7 +175,7 @@ static void drm_cmdline_test_res_vesa_rblank(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_rblank(struct kunit *test) +static void drm_test_cmdline_res_rblank(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480R"; @@ -197,7 +197,7 @@ static void drm_cmdline_test_res_rblank(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_bpp(struct kunit *test) +static void drm_test_cmdline_res_bpp(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24"; @@ -220,7 +220,7 @@ static void drm_cmdline_test_res_bpp(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_refresh(struct kunit *test) +static void drm_test_cmdline_res_refresh(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480@60"; @@ -243,7 +243,7 @@ static void drm_cmdline_test_res_refresh(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_bpp_refresh(struct kunit *test) +static void drm_test_cmdline_res_bpp_refresh(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60"; @@ -267,7 +267,7 @@ static void drm_cmdline_test_res_bpp_refresh(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_bpp_refresh_interlaced(struct kunit *test) +static void drm_test_cmdline_res_bpp_refresh_interlaced(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60i"; @@ -291,7 +291,7 @@ static void drm_cmdline_test_res_bpp_refresh_interlaced(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_bpp_refresh_margins(struct kunit *test) +static void drm_test_cmdline_res_bpp_refresh_margins(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60m"; @@ -315,7 +315,7 @@ static void drm_cmdline_test_res_bpp_refresh_margins(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_bpp_refresh_force_off(struct kunit *test) +static void drm_test_cmdline_res_bpp_refresh_force_off(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60d"; @@ -339,7 +339,7 @@ static void drm_cmdline_test_res_bpp_refresh_force_off(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_OFF); } -static void drm_cmdline_test_res_bpp_refresh_force_on(struct kunit *test) +static void drm_test_cmdline_res_bpp_refresh_force_on(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60e"; @@ -363,7 +363,7 @@ static void drm_cmdline_test_res_bpp_refresh_force_on(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); } -static void drm_cmdline_test_res_bpp_refresh_force_on_analog(struct kunit *test) +static void drm_test_cmdline_res_bpp_refresh_force_on_analog(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60D"; @@ -387,7 +387,7 @@ static void drm_cmdline_test_res_bpp_refresh_force_on_analog(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); } -static void drm_cmdline_test_res_bpp_refresh_force_on_digital(struct kunit *test) +static void drm_test_cmdline_res_bpp_refresh_force_on_digital(struct kunit *test) { struct drm_cmdline_mode mode = { }; static const struct drm_connector connector = { @@ -414,7 +414,7 @@ static void drm_cmdline_test_res_bpp_refresh_force_on_digital(struct kunit *test KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON_DIGITAL); } -static void drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on(struct kunit *test) +static void drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60ime"; @@ -438,7 +438,7 @@ static void drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on(struct KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); } -static void drm_cmdline_test_res_margins_force_on(struct kunit *test) +static void drm_test_cmdline_res_margins_force_on(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480me"; @@ -460,7 +460,7 @@ static void drm_cmdline_test_res_margins_force_on(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); } -static void drm_cmdline_test_res_vesa_margins(struct kunit *test) +static void drm_test_cmdline_res_vesa_margins(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480Mm"; @@ -482,7 +482,7 @@ static void drm_cmdline_test_res_vesa_margins(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_name(struct kunit *test) +static void drm_test_cmdline_name(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "NTSC"; @@ -494,7 +494,7 @@ static void drm_cmdline_test_name(struct kunit *test) KUNIT_EXPECT_FALSE(test, mode.bpp_specified); } -static void drm_cmdline_test_name_bpp(struct kunit *test) +static void drm_test_cmdline_name_bpp(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "NTSC-24"; @@ -509,7 +509,7 @@ static void drm_cmdline_test_name_bpp(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.bpp, 24); } -static void drm_cmdline_test_name_option(struct kunit *test) +static void drm_test_cmdline_name_option(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "NTSC,rotate=180"; @@ -521,7 +521,7 @@ static void drm_cmdline_test_name_option(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180); } -static void drm_cmdline_test_name_bpp_option(struct kunit *test) +static void drm_test_cmdline_name_bpp_option(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "NTSC-24,rotate=180"; @@ -535,7 +535,7 @@ static void drm_cmdline_test_name_bpp_option(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.bpp, 24); } -static void drm_cmdline_test_rotate_0(struct kunit *test) +static void drm_test_cmdline_rotate_0(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=0"; @@ -558,7 +558,7 @@ static void drm_cmdline_test_rotate_0(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_rotate_90(struct kunit *test) +static void drm_test_cmdline_rotate_90(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=90"; @@ -581,7 +581,7 @@ static void drm_cmdline_test_rotate_90(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_rotate_180(struct kunit *test) +static void drm_test_cmdline_rotate_180(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=180"; @@ -604,7 +604,7 @@ static void drm_cmdline_test_rotate_180(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_rotate_270(struct kunit *test) +static void drm_test_cmdline_rotate_270(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=270"; @@ -627,7 +627,7 @@ static void drm_cmdline_test_rotate_270(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_hmirror(struct kunit *test) +static void drm_test_cmdline_hmirror(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,reflect_x"; @@ -650,7 +650,7 @@ static void drm_cmdline_test_hmirror(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_vmirror(struct kunit *test) +static void drm_test_cmdline_vmirror(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,reflect_y"; @@ -673,7 +673,7 @@ static void drm_cmdline_test_vmirror(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_margin_options(struct kunit *test) +static void drm_test_cmdline_margin_options(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = @@ -700,7 +700,7 @@ static void drm_cmdline_test_margin_options(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_multiple_options(struct kunit *test) +static void drm_test_cmdline_multiple_options(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=270,reflect_x"; @@ -723,7 +723,7 @@ static void drm_cmdline_test_multiple_options(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_bpp_extra_and_option(struct kunit *test) +static void drm_test_cmdline_bpp_extra_and_option(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24e,rotate=180"; @@ -747,7 +747,7 @@ static void drm_cmdline_test_bpp_extra_and_option(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); } -static void drm_cmdline_test_extra_and_option(struct kunit *test) +static void drm_test_cmdline_extra_and_option(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480e,rotate=180"; @@ -769,7 +769,7 @@ static void drm_cmdline_test_extra_and_option(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); } -static void drm_cmdline_test_freestanding_options(struct kunit *test) +static void drm_test_cmdline_freestanding_options(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "margin_right=14,margin_left=24,margin_bottom=36,margin_top=42"; @@ -792,7 +792,7 @@ static void drm_cmdline_test_freestanding_options(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_freestanding_force_e_and_options(struct kunit *test) +static void drm_test_cmdline_freestanding_force_e_and_options(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42"; @@ -815,7 +815,7 @@ static void drm_cmdline_test_freestanding_force_e_and_options(struct kunit *test KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); } -static void drm_cmdline_test_panel_orientation(struct kunit *test) +static void drm_test_cmdline_panel_orientation(struct kunit *test) { struct drm_cmdline_mode mode = { }; const char *cmdline = "panel_orientation=upside_down"; @@ -840,7 +840,7 @@ struct drm_cmdline_invalid_test { const char *cmdline; }; -static void drm_cmdline_test_invalid(struct kunit *test) +static void drm_test_cmdline_invalid(struct kunit *test) { const struct drm_cmdline_invalid_test *params = test->param_value; struct drm_cmdline_mode mode = { }; @@ -938,45 +938,45 @@ static void drm_cmdline_invalid_desc(const struct drm_cmdline_invalid_test *t, KUNIT_ARRAY_PARAM(drm_cmdline_invalid, drm_cmdline_invalid_tests, drm_cmdline_invalid_desc); static struct kunit_case drm_cmdline_parser_tests[] = { - KUNIT_CASE(drm_cmdline_test_force_d_only), - KUNIT_CASE(drm_cmdline_test_force_D_only_dvi), - KUNIT_CASE(drm_cmdline_test_force_D_only_hdmi), - KUNIT_CASE(drm_cmdline_test_force_D_only_not_digital), - KUNIT_CASE(drm_cmdline_test_force_e_only), - KUNIT_CASE(drm_cmdline_test_res), - KUNIT_CASE(drm_cmdline_test_res_vesa), - KUNIT_CASE(drm_cmdline_test_res_vesa_rblank), - KUNIT_CASE(drm_cmdline_test_res_rblank), - KUNIT_CASE(drm_cmdline_test_res_bpp), - KUNIT_CASE(drm_cmdline_test_res_refresh), - KUNIT_CASE(drm_cmdline_test_res_bpp_refresh), - KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_interlaced), - KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_margins), - KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_off), - KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on), - KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_analog), - KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_digital), - KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on), - KUNIT_CASE(drm_cmdline_test_res_margins_force_on), - KUNIT_CASE(drm_cmdline_test_res_vesa_margins), - KUNIT_CASE(drm_cmdline_test_name), - KUNIT_CASE(drm_cmdline_test_name_bpp), - KUNIT_CASE(drm_cmdline_test_name_option), - KUNIT_CASE(drm_cmdline_test_name_bpp_option), - KUNIT_CASE(drm_cmdline_test_rotate_0), - KUNIT_CASE(drm_cmdline_test_rotate_90), - KUNIT_CASE(drm_cmdline_test_rotate_180), - KUNIT_CASE(drm_cmdline_test_rotate_270), - KUNIT_CASE(drm_cmdline_test_hmirror), - KUNIT_CASE(drm_cmdline_test_vmirror), - KUNIT_CASE(drm_cmdline_test_margin_options), - KUNIT_CASE(drm_cmdline_test_multiple_options), - KUNIT_CASE(drm_cmdline_test_bpp_extra_and_option), - KUNIT_CASE(drm_cmdline_test_extra_and_option), - KUNIT_CASE(drm_cmdline_test_freestanding_options), - KUNIT_CASE(drm_cmdline_test_freestanding_force_e_and_options), - KUNIT_CASE(drm_cmdline_test_panel_orientation), - KUNIT_CASE_PARAM(drm_cmdline_test_invalid, drm_cmdline_invalid_gen_params), + KUNIT_CASE(drm_test_cmdline_force_d_only), + KUNIT_CASE(drm_test_cmdline_force_D_only_dvi), + KUNIT_CASE(drm_test_cmdline_force_D_only_hdmi), + KUNIT_CASE(drm_test_cmdline_force_D_only_not_digital), + KUNIT_CASE(drm_test_cmdline_force_e_only), + KUNIT_CASE(drm_test_cmdline_res), + KUNIT_CASE(drm_test_cmdline_res_vesa), + KUNIT_CASE(drm_test_cmdline_res_vesa_rblank), + KUNIT_CASE(drm_test_cmdline_res_rblank), + KUNIT_CASE(drm_test_cmdline_res_bpp), + KUNIT_CASE(drm_test_cmdline_res_refresh), + KUNIT_CASE(drm_test_cmdline_res_bpp_refresh), + KUNIT_CASE(drm_test_cmdline_res_bpp_refresh_interlaced), + KUNIT_CASE(drm_test_cmdline_res_bpp_refresh_margins), + KUNIT_CASE(drm_test_cmdline_res_bpp_refresh_force_off), + KUNIT_CASE(drm_test_cmdline_res_bpp_refresh_force_on), + KUNIT_CASE(drm_test_cmdline_res_bpp_refresh_force_on_analog), + KUNIT_CASE(drm_test_cmdline_res_bpp_refresh_force_on_digital), + KUNIT_CASE(drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on), + KUNIT_CASE(drm_test_cmdline_res_margins_force_on), + KUNIT_CASE(drm_test_cmdline_res_vesa_margins), + KUNIT_CASE(drm_test_cmdline_name), + KUNIT_CASE(drm_test_cmdline_name_bpp), + KUNIT_CASE(drm_test_cmdline_name_option), + KUNIT_CASE(drm_test_cmdline_name_bpp_option), + KUNIT_CASE(drm_test_cmdline_rotate_0), + KUNIT_CASE(drm_test_cmdline_rotate_90), + KUNIT_CASE(drm_test_cmdline_rotate_180), + KUNIT_CASE(drm_test_cmdline_rotate_270), + KUNIT_CASE(drm_test_cmdline_hmirror), + KUNIT_CASE(drm_test_cmdline_vmirror), + KUNIT_CASE(drm_test_cmdline_margin_options), + KUNIT_CASE(drm_test_cmdline_multiple_options), + KUNIT_CASE(drm_test_cmdline_bpp_extra_and_option), + KUNIT_CASE(drm_test_cmdline_extra_and_option), + KUNIT_CASE(drm_test_cmdline_freestanding_options), + KUNIT_CASE(drm_test_cmdline_freestanding_force_e_and_options), + KUNIT_CASE(drm_test_cmdline_panel_orientation), + KUNIT_CASE_PARAM(drm_test_cmdline_invalid, drm_cmdline_invalid_gen_params), {} }; diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c index c608ae06f0e31..115034fc34215 100644 --- a/drivers/gpu/drm/tests/drm_damage_helper_test.c +++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c @@ -116,7 +116,7 @@ static void check_damage_clip(struct kunit *test, struct drm_rect *r, r->x1, r->y1, r->x2, r->y2, x1, y1, x2, y2); } -static void igt_damage_iter_no_damage(struct kunit *test) +static void drm_test_damage_iter_no_damage(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -134,7 +134,7 @@ static void igt_damage_iter_no_damage(struct kunit *test) check_damage_clip(test, &clip, 0, 0, 2048, 2048); } -static void igt_damage_iter_no_damage_fractional_src(struct kunit *test) +static void drm_test_damage_iter_no_damage_fractional_src(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -155,7 +155,7 @@ static void igt_damage_iter_no_damage_fractional_src(struct kunit *test) check_damage_clip(test, &clip, 3, 3, 1028, 772); } -static void igt_damage_iter_no_damage_src_moved(struct kunit *test) +static void drm_test_damage_iter_no_damage_src_moved(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -174,7 +174,7 @@ static void igt_damage_iter_no_damage_src_moved(struct kunit *test) check_damage_clip(test, &clip, 10, 10, 1034, 778); } -static void igt_damage_iter_no_damage_fractional_src_moved(struct kunit *test) +static void drm_test_damage_iter_no_damage_fractional_src_moved(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -194,7 +194,7 @@ static void igt_damage_iter_no_damage_fractional_src_moved(struct kunit *test) check_damage_clip(test, &clip, 4, 4, 1029, 773); } -static void igt_damage_iter_no_damage_not_visible(struct kunit *test) +static void drm_test_damage_iter_no_damage_not_visible(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -212,7 +212,7 @@ static void igt_damage_iter_no_damage_not_visible(struct kunit *test) KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); } -static void igt_damage_iter_no_damage_no_crtc(struct kunit *test) +static void drm_test_damage_iter_no_damage_no_crtc(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -230,7 +230,7 @@ static void igt_damage_iter_no_damage_no_crtc(struct kunit *test) KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); } -static void igt_damage_iter_no_damage_no_fb(struct kunit *test) +static void drm_test_damage_iter_no_damage_no_fb(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -248,7 +248,7 @@ static void igt_damage_iter_no_damage_no_fb(struct kunit *test) KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); } -static void igt_damage_iter_simple_damage(struct kunit *test) +static void drm_test_damage_iter_simple_damage(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -271,7 +271,7 @@ static void igt_damage_iter_simple_damage(struct kunit *test) check_damage_clip(test, &clip, 0, 0, 1024, 768); } -static void igt_damage_iter_single_damage(struct kunit *test) +static void drm_test_damage_iter_single_damage(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -293,7 +293,7 @@ static void igt_damage_iter_single_damage(struct kunit *test) check_damage_clip(test, &clip, 256, 192, 768, 576); } -static void igt_damage_iter_single_damage_intersect_src(struct kunit *test) +static void drm_test_damage_iter_single_damage_intersect_src(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -316,7 +316,7 @@ static void igt_damage_iter_single_damage_intersect_src(struct kunit *test) check_damage_clip(test, &clip, 256, 192, 1024, 768); } -static void igt_damage_iter_single_damage_outside_src(struct kunit *test) +static void drm_test_damage_iter_single_damage_outside_src(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -338,7 +338,7 @@ static void igt_damage_iter_single_damage_outside_src(struct kunit *test) KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); } -static void igt_damage_iter_single_damage_fractional_src(struct kunit *test) +static void drm_test_damage_iter_single_damage_fractional_src(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -363,7 +363,7 @@ static void igt_damage_iter_single_damage_fractional_src(struct kunit *test) check_damage_clip(test, &clip, 10, 10, 256, 330); } -static void igt_damage_iter_single_damage_intersect_fractional_src(struct kunit *test) +static void drm_test_damage_iter_single_damage_intersect_fractional_src(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -390,7 +390,7 @@ static void igt_damage_iter_single_damage_intersect_fractional_src(struct kunit check_damage_clip(test, &clip, 10, 4, 1029, 330); } -static void igt_damage_iter_single_damage_outside_fractional_src(struct kunit *test) +static void drm_test_damage_iter_single_damage_outside_fractional_src(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -415,7 +415,7 @@ static void igt_damage_iter_single_damage_outside_fractional_src(struct kunit *t KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); } -static void igt_damage_iter_single_damage_src_moved(struct kunit *test) +static void drm_test_damage_iter_single_damage_src_moved(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -440,7 +440,7 @@ static void igt_damage_iter_single_damage_src_moved(struct kunit *test) check_damage_clip(test, &clip, 10, 10, 1034, 778); } -static void igt_damage_iter_single_damage_fractional_src_moved(struct kunit *test) +static void drm_test_damage_iter_single_damage_fractional_src_moved(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -467,7 +467,7 @@ static void igt_damage_iter_single_damage_fractional_src_moved(struct kunit *tes check_damage_clip(test, &clip, 4, 4, 1029, 773); } -static void igt_damage_iter_damage(struct kunit *test) +static void drm_test_damage_iter_damage(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -495,7 +495,7 @@ static void igt_damage_iter_damage(struct kunit *test) KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set."); } -static void igt_damage_iter_damage_one_intersect(struct kunit *test) +static void drm_test_damage_iter_damage_one_intersect(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -525,7 +525,7 @@ static void igt_damage_iter_damage_one_intersect(struct kunit *test) KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set."); } -static void igt_damage_iter_damage_one_outside(struct kunit *test) +static void drm_test_damage_iter_damage_one_outside(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -549,7 +549,7 @@ static void igt_damage_iter_damage_one_outside(struct kunit *test) check_damage_clip(test, &clip, 240, 200, 280, 250); } -static void igt_damage_iter_damage_src_moved(struct kunit *test) +static void drm_test_damage_iter_damage_src_moved(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -576,7 +576,7 @@ static void igt_damage_iter_damage_src_moved(struct kunit *test) check_damage_clip(test, &clip, 3, 3, 1028, 772); } -static void igt_damage_iter_damage_not_visible(struct kunit *test) +static void drm_test_damage_iter_damage_not_visible(struct kunit *test) { struct drm_damage_mock *mock = test->priv; struct drm_atomic_helper_damage_iter iter; @@ -604,27 +604,27 @@ static void igt_damage_iter_damage_not_visible(struct kunit *test) } static struct kunit_case drm_damage_helper_tests[] = { - KUNIT_CASE(igt_damage_iter_no_damage), - KUNIT_CASE(igt_damage_iter_no_damage_fractional_src), - KUNIT_CASE(igt_damage_iter_no_damage_src_moved), - KUNIT_CASE(igt_damage_iter_no_damage_fractional_src_moved), - KUNIT_CASE(igt_damage_iter_no_damage_not_visible), - KUNIT_CASE(igt_damage_iter_no_damage_no_crtc), - KUNIT_CASE(igt_damage_iter_no_damage_no_fb), - KUNIT_CASE(igt_damage_iter_simple_damage), - KUNIT_CASE(igt_damage_iter_single_damage), - KUNIT_CASE(igt_damage_iter_single_damage_intersect_src), - KUNIT_CASE(igt_damage_iter_single_damage_outside_src), - KUNIT_CASE(igt_damage_iter_single_damage_fractional_src), - KUNIT_CASE(igt_damage_iter_single_damage_intersect_fractional_src), - KUNIT_CASE(igt_damage_iter_single_damage_outside_fractional_src), - KUNIT_CASE(igt_damage_iter_single_damage_src_moved), - KUNIT_CASE(igt_damage_iter_single_damage_fractional_src_moved), - KUNIT_CASE(igt_damage_iter_damage), - KUNIT_CASE(igt_damage_iter_damage_one_intersect), - KUNIT_CASE(igt_damage_iter_damage_one_outside), - KUNIT_CASE(igt_damage_iter_damage_src_moved), - KUNIT_CASE(igt_damage_iter_damage_not_visible), + KUNIT_CASE(drm_test_damage_iter_no_damage), + KUNIT_CASE(drm_test_damage_iter_no_damage_fractional_src), + KUNIT_CASE(drm_test_damage_iter_no_damage_src_moved), + KUNIT_CASE(drm_test_damage_iter_no_damage_fractional_src_moved), + KUNIT_CASE(drm_test_damage_iter_no_damage_not_visible), + KUNIT_CASE(drm_test_damage_iter_no_damage_no_crtc), + KUNIT_CASE(drm_test_damage_iter_no_damage_no_fb), + KUNIT_CASE(drm_test_damage_iter_simple_damage), + KUNIT_CASE(drm_test_damage_iter_single_damage), + KUNIT_CASE(drm_test_damage_iter_single_damage_intersect_src), + KUNIT_CASE(drm_test_damage_iter_single_damage_outside_src), + KUNIT_CASE(drm_test_damage_iter_single_damage_fractional_src), + KUNIT_CASE(drm_test_damage_iter_single_damage_intersect_fractional_src), + KUNIT_CASE(drm_test_damage_iter_single_damage_outside_fractional_src), + KUNIT_CASE(drm_test_damage_iter_single_damage_src_moved), + KUNIT_CASE(drm_test_damage_iter_single_damage_fractional_src_moved), + KUNIT_CASE(drm_test_damage_iter_damage), + KUNIT_CASE(drm_test_damage_iter_damage_one_intersect), + KUNIT_CASE(drm_test_damage_iter_damage_one_outside), + KUNIT_CASE(drm_test_damage_iter_damage_src_moved), + KUNIT_CASE(drm_test_damage_iter_damage_not_visible), { } }; diff --git a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c index 1d2fade562273..65c9d225b5580 100644 --- a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c +++ b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c @@ -16,7 +16,7 @@ #include "../display/drm_dp_mst_topology_internal.h" -static void igt_dp_mst_calc_pbn_mode(struct kunit *test) +static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test) { int pbn, i; const struct { @@ -177,7 +177,7 @@ sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in) return result; } -static void igt_dp_mst_sideband_msg_req_decode(struct kunit *test) +static void drm_test_dp_mst_sideband_msg_req_decode(struct kunit *test) { struct drm_dp_sideband_msg_req_body in = { 0 }; u8 data[] = { 0xff, 0x0, 0xdd }; @@ -271,8 +271,8 @@ static void igt_dp_mst_sideband_msg_req_decode(struct kunit *test) } static struct kunit_case drm_dp_mst_helper_tests[] = { - KUNIT_CASE(igt_dp_mst_calc_pbn_mode), - KUNIT_CASE(igt_dp_mst_sideband_msg_req_decode), + KUNIT_CASE(drm_test_dp_mst_calc_pbn_mode), + KUNIT_CASE(drm_test_dp_mst_sideband_msg_req_decode), { } }; diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 8284870717969..ab49f5e8796c0 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -192,7 +192,7 @@ static void convert_xrgb8888_case_desc(struct convert_xrgb8888_case *t, KUNIT_ARRAY_PARAM(convert_xrgb8888, convert_xrgb8888_cases, convert_xrgb8888_case_desc); -static void xrgb8888_to_rgb332_test(struct kunit *test) +static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test) { const struct convert_xrgb8888_case *params = test->param_value; const struct convert_to_rgb332_result *result = ¶ms->rgb332_result; @@ -222,7 +222,7 @@ static void xrgb8888_to_rgb332_test(struct kunit *test) KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); } -static void xrgb8888_to_rgb565_test(struct kunit *test) +static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test) { const struct convert_xrgb8888_case *params = test->param_value; const struct convert_to_rgb565_result *result = ¶ms->rgb565_result; @@ -256,8 +256,8 @@ static void xrgb8888_to_rgb565_test(struct kunit *test) } static struct kunit_case drm_format_helper_test_cases[] = { - KUNIT_CASE_PARAM(xrgb8888_to_rgb332_test, convert_xrgb8888_gen_params), - KUNIT_CASE_PARAM(xrgb8888_to_rgb565_test, convert_xrgb8888_gen_params), + KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params), + KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb565, convert_xrgb8888_gen_params), {} }; diff --git a/drivers/gpu/drm/tests/drm_format_test.c b/drivers/gpu/drm/tests/drm_format_test.c index 1936d2d599087..ec6996ce819a3 100644 --- a/drivers/gpu/drm/tests/drm_format_test.c +++ b/drivers/gpu/drm/tests/drm_format_test.c @@ -9,7 +9,7 @@ #include -static void drm_format_block_width_invalid(struct kunit *test) +static void drm_test_format_block_width_invalid(struct kunit *test) { const struct drm_format_info *info = NULL; @@ -18,7 +18,7 @@ static void drm_format_block_width_invalid(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 1), 0); } -static void drm_format_block_width_one_plane(struct kunit *test) +static void drm_test_format_block_width_one_plane(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_XRGB4444); @@ -29,7 +29,7 @@ static void drm_format_block_width_one_plane(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); } -static void drm_format_block_width_two_plane(struct kunit *test) +static void drm_test_format_block_width_two_plane(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_NV12); @@ -41,7 +41,7 @@ static void drm_format_block_width_two_plane(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); } -static void drm_format_block_width_three_plane(struct kunit *test) +static void drm_test_format_block_width_three_plane(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_YUV422); @@ -54,7 +54,7 @@ static void drm_format_block_width_three_plane(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); } -static void drm_format_block_width_tiled(struct kunit *test) +static void drm_test_format_block_width_tiled(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_X0L0); @@ -65,7 +65,7 @@ static void drm_format_block_width_tiled(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, -1), 0); } -static void drm_format_block_height_invalid(struct kunit *test) +static void drm_test_format_block_height_invalid(struct kunit *test) { const struct drm_format_info *info = NULL; @@ -74,7 +74,7 @@ static void drm_format_block_height_invalid(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 0); } -static void drm_format_block_height_one_plane(struct kunit *test) +static void drm_test_format_block_height_one_plane(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_XRGB4444); @@ -85,7 +85,7 @@ static void drm_format_block_height_one_plane(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 1), 0); } -static void drm_format_block_height_two_plane(struct kunit *test) +static void drm_test_format_block_height_two_plane(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_NV12); @@ -97,7 +97,7 @@ static void drm_format_block_height_two_plane(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); } -static void drm_format_block_height_three_plane(struct kunit *test) +static void drm_test_format_block_height_three_plane(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_YUV422); @@ -110,7 +110,7 @@ static void drm_format_block_height_three_plane(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); } -static void drm_format_block_height_tiled(struct kunit *test) +static void drm_test_format_block_height_tiled(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_X0L0); @@ -121,7 +121,7 @@ static void drm_format_block_height_tiled(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, -1), 0); } -static void drm_format_min_pitch_invalid(struct kunit *test) +static void drm_test_format_min_pitch_invalid(struct kunit *test) { const struct drm_format_info *info = NULL; @@ -130,7 +130,7 @@ static void drm_format_min_pitch_invalid(struct kunit *test) KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 0), 0); } -static void drm_format_min_pitch_one_plane_8bpp(struct kunit *test) +static void drm_test_format_min_pitch_one_plane_8bpp(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_RGB332); @@ -153,7 +153,7 @@ static void drm_format_min_pitch_one_plane_8bpp(struct kunit *test) (uint64_t)(UINT_MAX - 1)); } -static void drm_format_min_pitch_one_plane_16bpp(struct kunit *test) +static void drm_test_format_min_pitch_one_plane_16bpp(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_XRGB4444); @@ -176,7 +176,7 @@ static void drm_format_min_pitch_one_plane_16bpp(struct kunit *test) (uint64_t)(UINT_MAX - 1) * 2); } -static void drm_format_min_pitch_one_plane_24bpp(struct kunit *test) +static void drm_test_format_min_pitch_one_plane_24bpp(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_RGB888); @@ -199,7 +199,7 @@ static void drm_format_min_pitch_one_plane_24bpp(struct kunit *test) (uint64_t)(UINT_MAX - 1) * 3); } -static void drm_format_min_pitch_one_plane_32bpp(struct kunit *test) +static void drm_test_format_min_pitch_one_plane_32bpp(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_ABGR8888); @@ -222,7 +222,7 @@ static void drm_format_min_pitch_one_plane_32bpp(struct kunit *test) (uint64_t)(UINT_MAX - 1) * 4); } -static void drm_format_min_pitch_two_plane(struct kunit *test) +static void drm_test_format_min_pitch_two_plane(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_NV12); @@ -257,7 +257,7 @@ static void drm_format_min_pitch_two_plane(struct kunit *test) (uint64_t)(UINT_MAX - 1)); } -static void drm_format_min_pitch_three_plane_8bpp(struct kunit *test) +static void drm_test_format_min_pitch_three_plane_8bpp(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_YUV422); @@ -304,7 +304,7 @@ static void drm_format_min_pitch_three_plane_8bpp(struct kunit *test) (uint64_t)(UINT_MAX - 1) / 2); } -static void drm_format_min_pitch_tiled(struct kunit *test) +static void drm_test_format_min_pitch_tiled(struct kunit *test) { const struct drm_format_info *info = drm_format_info(DRM_FORMAT_X0L2); @@ -328,24 +328,24 @@ static void drm_format_min_pitch_tiled(struct kunit *test) } static struct kunit_case drm_format_tests[] = { - KUNIT_CASE(drm_format_block_width_invalid), - KUNIT_CASE(drm_format_block_width_one_plane), - KUNIT_CASE(drm_format_block_width_two_plane), - KUNIT_CASE(drm_format_block_width_three_plane), - KUNIT_CASE(drm_format_block_width_tiled), - KUNIT_CASE(drm_format_block_height_invalid), - KUNIT_CASE(drm_format_block_height_one_plane), - KUNIT_CASE(drm_format_block_height_two_plane), - KUNIT_CASE(drm_format_block_height_three_plane), - KUNIT_CASE(drm_format_block_height_tiled), - KUNIT_CASE(drm_format_min_pitch_invalid), - KUNIT_CASE(drm_format_min_pitch_one_plane_8bpp), - KUNIT_CASE(drm_format_min_pitch_one_plane_16bpp), - KUNIT_CASE(drm_format_min_pitch_one_plane_24bpp), - KUNIT_CASE(drm_format_min_pitch_one_plane_32bpp), - KUNIT_CASE(drm_format_min_pitch_two_plane), - KUNIT_CASE(drm_format_min_pitch_three_plane_8bpp), - KUNIT_CASE(drm_format_min_pitch_tiled), + KUNIT_CASE(drm_test_format_block_width_invalid), + KUNIT_CASE(drm_test_format_block_width_one_plane), + KUNIT_CASE(drm_test_format_block_width_two_plane), + KUNIT_CASE(drm_test_format_block_width_three_plane), + KUNIT_CASE(drm_test_format_block_width_tiled), + KUNIT_CASE(drm_test_format_block_height_invalid), + KUNIT_CASE(drm_test_format_block_height_one_plane), + KUNIT_CASE(drm_test_format_block_height_two_plane), + KUNIT_CASE(drm_test_format_block_height_three_plane), + KUNIT_CASE(drm_test_format_block_height_tiled), + KUNIT_CASE(drm_test_format_min_pitch_invalid), + KUNIT_CASE(drm_test_format_min_pitch_one_plane_8bpp), + KUNIT_CASE(drm_test_format_min_pitch_one_plane_16bpp), + KUNIT_CASE(drm_test_format_min_pitch_one_plane_24bpp), + KUNIT_CASE(drm_test_format_min_pitch_one_plane_32bpp), + KUNIT_CASE(drm_test_format_min_pitch_two_plane), + KUNIT_CASE(drm_test_format_min_pitch_three_plane_8bpp), + KUNIT_CASE(drm_test_format_min_pitch_tiled), {} }; diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/drm_mm_test.c index 1e2c1aa524bd4..659d1af4dca78 100644 --- a/drivers/gpu/drm/tests/drm_mm_test.c +++ b/drivers/gpu/drm/tests/drm_mm_test.c @@ -191,7 +191,7 @@ static bool assert_node(struct kunit *test, struct drm_mm_node *node, struct drm return ok; } -static void igt_mm_init(struct kunit *test) +static void drm_test_mm_init(struct kunit *test) { const unsigned int size = 4096; struct drm_mm mm; @@ -245,7 +245,7 @@ static void igt_mm_init(struct kunit *test) drm_mm_takedown(&mm); } -static void igt_mm_debug(struct kunit *test) +static void drm_test_mm_debug(struct kunit *test) { struct drm_mm mm; struct drm_mm_node nodes[2]; @@ -341,7 +341,7 @@ static bool check_reserve_boundaries(struct kunit *test, struct drm_mm *mm, return true; } -static int __igt_reserve(struct kunit *test, unsigned int count, u64 size) +static int __drm_test_mm_reserve(struct kunit *test, unsigned int count, u64 size) { DRM_RND_STATE(prng, random_seed); struct drm_mm mm; @@ -349,7 +349,7 @@ static int __igt_reserve(struct kunit *test, unsigned int count, u64 size) unsigned int *order, n, m, o = 0; int ret, err; - /* For exercising drm_mm_reserve_node(struct kunit *test, ), we want to check that + /* For exercising drm_mm_reserve_node(), we want to check that * reservations outside of the drm_mm range are rejected, and to * overlapping and otherwise already occupied ranges. Afterwards, * the tree and nodes should be intact. @@ -463,7 +463,7 @@ static int __igt_reserve(struct kunit *test, unsigned int count, u64 size) return ret; } -static void igt_mm_reserve(struct kunit *test) +static void drm_test_mm_reserve(struct kunit *test) { const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); int n; @@ -471,9 +471,9 @@ static void igt_mm_reserve(struct kunit *test) for_each_prime_number_from(n, 1, 54) { u64 size = BIT_ULL(n); - KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size - 1)); - KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size)); - KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size + 1)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_reserve(test, count, size - 1)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_reserve(test, count, size)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_reserve(test, count, size + 1)); cond_resched(); } @@ -524,7 +524,7 @@ static bool expect_insert_fail(struct kunit *test, struct drm_mm *mm, u64 size) return false; } -static int __igt_insert(struct kunit *test, unsigned int count, u64 size, bool replace) +static int __drm_test_mm_insert(struct kunit *test, unsigned int count, u64 size, bool replace) { DRM_RND_STATE(prng, random_seed); const struct insert_mode *mode; @@ -660,7 +660,7 @@ static int __igt_insert(struct kunit *test, unsigned int count, u64 size, bool r return ret; } -static void igt_mm_insert(struct kunit *test) +static void drm_test_mm_insert(struct kunit *test) { const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); unsigned int n; @@ -668,20 +668,20 @@ static void igt_mm_insert(struct kunit *test) for_each_prime_number_from(n, 1, 54) { u64 size = BIT_ULL(n); - KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size - 1, false)); - KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size, false)); - KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size + 1, false)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert(test, count, size - 1, false)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert(test, count, size, false)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert(test, count, size + 1, false)); cond_resched(); } } -static void igt_mm_replace(struct kunit *test) +static void drm_test_mm_replace(struct kunit *test) { const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); unsigned int n; - /* Reuse igt_insert to exercise replacement by inserting a dummy node, + /* Reuse __drm_test_mm_insert to exercise replacement by inserting a dummy node, * then replacing it with the intended node. We want to check that * the tree is intact and all the information we need is carried * across to the target node. @@ -690,9 +690,9 @@ static void igt_mm_replace(struct kunit *test) for_each_prime_number_from(n, 1, 54) { u64 size = BIT_ULL(n); - KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size - 1, true)); - KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size, true)); - KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size + 1, true)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert(test, count, size - 1, true)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert(test, count, size, true)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert(test, count, size + 1, true)); cond_resched(); } @@ -808,7 +808,8 @@ static bool assert_contiguous_in_range(struct kunit *test, struct drm_mm *mm, return true; } -static int __igt_insert_range(struct kunit *test, unsigned int count, u64 size, u64 start, u64 end) +static int __drm_test_mm_insert_range(struct kunit *test, unsigned int count, u64 size, + u64 start, u64 end) { const struct insert_mode *mode; struct drm_mm mm; @@ -820,7 +821,7 @@ static int __igt_insert_range(struct kunit *test, unsigned int count, u64 size, DRM_MM_BUG_ON(!size); DRM_MM_BUG_ON(end <= start); - /* Very similar to __igt_insert(struct kunit *test, ), but now instead of populating the + /* Very similar to __drm_test_mm_insert(), but now instead of populating the * full range of the drm_mm, we try to fill a small portion of it. */ @@ -921,7 +922,7 @@ static int insert_outside_range(struct kunit *test) return 0; } -static void igt_mm_insert_range(struct kunit *test) +static void drm_test_mm_insert_range(struct kunit *test) { const unsigned int count = min_t(unsigned int, BIT(13), max_iterations); unsigned int n; @@ -933,21 +934,21 @@ static void igt_mm_insert_range(struct kunit *test) const u64 size = BIT_ULL(n); const u64 max = count * size; - KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max)); - KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 1, max)); - KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max - 1)); - KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max / 2)); - KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, max / 2, max / 2)); - KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, - max / 4 + 1, 3 * max / 4 - 1)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, 0, max)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, 1, max)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, 0, max - 1)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, 0, max / 2)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, + max / 2, max / 2)); + KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, + max / 4 + 1, 3 * max / 4 - 1)); cond_resched(); } } -static int prepare_igt_frag(struct kunit *test, struct drm_mm *mm, - struct drm_mm_node *nodes, unsigned int num_insert, - const struct insert_mode *mode) +static int prepare_frag(struct kunit *test, struct drm_mm *mm, struct drm_mm_node *nodes, + unsigned int num_insert, const struct insert_mode *mode) { unsigned int size = 4096; unsigned int i; @@ -987,7 +988,7 @@ static u64 get_insert_time(struct kunit *test, struct drm_mm *mm, return ktime_to_ns(ktime_sub(ktime_get(), start)); } -static void igt_mm_frag(struct kunit *test) +static void drm_test_mm_frag(struct kunit *test) { struct drm_mm mm; const struct insert_mode *mode; @@ -997,15 +998,15 @@ static void igt_mm_frag(struct kunit *test) /* We need 4 * insert_size nodes to hold intermediate allocated * drm_mm nodes. - * 1 times for prepare_igt_frag(struct kunit *test, ) - * 1 times for get_insert_time(struct kunit *test, ) - * 2 times for get_insert_time(struct kunit *test, ) + * 1 times for prepare_frag() + * 1 times for get_insert_time() + * 2 times for get_insert_time() */ nodes = vzalloc(array_size(insert_size * 4, sizeof(*nodes))); KUNIT_ASSERT_TRUE(test, nodes); /* For BOTTOMUP and TOPDOWN, we first fragment the - * address space using prepare_igt_frag(struct kunit *test, ) and then try to verify + * address space using prepare_frag() and then try to verify * that insertions scale quadratically from 10k to 20k insertions */ drm_mm_init(&mm, 1, U64_MAX - 2); @@ -1016,7 +1017,7 @@ static void igt_mm_frag(struct kunit *test) mode->mode != DRM_MM_INSERT_HIGH) continue; - if (prepare_igt_frag(test, &mm, nodes, insert_size, mode)) + if (prepare_frag(test, &mm, nodes, insert_size, mode)) goto err; insert_time1 = get_insert_time(test, &mm, insert_size, @@ -1049,7 +1050,7 @@ static void igt_mm_frag(struct kunit *test) vfree(nodes); } -static void igt_mm_align(struct kunit *test) +static void drm_test_mm_align(struct kunit *test) { const struct insert_mode *mode; const unsigned int max_count = min(8192u, max_prime); @@ -1096,7 +1097,7 @@ static void igt_mm_align(struct kunit *test) vfree(nodes); } -static void igt_align_pot(struct kunit *test, int max) +static void drm_test_mm_align_pot(struct kunit *test, int max) { struct drm_mm mm; struct drm_mm_node *node, *next; @@ -1133,14 +1134,14 @@ static void igt_align_pot(struct kunit *test, int max) drm_mm_takedown(&mm); } -static void igt_mm_align32(struct kunit *test) +static void drm_test_mm_align32(struct kunit *test) { - igt_align_pot(test, 32); + drm_test_mm_align_pot(test, 32); } -static void igt_mm_align64(struct kunit *test) +static void drm_test_mm_align64(struct kunit *test) { - igt_align_pot(test, 64); + drm_test_mm_align_pot(test, 64); } static void show_scan(struct kunit *test, const struct drm_mm_scan *scan) @@ -1386,7 +1387,7 @@ static int evict_something(struct kunit *test, struct drm_mm *mm, return 0; } -static void igt_mm_evict(struct kunit *test) +static void drm_test_mm_evict(struct kunit *test) { DRM_RND_STATE(prng, random_seed); const unsigned int size = 8192; @@ -1477,7 +1478,7 @@ static void igt_mm_evict(struct kunit *test) vfree(nodes); } -static void igt_mm_evict_range(struct kunit *test) +static void drm_test_mm_evict_range(struct kunit *test) { DRM_RND_STATE(prng, random_seed); const unsigned int size = 8192; @@ -1490,7 +1491,7 @@ static void igt_mm_evict_range(struct kunit *test) struct drm_mm_node *node, *next; unsigned int *order, n; - /* Like igt_evict() but now we are limiting the search to a + /* Like drm_test_mm_evict() but now we are limiting the search to a * small portion of the full drm_mm. */ @@ -1564,7 +1565,7 @@ static unsigned int node_index(const struct drm_mm_node *node) return div64_u64(node->start, node->size); } -static void igt_mm_topdown(struct kunit *test) +static void drm_test_mm_topdown(struct kunit *test) { const struct insert_mode *topdown = &insert_modes[TOPDOWN]; @@ -1671,7 +1672,7 @@ static void igt_mm_topdown(struct kunit *test) vfree(nodes); } -static void igt_mm_bottomup(struct kunit *test) +static void drm_test_mm_bottomup(struct kunit *test) { const struct insert_mode *bottomup = &insert_modes[BOTTOMUP]; @@ -1683,7 +1684,7 @@ static void igt_mm_bottomup(struct kunit *test) struct drm_mm_node *nodes, *node, *next; unsigned int *order, n, m, o = 0; - /* Like igt_topdown, but instead of searching for the last hole, + /* Like drm_test_mm_topdown, but instead of searching for the last hole, * we search for the first. */ @@ -1763,7 +1764,7 @@ static void igt_mm_bottomup(struct kunit *test) vfree(nodes); } -static void __igt_once(struct kunit *test, unsigned int mode) +static void drm_test_mm_once(struct kunit *test, unsigned int mode) { struct drm_mm mm; struct drm_mm_node rsvd_lo, rsvd_hi, node; @@ -1806,14 +1807,14 @@ static void __igt_once(struct kunit *test, unsigned int mode) drm_mm_takedown(&mm); } -static void igt_mm_lowest(struct kunit *test) +static void drm_test_mm_lowest(struct kunit *test) { - __igt_once(test, DRM_MM_INSERT_LOW); + drm_test_mm_once(test, DRM_MM_INSERT_LOW); } -static void igt_mm_highest(struct kunit *test) +static void drm_test_mm_highest(struct kunit *test) { - __igt_once(test, DRM_MM_INSERT_HIGH); + drm_test_mm_once(test, DRM_MM_INSERT_HIGH); } static void separate_adjacent_colors(const struct drm_mm_node *node, @@ -1842,7 +1843,7 @@ static bool colors_abutt(struct kunit *test, const struct drm_mm_node *node) return false; } -static void igt_mm_color(struct kunit *test) +static void drm_test_mm_color(struct kunit *test) { const unsigned int count = min(4096u, max_iterations); const struct insert_mode *mode; @@ -2041,7 +2042,7 @@ static int evict_color(struct kunit *test, struct drm_mm *mm, u64 range_start, return 0; } -static void igt_mm_color_evict(struct kunit *test) +static void drm_test_mm_color_evict(struct kunit *test) { DRM_RND_STATE(prng, random_seed); const unsigned int total_size = min(8192u, max_iterations); @@ -2122,7 +2123,7 @@ static void igt_mm_color_evict(struct kunit *test) vfree(nodes); } -static void igt_mm_color_evict_range(struct kunit *test) +static void drm_test_mm_color_evict_range(struct kunit *test) { DRM_RND_STATE(prng, random_seed); const unsigned int total_size = 8192; @@ -2136,7 +2137,7 @@ static void igt_mm_color_evict_range(struct kunit *test) struct drm_mm_node *node, *next; unsigned int *order, n; - /* Like igt_color_evict(), but limited to small portion of the full + /* Like drm_test_mm_color_evict(), but limited to small portion of the full * drm_mm range. */ @@ -2221,25 +2222,25 @@ module_param(max_iterations, uint, 0400); module_param(max_prime, uint, 0400); static struct kunit_case drm_mm_tests[] = { - KUNIT_CASE(igt_mm_init), - KUNIT_CASE(igt_mm_debug), - KUNIT_CASE(igt_mm_reserve), - KUNIT_CASE(igt_mm_insert), - KUNIT_CASE(igt_mm_replace), - KUNIT_CASE(igt_mm_insert_range), - KUNIT_CASE(igt_mm_frag), - KUNIT_CASE(igt_mm_align), - KUNIT_CASE(igt_mm_align32), - KUNIT_CASE(igt_mm_align64), - KUNIT_CASE(igt_mm_evict), - KUNIT_CASE(igt_mm_evict_range), - KUNIT_CASE(igt_mm_topdown), - KUNIT_CASE(igt_mm_bottomup), - KUNIT_CASE(igt_mm_lowest), - KUNIT_CASE(igt_mm_highest), - KUNIT_CASE(igt_mm_color), - KUNIT_CASE(igt_mm_color_evict), - KUNIT_CASE(igt_mm_color_evict_range), + KUNIT_CASE(drm_test_mm_init), + KUNIT_CASE(drm_test_mm_debug), + KUNIT_CASE(drm_test_mm_reserve), + KUNIT_CASE(drm_test_mm_insert), + KUNIT_CASE(drm_test_mm_replace), + KUNIT_CASE(drm_test_mm_insert_range), + KUNIT_CASE(drm_test_mm_frag), + KUNIT_CASE(drm_test_mm_align), + KUNIT_CASE(drm_test_mm_align32), + KUNIT_CASE(drm_test_mm_align64), + KUNIT_CASE(drm_test_mm_evict), + KUNIT_CASE(drm_test_mm_evict_range), + KUNIT_CASE(drm_test_mm_topdown), + KUNIT_CASE(drm_test_mm_bottomup), + KUNIT_CASE(drm_test_mm_lowest), + KUNIT_CASE(drm_test_mm_highest), + KUNIT_CASE(drm_test_mm_color), + KUNIT_CASE(drm_test_mm_color_evict), + KUNIT_CASE(drm_test_mm_color_evict_range), {} }; diff --git a/drivers/gpu/drm/tests/drm_plane_helper_test.c b/drivers/gpu/drm/tests/drm_plane_helper_test.c index be6cff0020edf..ec71af791f1fd 100644 --- a/drivers/gpu/drm/tests/drm_plane_helper_test.c +++ b/drivers/gpu/drm/tests/drm_plane_helper_test.c @@ -73,7 +73,7 @@ static bool check_crtc_eq(struct drm_plane_state *plane_state, return true; } -static void igt_check_plane_state(struct kunit *test) +static void drm_test_check_plane_state(struct kunit *test) { int ret; @@ -223,7 +223,7 @@ static void igt_check_plane_state(struct kunit *test) } static struct kunit_case drm_plane_helper_test[] = { - KUNIT_CASE(igt_check_plane_state), + KUNIT_CASE(drm_test_check_plane_state), {} }; diff --git a/drivers/gpu/drm/tests/drm_rect_test.c b/drivers/gpu/drm/tests/drm_rect_test.c index c1dbefd49a4cb..e9809ea326968 100644 --- a/drivers/gpu/drm/tests/drm_rect_test.c +++ b/drivers/gpu/drm/tests/drm_rect_test.c @@ -9,7 +9,7 @@ #include -static void igt_drm_rect_clip_scaled_div_by_zero(struct kunit *test) +static void drm_test_rect_clip_scaled_div_by_zero(struct kunit *test) { struct drm_rect src, dst, clip; bool visible; @@ -35,7 +35,7 @@ static void igt_drm_rect_clip_scaled_div_by_zero(struct kunit *test) KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n"); } -static void igt_drm_rect_clip_scaled_not_clipped(struct kunit *test) +static void drm_test_rect_clip_scaled_not_clipped(struct kunit *test) { struct drm_rect src, dst, clip; bool visible; @@ -83,7 +83,7 @@ static void igt_drm_rect_clip_scaled_not_clipped(struct kunit *test) KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); } -static void igt_drm_rect_clip_scaled_clipped(struct kunit *test) +static void drm_test_rect_clip_scaled_clipped(struct kunit *test) { struct drm_rect src, dst, clip; bool visible; @@ -173,7 +173,7 @@ static void igt_drm_rect_clip_scaled_clipped(struct kunit *test) KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); } -static void igt_drm_rect_clip_scaled_signed_vs_unsigned(struct kunit *test) +static void drm_test_rect_clip_scaled_signed_vs_unsigned(struct kunit *test) { struct drm_rect src, dst, clip; bool visible; @@ -197,10 +197,10 @@ static void igt_drm_rect_clip_scaled_signed_vs_unsigned(struct kunit *test) } static struct kunit_case drm_rect_tests[] = { - KUNIT_CASE(igt_drm_rect_clip_scaled_div_by_zero), - KUNIT_CASE(igt_drm_rect_clip_scaled_not_clipped), - KUNIT_CASE(igt_drm_rect_clip_scaled_clipped), - KUNIT_CASE(igt_drm_rect_clip_scaled_signed_vs_unsigned), + KUNIT_CASE(drm_test_rect_clip_scaled_div_by_zero), + KUNIT_CASE(drm_test_rect_clip_scaled_not_clipped), + KUNIT_CASE(drm_test_rect_clip_scaled_clipped), + KUNIT_CASE(drm_test_rect_clip_scaled_signed_vs_unsigned), { } }; From 3ba000d6ae999b99f29afd64814877a5c4406786 Mon Sep 17 00:00:00 2001 From: Hugh Cole-Baker Date: Tue, 19 Oct 2021 22:58:41 +0100 Subject: [PATCH 080/119] drm/rockchip: define gamma registers for RK3399 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VOP on RK3399 has a different approach from previous versions for setting a gamma lookup table, using an update_gamma_lut register. As this differs from RK3288, give RK3399 its own set of "common" register definitions. Signed-off-by: Hugh Cole-Baker Tested-by: "Milan P. Stanić" Tested-by: Linus Heckemann Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20211019215843.42718-2-sigmaris@gmail.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 2 ++ drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 24 +++++++++++++++++++-- drivers/gpu/drm/rockchip/rockchip_vop_reg.h | 1 + 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index ba88addc1a754..8502849833d93 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -113,6 +113,8 @@ struct vop_common { struct vop_reg dither_down_en; struct vop_reg dither_up; struct vop_reg dsp_lut_en; + struct vop_reg update_gamma_lut; + struct vop_reg lut_buffer_index; struct vop_reg gate_en; struct vop_reg mmu_en; struct vop_reg out_mode; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index d03dd04029234..014f99e8928e3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -875,6 +875,24 @@ static const struct vop_output rk3399_output = { .mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3), }; +static const struct vop_common rk3399_common = { + .standby = VOP_REG_SYNC(RK3399_SYS_CTRL, 0x1, 22), + .gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23), + .mmu_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 20), + .dither_down_sel = VOP_REG(RK3399_DSP_CTRL1, 0x1, 4), + .dither_down_mode = VOP_REG(RK3399_DSP_CTRL1, 0x1, 3), + .dither_down_en = VOP_REG(RK3399_DSP_CTRL1, 0x1, 2), + .pre_dither_down = VOP_REG(RK3399_DSP_CTRL1, 0x1, 1), + .dither_up = VOP_REG(RK3399_DSP_CTRL1, 0x1, 6), + .dsp_lut_en = VOP_REG(RK3399_DSP_CTRL1, 0x1, 0), + .update_gamma_lut = VOP_REG(RK3399_DSP_CTRL1, 0x1, 7), + .lut_buffer_index = VOP_REG(RK3399_DBG_POST_REG1, 0x1, 1), + .data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19), + .dsp_blank = VOP_REG(RK3399_DSP_CTRL0, 0x3, 18), + .out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0), + .cfg_done = VOP_REG_SYNC(RK3399_REG_CFG_DONE, 0x1, 0), +}; + static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = { .y2r_coefficients = { VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0), @@ -957,7 +975,7 @@ static const struct vop_data rk3399_vop_big = { .version = VOP_VERSION(3, 5), .feature = VOP_FEATURE_OUTPUT_RGB10, .intr = &rk3366_vop_intr, - .common = &rk3288_common, + .common = &rk3399_common, .modeset = &rk3288_modeset, .output = &rk3399_output, .afbc = &rk3399_vop_afbc, @@ -965,6 +983,7 @@ static const struct vop_data rk3399_vop_big = { .win = rk3399_vop_win_data, .win_size = ARRAY_SIZE(rk3399_vop_win_data), .win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data, + .lut_size = 1024, }; static const struct vop_win_data rk3399_vop_lit_win_data[] = { @@ -983,13 +1002,14 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = { static const struct vop_data rk3399_vop_lit = { .version = VOP_VERSION(3, 6), .intr = &rk3366_vop_intr, - .common = &rk3288_common, + .common = &rk3399_common, .modeset = &rk3288_modeset, .output = &rk3399_output, .misc = &rk3368_misc, .win = rk3399_vop_lit_win_data, .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data), .win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data, + .lut_size = 256, }; static const struct vop_win_data rk3228_vop_win_data[] = { diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index 0b3cd65ba5c1b..406e981c75bd7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -628,6 +628,7 @@ #define RK3399_YUV2YUV_WIN 0x02c0 #define RK3399_YUV2YUV_POST 0x02c4 #define RK3399_AUTO_GATING_EN 0x02cc +#define RK3399_DBG_POST_REG1 0x036c #define RK3399_WIN0_CSC_COE 0x03a0 #define RK3399_WIN1_CSC_COE 0x03c0 #define RK3399_WIN2_CSC_COE 0x03e0 From 7ae7a6211fe7251543796d5af971acb8c9e2da9e Mon Sep 17 00:00:00 2001 From: Hugh Cole-Baker Date: Tue, 19 Oct 2021 22:58:42 +0100 Subject: [PATCH 081/119] drm/rockchip: support gamma control on RK3399 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RK3399 has a 1024-entry gamma LUT with 10 bits per component on its "big" VOP and a 256-entry, 8 bit per component LUT on the "little" VOP. Compared to the RK3288, it no longer requires disabling gamma while updating the LUT. On the RK3399, the LUT can be updated at any time as the hardware has two LUT buffers, one can be written while the other is in use. A swap of the buffers is triggered by writing 1 to the update_gamma_lut register. Signed-off-by: Hugh Cole-Baker Tested-by: "Milan P. Stanić" Tested-by: Linus Heckemann Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20211019215843.42718-3-sigmaris@gmail.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 105 +++++++++++++------- 1 file changed, 71 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index fab7109109977..6ca831d221ec0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,9 @@ #define VOP_REG_SET(vop, group, name, v) \ vop_reg_set(vop, &vop->data->group->name, 0, ~0, v, #name) +#define VOP_HAS_REG(vop, group, name) \ + (!!(vop->data->group->name.mask)) + #define VOP_INTR_SET_TYPE(vop, name, type, v) \ do { \ int i, reg = 0, mask = 0; \ @@ -1223,17 +1227,22 @@ static bool vop_dsp_lut_is_enabled(struct vop *vop) return vop_read_reg(vop, 0, &vop->data->common->dsp_lut_en); } +static u32 vop_lut_buffer_index(struct vop *vop) +{ + return vop_read_reg(vop, 0, &vop->data->common->lut_buffer_index); +} + static void vop_crtc_write_gamma_lut(struct vop *vop, struct drm_crtc *crtc) { struct drm_color_lut *lut = crtc->state->gamma_lut->data; - unsigned int i; + unsigned int i, bpc = ilog2(vop->data->lut_size); for (i = 0; i < crtc->gamma_size; i++) { u32 word; - word = (drm_color_lut_extract(lut[i].red, 10) << 20) | - (drm_color_lut_extract(lut[i].green, 10) << 10) | - drm_color_lut_extract(lut[i].blue, 10); + word = (drm_color_lut_extract(lut[i].red, bpc) << (2 * bpc)) | + (drm_color_lut_extract(lut[i].green, bpc) << bpc) | + drm_color_lut_extract(lut[i].blue, bpc); writel(word, vop->lut_regs + i * 4); } } @@ -1243,38 +1252,66 @@ static void vop_crtc_gamma_set(struct vop *vop, struct drm_crtc *crtc, { struct drm_crtc_state *state = crtc->state; unsigned int idle; + u32 lut_idx, old_idx; int ret; if (!vop->lut_regs) return; - /* - * To disable gamma (gamma_lut is null) or to write - * an update to the LUT, clear dsp_lut_en. - */ - spin_lock(&vop->reg_lock); - VOP_REG_SET(vop, common, dsp_lut_en, 0); - vop_cfg_done(vop); - spin_unlock(&vop->reg_lock); - /* - * In order to write the LUT to the internal memory, - * we need to first make sure the dsp_lut_en bit is cleared. - */ - ret = readx_poll_timeout(vop_dsp_lut_is_enabled, vop, - idle, !idle, 5, 30 * 1000); - if (ret) { - DRM_DEV_ERROR(vop->dev, "display LUT RAM enable timeout!\n"); - return; - } + if (!state->gamma_lut || !VOP_HAS_REG(vop, common, update_gamma_lut)) { + /* + * To disable gamma (gamma_lut is null) or to write + * an update to the LUT, clear dsp_lut_en. + */ + spin_lock(&vop->reg_lock); + VOP_REG_SET(vop, common, dsp_lut_en, 0); + vop_cfg_done(vop); + spin_unlock(&vop->reg_lock); - if (!state->gamma_lut) - return; + /* + * In order to write the LUT to the internal memory, + * we need to first make sure the dsp_lut_en bit is cleared. + */ + ret = readx_poll_timeout(vop_dsp_lut_is_enabled, vop, + idle, !idle, 5, 30 * 1000); + if (ret) { + DRM_DEV_ERROR(vop->dev, "display LUT RAM enable timeout!\n"); + return; + } + + if (!state->gamma_lut) + return; + } else { + /* + * On RK3399 the gamma LUT can updated without clearing dsp_lut_en, + * by setting update_gamma_lut then waiting for lut_buffer_index change + */ + old_idx = vop_lut_buffer_index(vop); + } spin_lock(&vop->reg_lock); vop_crtc_write_gamma_lut(vop, crtc); VOP_REG_SET(vop, common, dsp_lut_en, 1); + VOP_REG_SET(vop, common, update_gamma_lut, 1); vop_cfg_done(vop); spin_unlock(&vop->reg_lock); + + if (VOP_HAS_REG(vop, common, update_gamma_lut)) { + ret = readx_poll_timeout(vop_lut_buffer_index, vop, + lut_idx, lut_idx != old_idx, 5, 30 * 1000); + if (ret) { + DRM_DEV_ERROR(vop->dev, "gamma LUT update timeout!\n"); + return; + } + + /* + * update_gamma_lut is auto cleared by HW, but write 0 to clear the bit + * in our backup of the regs. + */ + spin_lock(&vop->reg_lock); + VOP_REG_SET(vop, common, update_gamma_lut, 0); + spin_unlock(&vop->reg_lock); + } } static void vop_crtc_atomic_begin(struct drm_crtc *crtc, @@ -1324,14 +1361,6 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, return; } - /* - * If we have a GAMMA LUT in the state, then let's make sure - * it's updated. We might be coming out of suspend, - * which means the LUT internal memory needs to be re-written. - */ - if (crtc->state->gamma_lut) - vop_crtc_gamma_set(vop, crtc, old_state); - mutex_lock(&vop->vop_lock); WARN_ON(vop->event); @@ -1422,6 +1451,14 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, VOP_REG_SET(vop, common, standby, 0); mutex_unlock(&vop->vop_lock); + + /* + * If we have a GAMMA LUT in the state, then let's make sure + * it's updated. We might be coming out of suspend, + * which means the LUT internal memory needs to be re-written. + */ + if (crtc->state->gamma_lut) + vop_crtc_gamma_set(vop, crtc, old_state); } static bool vop_fs_irq_is_pending(struct vop *vop) @@ -2147,8 +2184,8 @@ static int vop_bind(struct device *dev, struct device *master, void *data) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res) { - if (!vop_data->lut_size) { - DRM_DEV_ERROR(dev, "no gamma LUT size defined\n"); + if (vop_data->lut_size != 1024 && vop_data->lut_size != 256) { + DRM_DEV_ERROR(dev, "unsupported gamma LUT size %d\n", vop_data->lut_size); return -EINVAL; } vop->lut_regs = devm_ioremap_resource(dev, res); From 98a65e6d498c46b0beec7a40aac4b3e404642993 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sat, 21 May 2022 15:07:16 -0400 Subject: [PATCH 082/119] drm/rockchip: remove vop_writel from vop1 driver cppcheck reports [drivers/gpu/drm/rockchip/rockchip_drm_vop.c:186]: (style) The function 'vop_writel' is never used. vop_writel is static function that is not used, so remove it. Signed-off-by: Tom Rix Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20220521190716.1936193-1-trix@redhat.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 6ca831d221ec0..c356de5dd2206 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -188,12 +188,6 @@ struct vop { struct vop_win win[]; }; -static inline void vop_writel(struct vop *vop, uint32_t offset, uint32_t v) -{ - writel(v, vop->regs + offset); - vop->regsbak[offset >> 2] = v; -} - static inline uint32_t vop_readl(struct vop *vop, uint32_t offset) { return readl(vop->regs + offset); From 6ad9aa476ce23be45de9dcb03edcdbfdf6117c25 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 14 Sep 2022 22:13:16 +0530 Subject: [PATCH 083/119] dma-buf: Remove the signaled bit status check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the signaled bit status check because it is returning early when the fence is already signaled and __dma_fence_enable_signaling is checking the status of signaled bit again. Signed-off-by: Arvind Yadav Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20220914164321.2156-2-Arvind.Yadav@amd.com Signed-off-by: Christian König --- drivers/dma-buf/dma-fence.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 066400ed8841f..64c99739ad232 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -601,9 +601,6 @@ void dma_fence_enable_sw_signaling(struct dma_fence *fence) { unsigned long flags; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - return; - spin_lock_irqsave(fence->lock, flags); __dma_fence_enable_signaling(fence); spin_unlock_irqrestore(fence->lock, flags); From c85d00d4fd8b98ea4d16817f397a4de5e177afd6 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 14 Sep 2022 22:13:17 +0530 Subject: [PATCH 084/119] dma-buf: set signaling bit for the stub fence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Here's setting software signaling bit for the stub fence which is always signaled. If this fence signaling bit is not set then the AMD GPU scheduler will cause a GPU reset due to a GPU scheduler cleanup activity timeout. Signed-off-by: Arvind Yadav Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20220914164321.2156-3-Arvind.Yadav@amd.com Signed-off-by: Christian König --- drivers/dma-buf/dma-fence.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 64c99739ad232..645c158b7e01b 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -136,6 +136,10 @@ struct dma_fence *dma_fence_get_stub(void) &dma_fence_stub_ops, &dma_fence_stub_lock, 0, 0); + + set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, + &dma_fence_stub.flags); + dma_fence_signal_locked(&dma_fence_stub); } spin_unlock(&dma_fence_stub_lock); @@ -161,6 +165,10 @@ struct dma_fence *dma_fence_allocate_private_stub(void) &dma_fence_stub_ops, &dma_fence_stub_lock, 0, 0); + + set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, + &dma_fence_stub.flags); + dma_fence_signal(fence); return fence; From d62c43a953ce02d54521ec06217d0c2ed6d489af Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 14 Sep 2022 22:13:18 +0530 Subject: [PATCH 085/119] dma-buf: Enable signaling on fence for selftests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Here's enabling software signaling on fence for selftest. Signed-off-by: Arvind Yadav Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20220914164321.2156-4-Arvind.Yadav@amd.com Signed-off-by: Christian König --- drivers/dma-buf/st-dma-fence-chain.c | 4 ++++ drivers/dma-buf/st-dma-fence-unwrap.c | 22 ++++++++++++++++++++++ drivers/dma-buf/st-dma-fence.c | 16 ++++++++++++++++ drivers/dma-buf/st-dma-resv.c | 10 ++++++++++ 4 files changed, 52 insertions(+) diff --git a/drivers/dma-buf/st-dma-fence-chain.c b/drivers/dma-buf/st-dma-fence-chain.c index 8ce1ea59d31b5..0a9b099d05187 100644 --- a/drivers/dma-buf/st-dma-fence-chain.c +++ b/drivers/dma-buf/st-dma-fence-chain.c @@ -87,6 +87,8 @@ static int sanitycheck(void *arg) if (!chain) err = -ENOMEM; + dma_fence_enable_sw_signaling(chain); + dma_fence_signal(f); dma_fence_put(f); @@ -143,6 +145,8 @@ static int fence_chains_init(struct fence_chains *fc, unsigned int count, } fc->tail = fc->chains[i]; + + dma_fence_enable_sw_signaling(fc->chains[i]); } fc->chain_length = i; diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c b/drivers/dma-buf/st-dma-fence-unwrap.c index 4105d5ea8ddeb..f0cee984b6c74 100644 --- a/drivers/dma-buf/st-dma-fence-unwrap.c +++ b/drivers/dma-buf/st-dma-fence-unwrap.c @@ -102,6 +102,8 @@ static int sanitycheck(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + array = mock_array(1, f); if (!array) return -ENOMEM; @@ -124,12 +126,16 @@ static int unwrap_array(void *arg) if (!f1) return -ENOMEM; + dma_fence_enable_sw_signaling(f1); + f2 = mock_fence(); if (!f2) { dma_fence_put(f1); return -ENOMEM; } + dma_fence_enable_sw_signaling(f2); + array = mock_array(2, f1, f2); if (!array) return -ENOMEM; @@ -164,12 +170,16 @@ static int unwrap_chain(void *arg) if (!f1) return -ENOMEM; + dma_fence_enable_sw_signaling(f1); + f2 = mock_fence(); if (!f2) { dma_fence_put(f1); return -ENOMEM; } + dma_fence_enable_sw_signaling(f2); + chain = mock_chain(f1, f2); if (!chain) return -ENOMEM; @@ -204,12 +214,16 @@ static int unwrap_chain_array(void *arg) if (!f1) return -ENOMEM; + dma_fence_enable_sw_signaling(f1); + f2 = mock_fence(); if (!f2) { dma_fence_put(f1); return -ENOMEM; } + dma_fence_enable_sw_signaling(f2); + array = mock_array(2, f1, f2); if (!array) return -ENOMEM; @@ -248,12 +262,16 @@ static int unwrap_merge(void *arg) if (!f1) return -ENOMEM; + dma_fence_enable_sw_signaling(f1); + f2 = mock_fence(); if (!f2) { err = -ENOMEM; goto error_put_f1; } + dma_fence_enable_sw_signaling(f2); + f3 = dma_fence_unwrap_merge(f1, f2); if (!f3) { err = -ENOMEM; @@ -296,10 +314,14 @@ static int unwrap_merge_complex(void *arg) if (!f1) return -ENOMEM; + dma_fence_enable_sw_signaling(f1); + f2 = mock_fence(); if (!f2) goto error_put_f1; + dma_fence_enable_sw_signaling(f2); + f3 = dma_fence_unwrap_merge(f1, f2); if (!f3) goto error_put_f2; diff --git a/drivers/dma-buf/st-dma-fence.c b/drivers/dma-buf/st-dma-fence.c index c8a12d7ad71ab..fb6e0a6ae2c96 100644 --- a/drivers/dma-buf/st-dma-fence.c +++ b/drivers/dma-buf/st-dma-fence.c @@ -102,6 +102,8 @@ static int sanitycheck(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + dma_fence_signal(f); dma_fence_put(f); @@ -117,6 +119,8 @@ static int test_signaling(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + if (dma_fence_is_signaled(f)) { pr_err("Fence unexpectedly signaled on creation\n"); goto err_free; @@ -190,6 +194,8 @@ static int test_late_add_callback(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + dma_fence_signal(f); if (!dma_fence_add_callback(f, &cb.cb, simple_callback)) { @@ -282,6 +288,8 @@ static int test_status(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + if (dma_fence_get_status(f)) { pr_err("Fence unexpectedly has signaled status on creation\n"); goto err_free; @@ -308,6 +316,8 @@ static int test_error(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + dma_fence_set_error(f, -EIO); if (dma_fence_get_status(f)) { @@ -337,6 +347,8 @@ static int test_wait(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + if (dma_fence_wait_timeout(f, false, 0) != -ETIME) { pr_err("Wait reported complete before being signaled\n"); goto err_free; @@ -379,6 +391,8 @@ static int test_wait_timeout(void *arg) if (!wt.f) return -ENOMEM; + dma_fence_enable_sw_signaling(wt.f); + if (dma_fence_wait_timeout(wt.f, false, 1) != -ETIME) { pr_err("Wait reported complete before being signaled\n"); goto err_free; @@ -458,6 +472,8 @@ static int thread_signal_callback(void *arg) break; } + dma_fence_enable_sw_signaling(f1); + rcu_assign_pointer(t->fences[t->id], f1); smp_wmb(); diff --git a/drivers/dma-buf/st-dma-resv.c b/drivers/dma-buf/st-dma-resv.c index 813779e3c9be5..15dbea1462ed4 100644 --- a/drivers/dma-buf/st-dma-resv.c +++ b/drivers/dma-buf/st-dma-resv.c @@ -45,6 +45,8 @@ static int sanitycheck(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + dma_fence_signal(f); dma_fence_put(f); @@ -69,6 +71,8 @@ static int test_signaling(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + dma_resv_init(&resv); r = dma_resv_lock(&resv, NULL); if (r) { @@ -114,6 +118,8 @@ static int test_for_each(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + dma_resv_init(&resv); r = dma_resv_lock(&resv, NULL); if (r) { @@ -173,6 +179,8 @@ static int test_for_each_unlocked(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + dma_resv_init(&resv); r = dma_resv_lock(&resv, NULL); if (r) { @@ -244,6 +252,8 @@ static int test_get_fences(void *arg) if (!f) return -ENOMEM; + dma_fence_enable_sw_signaling(f); + dma_resv_init(&resv); r = dma_resv_lock(&resv, NULL); if (r) { From b96fb1e724ae6839d5bffcf42dd3503db7cc7df5 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 14 Sep 2022 22:13:19 +0530 Subject: [PATCH 086/119] dma-buf: dma_fence_wait must enable signaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_fence_wait() should always enable signaling even when the fence is already signaled. Signed-off-by: Arvind Yadav Link: https://patchwork.freedesktop.org/patch/msgid/20220914164321.2156-5-Arvind.Yadav@amd.com Signed-off-by: Christian König --- drivers/dma-buf/dma-fence.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 645c158b7e01b..a5fbf1c1e0ea2 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -508,6 +508,8 @@ dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout) __dma_fence_might_wait(); + dma_fence_enable_sw_signaling(fence); + trace_dma_fence_wait_start(fence); if (fence->ops->wait) ret = fence->ops->wait(fence, intr, timeout); @@ -771,9 +773,6 @@ dma_fence_default_wait(struct dma_fence *fence, bool intr, signed long timeout) goto out; } - if (!__dma_fence_enable_signaling(fence)) - goto out; - if (!timeout) { ret = 0; goto out; From e4dc45b1848bc6bcac31eb1b4ccdd7f6718b3c86 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 14 Sep 2022 22:13:20 +0530 Subject: [PATCH 087/119] drm/sched: Use parent fence instead of finished MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the parent fence instead of the finished fence to get the job status. This change is to avoid GPU scheduler timeout error which can cause GPU reset. Signed-off-by: Arvind Yadav Reviewed-by: Andrey Grodzovsky Link: https://patchwork.freedesktop.org/patch/msgid/20220914164321.2156-6-Arvind.Yadav@amd.com Signed-off-by: Christian König --- drivers/gpu/drm/scheduler/sched_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index e5a4ecde0063d..4f2395d1a7918 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -829,7 +829,7 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched) job = list_first_entry_or_null(&sched->pending_list, struct drm_sched_job, list); - if (job && dma_fence_is_signaled(&job->s_fence->finished)) { + if (job && dma_fence_is_signaled(job->s_fence->parent)) { /* remove job from pending_list */ list_del_init(&job->list); @@ -841,7 +841,7 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched) if (next) { next->s_fence->scheduled.timestamp = - job->s_fence->finished.timestamp; + job->s_fence->parent->timestamp; /* start TO timer for next job */ drm_sched_start_timeout(sched); } From 8401bd361f5991ccfe9377e502fa37203ad70320 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 13 Sep 2022 18:23:07 +0200 Subject: [PATCH 088/119] drm/plane-helper: Add a drm_plane_helper_atomic_check() helper Provides a default plane state check handler for primary planes that are a fullscreen scanout buffer and whose state scale and position can't change. There are some drivers that duplicate this logic in their helpers, such as simpledrm and ssd130x. Factor out this common code into a plane helper and make drivers use it. Suggested-by: Thomas Zimmermann Signed-off-by: Javier Martinez Canillas Reviewed-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220913162307.121503-1-javierm@redhat.com --- drivers/gpu/drm/drm_plane_helper.c | 30 ++++++++++++++++++++++++++++++ drivers/gpu/drm/solomon/ssd130x.c | 18 +----------------- drivers/gpu/drm/tiny/simpledrm.c | 25 +------------------------ include/drm/drm_plane_helper.h | 1 + 4 files changed, 33 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index c7785967f5bf7..db04d9a32ce83 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -278,3 +278,33 @@ void drm_plane_helper_destroy(struct drm_plane *plane) kfree(plane); } EXPORT_SYMBOL(drm_plane_helper_destroy); + +/** + * drm_plane_helper_atomic_check() - Helper to check plane atomic-state + * @plane: plane to check + * @state: atomic state object + * + * Provides a default plane-state check handler for planes whose atomic-state + * scale and positioning are not expected to change since the plane is always + * a fullscreen scanout buffer. + * + * This is often the case for the primary plane of simple framebuffers. + * + * RETURNS: + * Zero on success, or an errno code otherwise. + */ +int drm_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) +{ + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *new_crtc = new_plane_state->crtc; + struct drm_crtc_state *new_crtc_state = NULL; + + if (new_crtc) + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); + + return drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); +} +EXPORT_SYMBOL(drm_plane_helper_atomic_check); diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index c95221fff474f..7fae9480aa116 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -565,22 +565,6 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_m return ret; } -static int ssd130x_primary_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_atomic_state *new_state) -{ - struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane); - struct drm_crtc *new_crtc = new_plane_state->crtc; - struct drm_crtc_state *new_crtc_state = NULL; - - if (new_crtc) - new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_crtc); - - return drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, - DRM_PLANE_NO_SCALING, - DRM_PLANE_NO_SCALING, - false, false); -} - static void ssd130x_primary_plane_helper_atomic_update(struct drm_plane *plane, struct drm_atomic_state *old_state) { @@ -623,7 +607,7 @@ static void ssd130x_primary_plane_helper_atomic_disable(struct drm_plane *plane, static const struct drm_plane_helper_funcs ssd130x_primary_plane_helper_funcs = { DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, - .atomic_check = ssd130x_primary_plane_helper_atomic_check, + .atomic_check = drm_plane_helper_atomic_check, .atomic_update = ssd130x_primary_plane_helper_atomic_update, .atomic_disable = ssd130x_primary_plane_helper_atomic_disable, }; diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 777ccd2508717..ea5b3239a6591 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -469,29 +469,6 @@ static const uint64_t simpledrm_primary_plane_format_modifiers[] = { DRM_FORMAT_MOD_INVALID }; -static int simpledrm_primary_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_atomic_state *new_state) -{ - struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane); - struct drm_crtc *new_crtc = new_plane_state->crtc; - struct drm_crtc_state *new_crtc_state = NULL; - int ret; - - if (new_crtc) - new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_crtc); - - ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, - DRM_PLANE_NO_SCALING, - DRM_PLANE_NO_SCALING, - false, false); - if (ret) - return ret; - else if (!new_plane_state->visible) - return 0; - - return 0; -} - static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane *plane, struct drm_atomic_state *old_state) { @@ -543,7 +520,7 @@ static void simpledrm_primary_plane_helper_atomic_disable(struct drm_plane *plan static const struct drm_plane_helper_funcs simpledrm_primary_plane_helper_funcs = { DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, - .atomic_check = simpledrm_primary_plane_helper_atomic_check, + .atomic_check = drm_plane_helper_atomic_check, .atomic_update = simpledrm_primary_plane_helper_atomic_update, .atomic_disable = simpledrm_primary_plane_helper_atomic_disable, }; diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 1781fab24dd69..7760b27b0323c 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -41,5 +41,6 @@ int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *cr int drm_plane_helper_disable_primary(struct drm_plane *plane, struct drm_modeset_acquire_ctx *ctx); void drm_plane_helper_destroy(struct drm_plane *plane); +int drm_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state); #endif From 770e19076065e079a32f33eb11be2057c87f1cde Mon Sep 17 00:00:00 2001 From: Maya Matuszczyk Date: Wed, 3 Aug 2022 20:24:03 +0200 Subject: [PATCH 089/119] drm: panel-orientation-quirks: Add quirk for Anbernic Win600 This device is another x86 gaming handheld, and as (hopefully) there is only one set of DMI IDs it's using DMI_EXACT_MATCH Signed-off-by: Maya Matuszczyk Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20220803182402.1217293-1-maccraft123mc@gmail.com --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index fc1728d46ac2a..64b194af003c2 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -128,6 +128,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"), }, .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* Anbernic Win600 */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Anbernic"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Win600"), + }, + .driver_data = (void *)&lcd720x1280_rightside_up, }, { /* Asus T100HA */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), From 2830ca9e5b98bee82f1d1e284ce23fe7fb244ea8 Mon Sep 17 00:00:00 2001 From: Jilin Yuan Date: Wed, 24 Aug 2022 21:02:26 +0800 Subject: [PATCH 090/119] drm/vboxvideo: fix repeated words in comments Delete the redundant word 'the'. Signed-off-by: Jilin Yuan Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20220824130226.33980-1-yuanjilin@cdjrlc.com --- drivers/gpu/drm/vboxvideo/vboxvideo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vboxvideo/vboxvideo.h b/drivers/gpu/drm/vboxvideo/vboxvideo.h index a5de40fe1a76a..f60d82504da02 100644 --- a/drivers/gpu/drm/vboxvideo/vboxvideo.h +++ b/drivers/gpu/drm/vboxvideo/vboxvideo.h @@ -43,7 +43,7 @@ * VBE_DISPI_INDEX_VBOX_VIDEO is used to read the configuration information * from the host and issue commands to the host. * - * The guest writes the VBE_DISPI_INDEX_VBOX_VIDEO index register, the the + * The guest writes the VBE_DISPI_INDEX_VBOX_VIDEO index register, the * following operations with the VBE data register can be performed: * * Operation Result From 9b6a16575ebf23a98a9ff84aedde9f3b25731714 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 6 Sep 2022 22:38:52 +0200 Subject: [PATCH 091/119] drm/gma500: Fix (vblank) IRQs not working after suspend/resume Fix gnome-shell (and other page-flip users) hanging after suspend/resume because of the gma500's IRQs not working. This fixes 2 problems with the IRQ handling: 1. gma_power_off() calls gma_irq_uninstall() which does a free_irq(), but gma_power_on() called gma_irq_preinstall() + gma_irq_postinstall() which do not call request_irq. Replace the pre- + post-install calls with gma_irq_install() which does prep + request + post. 2. After fixing 1. IRQs still do not work on a Packard Bell Dot SC (Intel Atom N2600, cedarview) netbook. Cederview uses MSI interrupts and it seems that the BIOS re-configures things back to normal APIC based interrupts during S3 suspend. There is some MSI PCI-config registers save/restore code which tries to deal with this, but on the Packard Bell Dot SC this is not sufficient to restore MSI IRQ functionality after a suspend/resume. Replace the PCI-config registers save/restore with pci_disable_msi() on suspend + pci_enable_msi() on resume. Fixing e.g. gnome-shell hanging. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220906203852.527663-4-hdegoede@redhat.com (cherry picked from commit 235fdbc32d559db21e580f85035c59372704f09e) --- drivers/gpu/drm/gma500/cdv_device.c | 4 +--- drivers/gpu/drm/gma500/oaktrail_device.c | 5 +---- drivers/gpu/drm/gma500/power.c | 8 +------- drivers/gpu/drm/gma500/psb_drv.c | 2 +- drivers/gpu/drm/gma500/psb_drv.h | 5 +---- drivers/gpu/drm/gma500/psb_irq.c | 15 ++++++++++++--- drivers/gpu/drm/gma500/psb_irq.h | 2 +- 7 files changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index dd32b484dd825..ce96234f3df20 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -581,11 +581,9 @@ static const struct psb_offset cdv_regmap[2] = { static int cdv_chip_setup(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - struct pci_dev *pdev = to_pci_dev(dev->dev); INIT_WORK(&dev_priv->hotplug_work, cdv_hotplug_work_func); - if (pci_enable_msi(pdev)) - dev_warn(dev->dev, "Enabling MSI failed!\n"); + dev_priv->use_msi = true; dev_priv->regmap = cdv_regmap; gma_get_core_freq(dev); psb_intel_opregion_init(dev); diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 5923a9c893122..f90e628cb482c 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -501,12 +501,9 @@ static const struct psb_offset oaktrail_regmap[2] = { static int oaktrail_chip_setup(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - struct pci_dev *pdev = to_pci_dev(dev->dev); int ret; - if (pci_enable_msi(pdev)) - dev_warn(dev->dev, "Enabling MSI failed!\n"); - + dev_priv->use_msi = true; dev_priv->regmap = oaktrail_regmap; ret = mid_chip_setup(dev); diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c index b91de6d36e412..66873085d4505 100644 --- a/drivers/gpu/drm/gma500/power.c +++ b/drivers/gpu/drm/gma500/power.c @@ -139,8 +139,6 @@ static void gma_suspend_pci(struct pci_dev *pdev) dev_priv->regs.saveBSM = bsm; pci_read_config_dword(pdev, 0xFC, &vbt); dev_priv->regs.saveVBT = vbt; - pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr); - pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); @@ -168,9 +166,6 @@ static bool gma_resume_pci(struct pci_dev *pdev) pci_restore_state(pdev); pci_write_config_dword(pdev, 0x5c, dev_priv->regs.saveBSM); pci_write_config_dword(pdev, 0xFC, dev_priv->regs.saveVBT); - /* restoring MSI address and data in PCIx space */ - pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr); - pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data); ret = pci_enable_device(pdev); if (ret != 0) @@ -223,8 +218,7 @@ int gma_power_resume(struct device *_dev) mutex_lock(&power_mutex); gma_resume_pci(pdev); gma_resume_display(pdev); - gma_irq_preinstall(dev); - gma_irq_postinstall(dev); + gma_irq_install(dev); mutex_unlock(&power_mutex); return 0; } diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 1d8744f3e7020..54e756b486060 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -383,7 +383,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - gma_irq_install(dev, pdev->irq); + gma_irq_install(dev); dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 0ea3d23575f3a..731cc356c07a3 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -490,6 +490,7 @@ struct drm_psb_private { int rpm_enabled; /* MID specific */ + bool use_msi; bool has_gct; struct oaktrail_gct_data gct_data; @@ -499,10 +500,6 @@ struct drm_psb_private { /* Register state */ struct psb_save_area regs; - /* MSI reg save */ - uint32_t msi_addr; - uint32_t msi_data; - /* Hotplug handling */ struct work_struct hotplug_work; diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index e6e6d61bbeab6..038f18ed0a95e 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -316,17 +316,24 @@ void gma_irq_postinstall(struct drm_device *dev) spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); } -int gma_irq_install(struct drm_device *dev, unsigned int irq) +int gma_irq_install(struct drm_device *dev) { + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); int ret; - if (irq == IRQ_NOTCONNECTED) + if (dev_priv->use_msi && pci_enable_msi(pdev)) { + dev_warn(dev->dev, "Enabling MSI failed!\n"); + dev_priv->use_msi = false; + } + + if (pdev->irq == IRQ_NOTCONNECTED) return -ENOTCONN; gma_irq_preinstall(dev); /* PCI devices require shared interrupts. */ - ret = request_irq(irq, gma_irq_handler, IRQF_SHARED, dev->driver->name, dev); + ret = request_irq(pdev->irq, gma_irq_handler, IRQF_SHARED, dev->driver->name, dev); if (ret) return ret; @@ -369,6 +376,8 @@ void gma_irq_uninstall(struct drm_device *dev) spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); free_irq(pdev->irq, dev); + if (dev_priv->use_msi) + pci_disable_msi(pdev); } int gma_crtc_enable_vblank(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h index b51e395194fff..7648f69824a5d 100644 --- a/drivers/gpu/drm/gma500/psb_irq.h +++ b/drivers/gpu/drm/gma500/psb_irq.h @@ -17,7 +17,7 @@ struct drm_device; void gma_irq_preinstall(struct drm_device *dev); void gma_irq_postinstall(struct drm_device *dev); -int gma_irq_install(struct drm_device *dev, unsigned int irq); +int gma_irq_install(struct drm_device *dev); void gma_irq_uninstall(struct drm_device *dev); int gma_crtc_enable_vblank(struct drm_crtc *crtc); From 49da26d7b418cfc99ad2473a2e3dee2e08c5ba4a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 9 Sep 2022 13:56:42 +0200 Subject: [PATCH 092/119] drm/gma500: Remove runtime_allowed dead code in psb_unlocked_ioctl() runtime_allowed is initialized to 0, so the runtime_allowed == 1 condition is never true making this dead code. Remove it. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220909115646.99920-3-hdegoede@redhat.com --- drivers/gpu/drm/gma500/psb_drv.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 54e756b486060..7a94e0d8fa6c9 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -433,18 +433,7 @@ static inline void get_brightness(struct backlight_device *bd) static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->minor->dev; - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - static unsigned int runtime_allowed; - - if (runtime_allowed == 1 && dev_priv->is_lvds_on) { - runtime_allowed++; - pm_runtime_allow(dev->dev); - dev_priv->rpm_enabled = 1; - } return drm_ioctl(filp, cmd, arg); - /* FIXME: do we need to wrap the other side of this */ } static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) From f3b173e9094f5b02fb92d641e3e71fee0bcda73a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 9 Sep 2022 13:56:43 +0200 Subject: [PATCH 093/119] drm/gma500: Remove never set dev_priv->rpm_enabled flag The rpm_enabled flag is never set, remove it. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220909115646.99920-4-hdegoede@redhat.com --- drivers/gpu/drm/gma500/gma_display.c | 13 +------------ drivers/gpu/drm/gma500/psb_drv.h | 3 --- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index bd40c040a2c91..5419f686f3297 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -555,18 +555,7 @@ int gma_crtc_page_flip(struct drm_crtc *crtc, int gma_crtc_set_config(struct drm_mode_set *set, struct drm_modeset_acquire_ctx *ctx) { - struct drm_device *dev = set->crtc->dev; - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - int ret; - - if (!dev_priv->rpm_enabled) - return drm_crtc_helper_set_config(set, ctx); - - pm_runtime_forbid(dev->dev); - ret = drm_crtc_helper_set_config(set, ctx); - pm_runtime_allow(dev->dev); - - return ret; + return drm_crtc_helper_set_config(set, ctx); } const struct drm_crtc_funcs gma_crtc_funcs = { diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 731cc356c07a3..dd6fd49d85f37 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -486,9 +486,6 @@ struct drm_psb_private { unsigned int core_freq; uint32_t iLVDS_enable; - /* Runtime PM state */ - int rpm_enabled; - /* MID specific */ bool use_msi; bool has_gct; From d35a4bf66079b92e232ac85b08f19312be9b7eca Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 9 Sep 2022 13:56:44 +0200 Subject: [PATCH 094/119] drm/gma500: Remove a couple of not useful function wrappers The gma_crtc_set_config() and psb_unlocked_ioctl() functions are 1:1 wrappers for drm_helpers. Drop these wrappers. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220909115646.99920-5-hdegoede@redhat.com --- drivers/gpu/drm/gma500/gma_display.c | 8 +------- drivers/gpu/drm/gma500/gma_display.h | 2 -- drivers/gpu/drm/gma500/psb_drv.c | 8 +------- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 5419f686f3297..b0ea911b27de1 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -552,17 +552,11 @@ int gma_crtc_page_flip(struct drm_crtc *crtc, return ret; } -int gma_crtc_set_config(struct drm_mode_set *set, - struct drm_modeset_acquire_ctx *ctx) -{ - return drm_crtc_helper_set_config(set, ctx); -} - const struct drm_crtc_funcs gma_crtc_funcs = { .cursor_set = gma_crtc_cursor_set, .cursor_move = gma_crtc_cursor_move, .gamma_set = gma_crtc_gamma_set, - .set_config = gma_crtc_set_config, + .set_config = drm_crtc_helper_set_config, .destroy = gma_crtc_destroy, .page_flip = gma_crtc_page_flip, .enable_vblank = gma_crtc_enable_vblank, diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h index 113cf048105e5..c8b611a2f6c62 100644 --- a/drivers/gpu/drm/gma500/gma_display.h +++ b/drivers/gpu/drm/gma500/gma_display.h @@ -69,8 +69,6 @@ extern int gma_crtc_page_flip(struct drm_crtc *crtc, struct drm_pending_vblank_event *event, uint32_t page_flip_flags, struct drm_modeset_acquire_ctx *ctx); -extern int gma_crtc_set_config(struct drm_mode_set *set, - struct drm_modeset_acquire_ctx *ctx); extern void gma_crtc_save(struct drm_crtc *crtc); extern void gma_crtc_restore(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 7a94e0d8fa6c9..8266371aeac1c 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -430,12 +430,6 @@ static inline void get_brightness(struct backlight_device *bd) #endif } -static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - return drm_ioctl(filp, cmd, arg); -} - static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct drm_psb_private *dev_priv; @@ -497,7 +491,7 @@ static const struct file_operations psb_gem_fops = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .unlocked_ioctl = psb_unlocked_ioctl, + .unlocked_ioctl = drm_ioctl, .compat_ioctl = drm_compat_ioctl, .mmap = drm_gem_mmap, .poll = drm_poll, From 672c473576ca5c9f5a40ac848c938e6898a5aac8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 9 Sep 2022 13:56:45 +0200 Subject: [PATCH 095/119] drm/gma500: Rewrite power management code Rewrite the power.c code. For some reason this was doing locking + refcounting + state (suspended or not) bookkeeping all by itself. But there is no reason for this, this is all taken care of by the runtime-pm core, through pm_runtime_get()/_put(). Besides this not being necessary the DIY code is also quite weird/ buggy in some places. E.g. power_begin() would manually do a resume when not resumed already and force_on=true, followed by a pm_runtime_get(), which will cause a call to gma_power_resume() to get scheduled which would redo the entire resume again. Which can all be replaced by a single pm_runtime_get_sync() call. Note that this is just a cleanup, this does not actually fix the (disabled through #if 0) runtime-pm support. It does now call pm_runtime_enable(), but only after doing a pm_runtime_get() at probe-time, so the device is never runtime suspended. Doing this permanent get() + enable() instead of not calling enable() at all is necessary for the pm_runtime_get_if_in_use() call in gma_power_begin() to work properly. Note this also removes the gma_power_is_on() call a check like this without actually holding a reference is always racy, so it is a bad idea (and therefor has no pm_runtime_foo() equivalent). The 2 code paths which were using gma_power_is_on() are actually both guaranteed to only run when the device is powered-on so the 2 checks can simply be dropped. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220909115646.99920-6-hdegoede@redhat.com --- drivers/gpu/drm/gma500/oaktrail_lvds.c | 1 - drivers/gpu/drm/gma500/power.c | 133 ++++++------------------- drivers/gpu/drm/gma500/power.h | 9 -- drivers/gpu/drm/gma500/psb_drv.c | 6 -- drivers/gpu/drm/gma500/psb_drv.h | 4 +- drivers/gpu/drm/gma500/psb_irq.c | 15 ++- 6 files changed, 38 insertions(+), 130 deletions(-) diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c index 4d98df189e10e..75b4eb1c8884d 100644 --- a/drivers/gpu/drm/gma500/oaktrail_lvds.c +++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c @@ -61,7 +61,6 @@ static void oaktrail_lvds_set_power(struct drm_device *dev, pp_status = REG_READ(PP_STATUS); } while (pp_status & PP_ON); dev_priv->is_lvds_on = false; - pm_request_idle(dev->dev); } gma_power_end(dev); } diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c index 66873085d4505..af09e0d680d94 100644 --- a/drivers/gpu/drm/gma500/power.c +++ b/drivers/gpu/drm/gma500/power.c @@ -37,9 +37,6 @@ #include #include -static struct mutex power_mutex; /* Serialize power ops */ -static DEFINE_SPINLOCK(power_ctrl_lock); /* Serialize power claim */ - /** * gma_power_init - initialise power manager * @dev: our device @@ -54,13 +51,23 @@ void gma_power_init(struct drm_device *dev) dev_priv->apm_base = dev_priv->apm_reg & 0xffff; dev_priv->ospm_base &= 0xffff; - dev_priv->display_power = true; /* We start active */ - dev_priv->display_count = 0; /* Currently no users */ - dev_priv->suspended = false; /* And not suspended */ - mutex_init(&power_mutex); - if (dev_priv->ops->init_pm) dev_priv->ops->init_pm(dev); + + /* + * Runtime pm support is broken atm. So for now unconditionally + * call pm_runtime_get() here and put it again in psb_driver_unload() + * + * To fix this we need to call pm_runtime_get() once for each active + * pipe at boot and then put() / get() for each pipe disable / enable + * so that the device gets runtime suspended when no pipes are active. + * Once this is in place the pm_runtime_get() below should be replaced + * by a pm_runtime_allow() call to undo the pm_runtime_forbid() from + * pci_pm_init(). + */ + pm_runtime_get(dev->dev); + + dev_priv->pm_initialized = true; } /** @@ -71,8 +78,12 @@ void gma_power_init(struct drm_device *dev) */ void gma_power_uninit(struct drm_device *dev) { - pm_runtime_disable(dev->dev); - pm_runtime_set_suspended(dev->dev); + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + + if (!dev_priv->pm_initialized) + return; + + pm_runtime_put_noidle(dev->dev); } /** @@ -85,11 +96,8 @@ static void gma_suspend_display(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - if (dev_priv->suspended) - return; dev_priv->ops->save_regs(dev); dev_priv->ops->power_down(dev); - dev_priv->display_power = false; } /** @@ -106,8 +114,6 @@ static void gma_resume_display(struct pci_dev *pdev) /* turn on the display power island */ dev_priv->ops->power_up(dev); - dev_priv->suspended = false; - dev_priv->display_power = true; PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); pci_write_config_word(pdev, PSB_GMCH_CTRL, @@ -131,9 +137,6 @@ static void gma_suspend_pci(struct pci_dev *pdev) struct drm_psb_private *dev_priv = to_drm_psb_private(dev); int bsm, vbt; - if (dev_priv->suspended) - return; - pci_save_state(pdev); pci_read_config_dword(pdev, 0x5C, &bsm); dev_priv->regs.saveBSM = bsm; @@ -142,8 +145,6 @@ static void gma_suspend_pci(struct pci_dev *pdev) pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); - - dev_priv->suspended = true; } /** @@ -153,26 +154,17 @@ static void gma_suspend_pci(struct pci_dev *pdev) * Perform the resume processing on our PCI device state - rewrite * register state and re-enable the PCI device */ -static bool gma_resume_pci(struct pci_dev *pdev) +static int gma_resume_pci(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - int ret; - - if (!dev_priv->suspended) - return true; pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); pci_write_config_dword(pdev, 0x5c, dev_priv->regs.saveBSM); pci_write_config_dword(pdev, 0xFC, dev_priv->regs.saveVBT); - ret = pci_enable_device(pdev); - if (ret != 0) - dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); - else - dev_priv->suspended = false; - return !dev_priv->suspended; + return pci_enable_device(pdev); } /** @@ -187,20 +179,10 @@ int gma_power_suspend(struct device *_dev) { struct pci_dev *pdev = to_pci_dev(_dev); struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - mutex_lock(&power_mutex); - if (!dev_priv->suspended) { - if (dev_priv->display_count) { - mutex_unlock(&power_mutex); - dev_err(dev->dev, "GPU hardware busy, cannot suspend\n"); - return -EBUSY; - } - gma_irq_uninstall(dev); - gma_suspend_display(dev); - gma_suspend_pci(pdev); - } - mutex_unlock(&power_mutex); + gma_irq_uninstall(dev); + gma_suspend_display(dev); + gma_suspend_pci(pdev); return 0; } @@ -215,26 +197,12 @@ int gma_power_resume(struct device *_dev) struct pci_dev *pdev = to_pci_dev(_dev); struct drm_device *dev = pci_get_drvdata(pdev); - mutex_lock(&power_mutex); gma_resume_pci(pdev); gma_resume_display(pdev); gma_irq_install(dev); - mutex_unlock(&power_mutex); return 0; } -/** - * gma_power_is_on - returne true if power is on - * @dev: our DRM device - * - * Returns true if the display island power is on at this moment - */ -bool gma_power_is_on(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - return dev_priv->display_power; -} - /** * gma_power_begin - begin requiring power * @dev: our DRM device @@ -245,35 +213,10 @@ bool gma_power_is_on(struct drm_device *dev) */ bool gma_power_begin(struct drm_device *dev, bool force_on) { - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - struct pci_dev *pdev = to_pci_dev(dev->dev); - int ret; - unsigned long flags; - - spin_lock_irqsave(&power_ctrl_lock, flags); - /* Power already on ? */ - if (dev_priv->display_power) { - dev_priv->display_count++; - pm_runtime_get(dev->dev); - spin_unlock_irqrestore(&power_ctrl_lock, flags); - return true; - } - if (force_on == false) - goto out_false; - - /* Ok power up needed */ - ret = gma_resume_pci(pdev); - if (ret == 0) { - gma_irq_preinstall(dev); - gma_irq_postinstall(dev); - pm_runtime_get(dev->dev); - dev_priv->display_count++; - spin_unlock_irqrestore(&power_ctrl_lock, flags); - return true; - } -out_false: - spin_unlock_irqrestore(&power_ctrl_lock, flags); - return false; + if (force_on) + return pm_runtime_resume_and_get(dev->dev) == 0; + else + return pm_runtime_get_if_in_use(dev->dev) == 1; } /** @@ -285,12 +228,6 @@ bool gma_power_begin(struct drm_device *dev, bool force_on) */ void gma_power_end(struct drm_device *dev) { - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - unsigned long flags; - spin_lock_irqsave(&power_ctrl_lock, flags); - dev_priv->display_count--; - WARN_ON(dev_priv->display_count < 0); - spin_unlock_irqrestore(&power_ctrl_lock, flags); pm_runtime_put(dev->dev); } @@ -304,16 +241,6 @@ int psb_runtime_resume(struct device *dev) return gma_power_resume(dev); } -int psb_runtime_idle(struct device *dev) -{ - struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); - struct drm_psb_private *dev_priv = to_drm_psb_private(drmdev); - if (dev_priv->display_count) - return 0; - else - return 1; -} - int gma_power_thaw(struct device *_dev) { return gma_power_resume(_dev); diff --git a/drivers/gpu/drm/gma500/power.h b/drivers/gpu/drm/gma500/power.h index 0c89c4d6ec204..243b9dd009104 100644 --- a/drivers/gpu/drm/gma500/power.h +++ b/drivers/gpu/drm/gma500/power.h @@ -54,19 +54,10 @@ int gma_power_restore(struct device *_dev); bool gma_power_begin(struct drm_device *dev, bool force); void gma_power_end(struct drm_device *dev); -/* - * Use this function to do an instantaneous check for if the hw is on. - * Only use this in cases where you know the mutex is already held such - * as in irq install/uninstall and you need to - * prevent a deadlock situation. Otherwise use gma_power_begin(). - */ -bool gma_power_is_on(struct drm_device *dev); - /* * GFX-Runtime PM callbacks */ int psb_runtime_suspend(struct device *dev); int psb_runtime_resume(struct device *dev); -int psb_runtime_idle(struct device *dev); #endif /*_PSB_POWERMGMT_H_*/ diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 8266371aeac1c..aea8876059d8d 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -407,11 +407,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) if (ret) return ret; psb_intel_opregion_enable_asle(dev); -#if 0 - /* Enable runtime pm at last */ - pm_runtime_enable(dev->dev); - pm_runtime_set_active(dev->dev); -#endif return devm_add_action_or_reset(dev->dev, psb_device_release, dev); @@ -484,7 +479,6 @@ static const struct dev_pm_ops psb_pm_ops = { .restore = gma_power_restore, .runtime_suspend = psb_runtime_suspend, .runtime_resume = psb_runtime_resume, - .runtime_idle = psb_runtime_idle, }; static const struct file_operations psb_gem_fops = { diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index dd6fd49d85f37..049701ce8a5f3 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -426,9 +426,7 @@ struct drm_psb_private { spinlock_t irqmask_lock; /* Power */ - bool suspended; - bool display_power; - int display_count; + bool pm_initialized; /* Modesetting */ struct psb_intel_mode_device mode_dev; diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 038f18ed0a95e..d421031462df6 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -228,7 +228,7 @@ static irqreturn_t gma_irq_handler(int irq, void *arg) vdc_stat &= dev_priv->vdc_irq_mask; spin_unlock(&dev_priv->irqmask_lock); - if (dsp_int && gma_power_is_on(dev)) { + if (dsp_int) { gma_vdc_interrupt(dev, vdc_stat); handled = 1; } @@ -264,13 +264,12 @@ void gma_irq_preinstall(struct drm_device *dev) spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - if (gma_power_is_on(dev)) { - PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - PSB_WVDC32(0x00000000, PSB_INT_MASK_R); - PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); - PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE); - PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); - } + PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); + PSB_WVDC32(0x00000000, PSB_INT_MASK_R); + PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); + PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE); + PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); + if (dev->vblank[0].enabled) dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; if (dev->vblank[1].enabled) From 74f481f187ce8b37ec5143cee19147da5243009c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 9 Sep 2022 13:56:46 +0200 Subject: [PATCH 096/119] drm/gma500: Remove unnecessary suspend/resume wrappers The psb_runtime_suspend/resume/thaw/freeze/restore functions are all just 1:1 wrappers around gma_power_suspend/_resume. Drop these wrappers and use the DEFINE_RUNTIME_DEV_PM_OPS() macro to define the dev_pm_ops struct. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220909115646.99920-7-hdegoede@redhat.com --- drivers/gpu/drm/gma500/power.c | 25 ------------------------- drivers/gpu/drm/gma500/power.h | 9 --------- drivers/gpu/drm/gma500/psb_drv.c | 10 +--------- 3 files changed, 1 insertion(+), 43 deletions(-) diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c index af09e0d680d94..186af29bea6fb 100644 --- a/drivers/gpu/drm/gma500/power.c +++ b/drivers/gpu/drm/gma500/power.c @@ -230,28 +230,3 @@ void gma_power_end(struct drm_device *dev) { pm_runtime_put(dev->dev); } - -int psb_runtime_suspend(struct device *dev) -{ - return gma_power_suspend(dev); -} - -int psb_runtime_resume(struct device *dev) -{ - return gma_power_resume(dev); -} - -int gma_power_thaw(struct device *_dev) -{ - return gma_power_resume(_dev); -} - -int gma_power_freeze(struct device *_dev) -{ - return gma_power_suspend(_dev); -} - -int gma_power_restore(struct device *_dev) -{ - return gma_power_resume(_dev); -} diff --git a/drivers/gpu/drm/gma500/power.h b/drivers/gpu/drm/gma500/power.h index 243b9dd009104..063328d66652c 100644 --- a/drivers/gpu/drm/gma500/power.h +++ b/drivers/gpu/drm/gma500/power.h @@ -43,9 +43,6 @@ void gma_power_uninit(struct drm_device *dev); */ int gma_power_suspend(struct device *dev); int gma_power_resume(struct device *dev); -int gma_power_thaw(struct device *dev); -int gma_power_freeze(struct device *dev); -int gma_power_restore(struct device *_dev); /* * These are the functions the driver should use to wrap all hw access @@ -54,10 +51,4 @@ int gma_power_restore(struct device *_dev); bool gma_power_begin(struct drm_device *dev, bool force); void gma_power_end(struct drm_device *dev); -/* - * GFX-Runtime PM callbacks - */ -int psb_runtime_suspend(struct device *dev); -int psb_runtime_resume(struct device *dev); - #endif /*_PSB_POWERMGMT_H_*/ diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index aea8876059d8d..9168bc620628b 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -471,15 +471,7 @@ static void psb_pci_remove(struct pci_dev *pdev) drm_dev_unregister(dev); } -static const struct dev_pm_ops psb_pm_ops = { - .resume = gma_power_resume, - .suspend = gma_power_suspend, - .thaw = gma_power_thaw, - .freeze = gma_power_freeze, - .restore = gma_power_restore, - .runtime_suspend = psb_runtime_suspend, - .runtime_resume = psb_runtime_resume, -}; +static DEFINE_RUNTIME_DEV_PM_OPS(psb_pm_ops, gma_power_suspend, gma_power_resume, NULL); static const struct file_operations psb_gem_fops = { .owner = THIS_MODULE, From e10ea7b9b90219da305a16b3c1252169715a807b Mon Sep 17 00:00:00 2001 From: Maya Matuszczyk Date: Thu, 25 Aug 2022 21:19:47 +0200 Subject: [PATCH 097/119] drm: panel-orientation-quirks: Add quirk for Aya Neo Air Yet another x86 gaming handheld. This one has many SKUs with quite a few of DMI strings, so let's just use a catchall, just as with Aya Neo Next. Signed-off-by: Maya Matuszczyk Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20220825191946.1678798-1-maccraft123mc@gmail.com --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 64b194af003c2..8a0c0e0bb5bd2 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -103,6 +103,12 @@ static const struct drm_dmi_panel_orientation_data lcd800x1280_rightside_up = { .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, }; +static const struct drm_dmi_panel_orientation_data lcd1080x1920_leftside_up = { + .width = 1080, + .height = 1920, + .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP, +}; + static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = { .width = 1200, .height = 1920, @@ -158,6 +164,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYA NEO 2021"), }, .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* AYA NEO AIR */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), + DMI_MATCH(DMI_BOARD_NAME, "AIR"), + }, + .driver_data = (void *)&lcd1080x1920_leftside_up, }, { /* AYA NEO NEXT */ .matches = { DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"), From 1f90b1232773249d924868bec3c31525a69fd482 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Sep 2022 22:59:16 +0200 Subject: [PATCH 098/119] drm/gma500: Refactor backlight support (v2) Refactor backlight support so that the gma_backlight_enable() / gma_backlight_disable() / gma_backlight_set() functions used by the Opregion handle will also work if no backlight_device gets registered. This is a preparation patch for not registering the gma500's own backlight device when acpi_video should be used, since registering 2 backlight devices for a single display really is undesirable. Since the acpi-video interface often uses the OpRegion we need to keep the OpRegion functional even when dev_priv->backlight_device is NULL. As a result of this refactor the actual backlight_device_register() call is moved to the shared backlight.c code and all #ifdefs related to CONFIG_BACKLIGHT_CLASS_DEVICE are now also limited to backlight.c . No functional changes intended. This has been tested on a Packard Bell Dot SC (Intel Atom N2600, cedarview) and a Sony Vaio vpc-x11s1e (Intel N540, poulsbo) laptop. Changes in v2: - Fix unused variable warnings when CONFIG_BACKLIGHT is not selected by marking the 2 variables as __maybe_unused. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220917205920.647212-2-hdegoede@redhat.com --- drivers/gpu/drm/gma500/backlight.c | 94 +++++++++++++++--------- drivers/gpu/drm/gma500/cdv_device.c | 50 +++---------- drivers/gpu/drm/gma500/oaktrail_device.c | 65 ++-------------- drivers/gpu/drm/gma500/opregion.c | 6 +- drivers/gpu/drm/gma500/psb_device.c | 73 +----------------- drivers/gpu/drm/gma500/psb_drv.c | 13 +--- drivers/gpu/drm/gma500/psb_drv.h | 13 ++-- 7 files changed, 87 insertions(+), 227 deletions(-) diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c index 46b9c0f13d6d6..b804325eb64ab 100644 --- a/drivers/gpu/drm/gma500/backlight.c +++ b/drivers/gpu/drm/gma500/backlight.c @@ -13,69 +13,95 @@ #include "intel_bios.h" #include "power.h" -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -static void do_gma_backlight_set(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - backlight_update_status(dev_priv->backlight_device); -} -#endif - void gma_backlight_enable(struct drm_device *dev) { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + dev_priv->backlight_enabled = true; - if (dev_priv->backlight_device) { - dev_priv->backlight_device->props.brightness = dev_priv->backlight_level; - do_gma_backlight_set(dev); - } -#endif + dev_priv->ops->backlight_set(dev, dev_priv->backlight_level); } void gma_backlight_disable(struct drm_device *dev) { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + dev_priv->backlight_enabled = false; - if (dev_priv->backlight_device) { - dev_priv->backlight_device->props.brightness = 0; - do_gma_backlight_set(dev); - } -#endif + dev_priv->ops->backlight_set(dev, 0); } void gma_backlight_set(struct drm_device *dev, int v) { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + dev_priv->backlight_level = v; - if (dev_priv->backlight_device && dev_priv->backlight_enabled) { - dev_priv->backlight_device->props.brightness = v; - do_gma_backlight_set(dev); - } -#endif + if (dev_priv->backlight_enabled) + dev_priv->ops->backlight_set(dev, v); } +static int gma_backlight_get_brightness(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + + if (dev_priv->ops->backlight_get) + return dev_priv->ops->backlight_get(dev); + + return dev_priv->backlight_level; +} + +static int gma_backlight_update_status(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + int level = bd->props.brightness; + + /* Percentage 1-100% being valid */ + if (level < 1) + level = 1; + + gma_backlight_set(dev, level); + return 0; +} + +static const struct backlight_ops gma_backlight_ops __maybe_unused = { + .get_brightness = gma_backlight_get_brightness, + .update_status = gma_backlight_update_status, +}; + int gma_backlight_init(struct drm_device *dev) { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct backlight_properties props __maybe_unused = {}; + int ret; + dev_priv->backlight_enabled = true; - return dev_priv->ops->backlight_init(dev); -#else - return 0; + dev_priv->backlight_level = 100; + + ret = dev_priv->ops->backlight_init(dev); + if (ret) + return ret; + +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE + props.brightness = dev_priv->backlight_level; + props.max_brightness = PSB_MAX_BRIGHTNESS; + props.type = BACKLIGHT_PLATFORM; + + dev_priv->backlight_device = + backlight_device_register(dev_priv->ops->backlight_name, + dev->dev, dev, + &gma_backlight_ops, &props); + if (IS_ERR(dev_priv->backlight_device)) + return PTR_ERR(dev_priv->backlight_device); #endif + + return 0; } void gma_backlight_exit(struct drm_device *dev) { #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - if (dev_priv->backlight_device) { - dev_priv->backlight_device->props.brightness = 0; - backlight_update_status(dev_priv->backlight_device); + + if (dev_priv->backlight_device) backlight_device_unregister(dev_priv->backlight_device); - } #endif } diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index ce96234f3df20..3065596257e9a 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -5,7 +5,6 @@ * **************************************************************************/ -#include #include #include @@ -62,14 +61,10 @@ static int cdv_output_init(struct drm_device *dev) return 0; } -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - /* * Cedartrail Backlght Interfaces */ -static struct backlight_device *cdv_backlight_device; - static int cdv_backlight_combination_mode(struct drm_device *dev) { return REG_READ(BLC_PWM_CTL2) & PWM_LEGACY_MODE; @@ -92,9 +87,8 @@ static u32 cdv_get_max_backlight(struct drm_device *dev) return max; } -static int cdv_get_brightness(struct backlight_device *bd) +static int cdv_get_brightness(struct drm_device *dev) { - struct drm_device *dev = bl_get_data(bd); struct pci_dev *pdev = to_pci_dev(dev->dev); u32 val = REG_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; @@ -106,20 +100,13 @@ static int cdv_get_brightness(struct backlight_device *bd) val *= lbpc; } return (val * 100)/cdv_get_max_backlight(dev); - } -static int cdv_set_brightness(struct backlight_device *bd) +static void cdv_set_brightness(struct drm_device *dev, int level) { - struct drm_device *dev = bl_get_data(bd); struct pci_dev *pdev = to_pci_dev(dev->dev); - int level = bd->props.brightness; u32 blc_pwm_ctl; - /* Percentage 1-100% being valid */ - if (level < 1) - level = 1; - level *= cdv_get_max_backlight(dev); level /= 100; @@ -136,38 +123,18 @@ static int cdv_set_brightness(struct backlight_device *bd) blc_pwm_ctl = REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; REG_WRITE(BLC_PWM_CTL, (blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); - return 0; } -static const struct backlight_ops cdv_ops = { - .get_brightness = cdv_get_brightness, - .update_status = cdv_set_brightness, -}; - static int cdv_backlight_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - struct backlight_properties props; - - memset(&props, 0, sizeof(struct backlight_properties)); - props.max_brightness = 100; - props.type = BACKLIGHT_PLATFORM; - - cdv_backlight_device = backlight_device_register("psb-bl", - NULL, (void *)dev, &cdv_ops, &props); - if (IS_ERR(cdv_backlight_device)) - return PTR_ERR(cdv_backlight_device); - - cdv_backlight_device->props.brightness = - cdv_get_brightness(cdv_backlight_device); - backlight_update_status(cdv_backlight_device); - dev_priv->backlight_device = cdv_backlight_device; - dev_priv->backlight_enabled = true; + + dev_priv->backlight_level = cdv_get_brightness(dev); + cdv_set_brightness(dev, dev_priv->backlight_level); + return 0; } -#endif - /* * Provide the Cedarview specific chip logic and low level methods * for power management @@ -613,9 +580,10 @@ const struct psb_ops cdv_chip_ops = { .hotplug = cdv_hotplug_event, .hotplug_enable = cdv_hotplug_enable, -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE .backlight_init = cdv_backlight_init, -#endif + .backlight_get = cdv_get_brightness, + .backlight_set = cdv_set_brightness, + .backlight_name = "psb-bl", .init_pm = cdv_init_pm, .save_regs = cdv_save_display_registers, diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index f90e628cb482c..2531959d3d770 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -5,7 +5,6 @@ * **************************************************************************/ -#include #include #include #include @@ -37,29 +36,18 @@ static int oaktrail_output_init(struct drm_device *dev) * Provide the low level interfaces for the Moorestown backlight */ -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - #define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ #define BLC_PWM_FREQ_CALC_CONSTANT 32 #define MHz 1000000 #define BLC_ADJUSTMENT_MAX 100 -static struct backlight_device *oaktrail_backlight_device; -static int oaktrail_brightness; - -static int oaktrail_set_brightness(struct backlight_device *bd) +static void oaktrail_set_brightness(struct drm_device *dev, int level) { - struct drm_device *dev = bl_get_data(oaktrail_backlight_device); struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - int level = bd->props.brightness; u32 blc_pwm_ctl; u32 max_pwm_blc; - /* Percentage 1-100% being valid */ - if (level < 1) - level = 1; - if (gma_power_begin(dev, 0)) { /* Calculate and set the brightness value */ max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16; @@ -82,19 +70,9 @@ static int oaktrail_set_brightness(struct backlight_device *bd) REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl); gma_power_end(dev); } - oaktrail_brightness = level; - return 0; -} - -static int oaktrail_get_brightness(struct backlight_device *bd) -{ - /* return locally cached var instead of HW read (due to DPST etc.) */ - /* FIXME: ideally return actual value in case firmware fiddled with - it */ - return oaktrail_brightness; } -static int device_backlight_init(struct drm_device *dev) +static int oaktrail_backlight_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); unsigned long core_clock; @@ -123,44 +101,11 @@ static int device_backlight_init(struct drm_device *dev) REG_WRITE(BLC_PWM_CTL, value | (value << 16)); gma_power_end(dev); } - return 0; -} - -static const struct backlight_ops oaktrail_ops = { - .get_brightness = oaktrail_get_brightness, - .update_status = oaktrail_set_brightness, -}; -static int oaktrail_backlight_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - int ret; - struct backlight_properties props; - - memset(&props, 0, sizeof(struct backlight_properties)); - props.max_brightness = 100; - props.type = BACKLIGHT_PLATFORM; - - oaktrail_backlight_device = backlight_device_register("oaktrail-bl", - NULL, (void *)dev, &oaktrail_ops, &props); - - if (IS_ERR(oaktrail_backlight_device)) - return PTR_ERR(oaktrail_backlight_device); - - ret = device_backlight_init(dev); - if (ret < 0) { - backlight_device_unregister(oaktrail_backlight_device); - return ret; - } - oaktrail_backlight_device->props.brightness = 100; - oaktrail_backlight_device->props.max_brightness = 100; - backlight_update_status(oaktrail_backlight_device); - dev_priv->backlight_device = oaktrail_backlight_device; + oaktrail_set_brightness(dev, PSB_MAX_BRIGHTNESS); return 0; } -#endif - /* * Provide the Moorestown specific chip logic and low level methods * for power management @@ -545,9 +490,9 @@ const struct psb_ops oaktrail_chip_ops = { .output_init = oaktrail_output_init, -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE .backlight_init = oaktrail_backlight_init, -#endif + .backlight_set = oaktrail_set_brightness, + .backlight_name = "oaktrail-bl", .save_regs = oaktrail_save_display_registers, .restore_regs = oaktrail_restore_display_registers, diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c index dc494df71a48c..0c271072af63f 100644 --- a/drivers/gpu/drm/gma500/opregion.c +++ b/drivers/gpu/drm/gma500/opregion.c @@ -150,21 +150,17 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct opregion_asle *asle = dev_priv->opregion.asle; - struct backlight_device *bd = dev_priv->backlight_device; DRM_DEBUG_DRIVER("asle set backlight %x\n", bclp); if (!(bclp & ASLE_BCLP_VALID)) return ASLE_BACKLIGHT_FAILED; - if (bd == NULL) - return ASLE_BACKLIGHT_FAILED; - bclp &= ASLE_BCLP_MSK; if (bclp > 255) return ASLE_BACKLIGHT_FAILED; - gma_backlight_set(dev, bclp * bd->props.max_brightness / 255); + gma_backlight_set(dev, bclp * PSB_MAX_BRIGHTNESS / 255); asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID; diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index 71534f4ca8345..3c294c38bdb4d 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -5,8 +5,6 @@ * **************************************************************************/ -#include - #include #include "gma_device.h" @@ -24,8 +22,6 @@ static int psb_output_init(struct drm_device *dev) return 0; } -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - /* * Poulsbo Backlight Interfaces */ @@ -41,18 +37,6 @@ static int psb_output_init(struct drm_device *dev) #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) #define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) -static int psb_brightness; -static struct backlight_device *psb_backlight_device; - -static int psb_get_brightness(struct backlight_device *bd) -{ - /* return locally cached var instead of HW read (due to DPST etc.) */ - /* FIXME: ideally return actual value in case firmware fiddled with - it */ - return psb_brightness; -} - - static int psb_backlight_setup(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); @@ -86,62 +70,13 @@ static int psb_backlight_setup(struct drm_device *dev) REG_WRITE(BLC_PWM_CTL, (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value)); } - return 0; -} - -static int psb_set_brightness(struct backlight_device *bd) -{ - struct drm_device *dev = bl_get_data(psb_backlight_device); - int level = bd->props.brightness; - - /* Percentage 1-100% being valid */ - if (level < 1) - level = 1; - - psb_intel_lvds_set_brightness(dev, level); - psb_brightness = level; - return 0; -} - -static const struct backlight_ops psb_ops = { - .get_brightness = psb_get_brightness, - .update_status = psb_set_brightness, -}; - -static int psb_backlight_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - int ret; - struct backlight_properties props; - - memset(&props, 0, sizeof(struct backlight_properties)); - props.max_brightness = 100; - props.type = BACKLIGHT_PLATFORM; - - psb_backlight_device = backlight_device_register("psb-bl", - NULL, (void *)dev, &psb_ops, &props); - if (IS_ERR(psb_backlight_device)) - return PTR_ERR(psb_backlight_device); - - ret = psb_backlight_setup(dev); - if (ret < 0) { - backlight_device_unregister(psb_backlight_device); - psb_backlight_device = NULL; - return ret; - } - psb_backlight_device->props.brightness = 100; - psb_backlight_device->props.max_brightness = 100; - backlight_update_status(psb_backlight_device); - dev_priv->backlight_device = psb_backlight_device; + psb_intel_lvds_set_brightness(dev, PSB_MAX_BRIGHTNESS); /* This must occur after the backlight is properly initialised */ psb_lid_timer_init(dev_priv); - return 0; } -#endif - /* * Provide the Poulsbo specific chip logic and low level methods * for power management @@ -345,9 +280,9 @@ const struct psb_ops psb_chip_ops = { .output_init = psb_output_init, -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - .backlight_init = psb_backlight_init, -#endif + .backlight_init = psb_backlight_setup, + .backlight_set = psb_intel_lvds_set_brightness, + .backlight_name = "psb-bl", .init_pm = psb_init_pm, .save_regs = psb_save_display_registers, diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 9168bc620628b..d3dc16193a298 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -169,8 +169,7 @@ static void psb_driver_unload(struct drm_device *dev) /* TODO: Kill vblank etc here */ - if (dev_priv->backlight_device) - gma_backlight_exit(dev); + gma_backlight_exit(dev); psb_modeset_cleanup(dev); gma_irq_uninstall(dev); @@ -415,16 +414,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) return ret; } -static inline void get_brightness(struct backlight_device *bd) -{ -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - if (bd) { - bd->props.brightness = bd->ops->get_brightness(bd); - backlight_update_status(bd); - } -#endif -} - static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct drm_psb_private *dev_priv; diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 049701ce8a5f3..ae544b69fc475 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -172,6 +172,8 @@ #define PSB_WATCHDOG_DELAY (HZ * 2) #define PSB_LID_DELAY (HZ / 10) +#define PSB_MAX_BRIGHTNESS 100 + #define PSB_PWR_STATE_ON 1 #define PSB_PWR_STATE_OFF 2 @@ -522,10 +524,6 @@ struct drm_psb_private { struct drm_fb_helper *fb_helper; - /* Panel brightness */ - int brightness; - int brightness_adjusted; - bool dsr_enable; u32 dsr_fb_update; bool dpi_panel_on[3]; @@ -594,10 +592,13 @@ struct psb_ops { void (*disable_sr)(struct drm_device *dev); void (*lvds_bl_power)(struct drm_device *dev, bool on); -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE + /* Backlight */ int (*backlight_init)(struct drm_device *dev); -#endif + void (*backlight_set)(struct drm_device *dev, int level); + int (*backlight_get)(struct drm_device *dev); + const char *backlight_name; + int i2c_bus; /* I2C bus identifier for Moorestown */ }; From dec4ddbe1d4a4414092309611cc97e6b9dc7ec3f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Sep 2022 22:59:17 +0200 Subject: [PATCH 099/119] drm/gma500: Change registered backlight device type to raw/native Change the type for the registered backlight class device from platform to raw/native. The poulsbo/cedarview/oaktrail backlight support is using native GPU backlight control and as such the type should be raw (aka native) as is done by all the other native GPU backlight driver code. Note this will not change much from userspace's point of view. poulsbo/cedarview laptops typically offer both an ACPI-video backlight interface as well as the native GPU backlight interface. The /sys/class/backlight/acpi_video0 has a type of firmware and userspace typically looks for firmware devices before looking for platform devices. The typical standard lookup order is: firmware -> platform -> raw This means that both before and after this change typical userspace backlight consumers (sich as e.g. GNOME) will prefer the firmware acpi_video0 backlight device. This has been tested on a Packard Bell Dot SC (Intel Atom N2600, cedarview) and a Sony Vaio vpc-x11s1e (Intel N540, poulsbo) laptop. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220917205920.647212-3-hdegoede@redhat.com --- drivers/gpu/drm/gma500/backlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c index b804325eb64ab..5a40414e57482 100644 --- a/drivers/gpu/drm/gma500/backlight.c +++ b/drivers/gpu/drm/gma500/backlight.c @@ -83,7 +83,7 @@ int gma_backlight_init(struct drm_device *dev) #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE props.brightness = dev_priv->backlight_level; props.max_brightness = PSB_MAX_BRIGHTNESS; - props.type = BACKLIGHT_PLATFORM; + props.type = BACKLIGHT_RAW; dev_priv->backlight_device = backlight_device_register(dev_priv->ops->backlight_name, From fbf3093466d05461e3f307ffe6b1150daa4b065b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Sep 2022 22:59:18 +0200 Subject: [PATCH 100/119] drm/gma500: Use backlight_get_brightness() to get the brightness Use backlight_get_brightness() instead of directly referencing bd->props.brightness. This will take backlight_is_blank() into account, properly setting brightness to 0 when screen-blanking has been requested through the backlight sysfs interface. Suggested-by: Sam Ravnborg Acked-by: Sam Ravnborg Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220917205920.647212-4-hdegoede@redhat.com --- drivers/gpu/drm/gma500/backlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c index 5a40414e57482..e85fd181f2f36 100644 --- a/drivers/gpu/drm/gma500/backlight.c +++ b/drivers/gpu/drm/gma500/backlight.c @@ -52,7 +52,7 @@ static int gma_backlight_get_brightness(struct backlight_device *bd) static int gma_backlight_update_status(struct backlight_device *bd) { struct drm_device *dev = bl_get_data(bd); - int level = bd->props.brightness; + int level = backlight_get_brightness(bd); /* Percentage 1-100% being valid */ if (level < 1) From a7b98d4dfe68654641d56cdc7eace2c36be93a2d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Sep 2022 22:59:19 +0200 Subject: [PATCH 101/119] drm/gma500: Don't register backlight when another backlight should be used Before this commit when we want userspace to use the acpi_video backlight device we register both the GPU's native backlight device and acpi_video's firmware acpi_video# backlight device. This relies on userspace preferring firmware type backlight devices over native ones. Registering 2 backlight devices for a single display really is undesirable, don't register the GPU's native backlight device when another backlight device should be used. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220917205920.647212-5-hdegoede@redhat.com --- drivers/gpu/drm/gma500/backlight.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c index e85fd181f2f36..577a4987b1937 100644 --- a/drivers/gpu/drm/gma500/backlight.c +++ b/drivers/gpu/drm/gma500/backlight.c @@ -7,6 +7,8 @@ * Authors: Eric Knopp */ +#include + #include "psb_drv.h" #include "psb_intel_reg.h" #include "psb_intel_drv.h" @@ -80,6 +82,12 @@ int gma_backlight_init(struct drm_device *dev) if (ret) return ret; + if (!acpi_video_backlight_use_native()) { + drm_info(dev, "Skipping %s backlight registration\n", + dev_priv->ops->backlight_name); + return 0; + } + #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE props.brightness = dev_priv->backlight_level; props.max_brightness = PSB_MAX_BRIGHTNESS; From c989a62484ad75e0a06f2ffe67886e7cb6d41659 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Sep 2022 22:59:20 +0200 Subject: [PATCH 102/119] drm/gma500: Call acpi_video_register_backlight() On machines without an Intel video opregion the acpi_video driver immediately probes the ACPI video bus and used to also immediately register acpi_video# backlight devices when supported. Once the drm/kms driver then loaded later and possibly registered a native backlight device then the drivers/acpi/video_detect.c code unregistered the acpi_video0 device to avoid there being 2 backlight devices (when acpi_video_get_backlight_type()==native). This means that userspace used to briefly see 2 devices and the disappearing of acpi_video0 after a brief time confuses the systemd backlight level save/restore code, see e.g.: https://bbs.archlinux.org/viewtopic.php?id=269920 To fix this the ACPI video code has been modified to make backlight class device registration a separate step, relying on the drm/kms driver to ask for the acpi_video backlight registration after it is done setting up its native backlight device. Add a call to the new acpi_video_register_backlight() function after setting up the gma500's native backlight, so that the acpi_video backlight device gets registered on systems where the gma500's native backlight device is not registered. Signed-off-by: Hans de Goede Acked-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220917205920.647212-6-hdegoede@redhat.com --- drivers/gpu/drm/gma500/psb_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index d3dc16193a298..cd9c73f5a64ab 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -398,6 +398,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) if (gma_encoder->type == INTEL_OUTPUT_LVDS || gma_encoder->type == INTEL_OUTPUT_MIPI) { ret = gma_backlight_init(dev); + if (ret == 0) + acpi_video_register_backlight(); break; } } From 6e4c96884cdfa0e8bb53e977aa89cd1a830acb95 Mon Sep 17 00:00:00 2001 From: Bo-Chen Chen Date: Fri, 16 Sep 2022 21:38:19 +0800 Subject: [PATCH 103/119] drm/mediatek: dp: Reduce indentation in mtk_dp_bdg_detect() In order to improve human readability, reduce the indentation by returning early if the dp/edp cable is not plugged in. Signed-off-by: Bo-Chen Chen Acked-by: Chun-Kuang Hu Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Dmitry Osipenko Link: https://patchwork.freedesktop.org/patch/msgid/20220916133821.27980-2-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 66 ++++++++++++++++--------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index dfa942ca62da5..c72c646e25e92 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1933,39 +1933,41 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge) bool enabled = mtk_dp->enabled; u8 sink_count = 0; - if (mtk_dp->train_info.cable_plugged_in) { - if (!enabled) { - /* power on aux */ - mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, - DP_PWR_STATE_BANDGAP_TPLL_LANE, - DP_PWR_STATE_MASK); - - /* power on panel */ - drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); - usleep_range(2000, 5000); - } - /* - * Some dongles still source HPD when they do not connect to any - * sink device. To avoid this, we need to read the sink count - * to make sure we do connect to sink devices. After this detect - * function, we just need to check the HPD connection to check - * whether we connect to a sink device. - */ - drm_dp_dpcd_readb(&mtk_dp->aux, DP_SINK_COUNT, &sink_count); - if (DP_GET_SINK_COUNT(sink_count)) - ret = connector_status_connected; - - if (!enabled) { - /* power off panel */ - drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); - usleep_range(2000, 3000); - - /* power off aux */ - mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, - DP_PWR_STATE_BANDGAP_TPLL, - DP_PWR_STATE_MASK); - } + if (!mtk_dp->train_info.cable_plugged_in) + return ret; + + if (!enabled) { + /* power on aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL_LANE, + DP_PWR_STATE_MASK); + + /* power on panel */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + usleep_range(2000, 5000); } + /* + * Some dongles still source HPD when they do not connect to any + * sink device. To avoid this, we need to read the sink count + * to make sure we do connect to sink devices. After this detect + * function, we just need to check the HPD connection to check + * whether we connect to a sink device. + */ + drm_dp_dpcd_readb(&mtk_dp->aux, DP_SINK_COUNT, &sink_count); + if (DP_GET_SINK_COUNT(sink_count)) + ret = connector_status_connected; + + if (!enabled) { + /* power off panel */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); + usleep_range(2000, 3000); + + /* power off aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL, + DP_PWR_STATE_MASK); + } + return ret; } From 821ddae7e4c06f529040f93c22624c956db7431d Mon Sep 17 00:00:00 2001 From: Bo-Chen Chen Date: Fri, 16 Sep 2022 21:38:20 +0800 Subject: [PATCH 104/119] drm/mediatek: dp: Remove unused register definitions Some definitions in mtk_dp_reg.h are not used, so remove these redundant codes. Signed-off-by: Bo-Chen Chen Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Matthias Brugger Acked-by: Chun-Kuang Hu Signed-off-by: Dmitry Osipenko Link: https://patchwork.freedesktop.org/patch/msgid/20220916133821.27980-3-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp_reg.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp_reg.h b/drivers/gpu/drm/mediatek/mtk_dp_reg.h index 096ad6572a5e3..84e38cef03c26 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp_reg.h +++ b/drivers/gpu/drm/mediatek/mtk_dp_reg.h @@ -153,8 +153,6 @@ #define CH_STATUS_1_DP_ENC0_P0_MASK GENMASK(15, 0) #define MTK_DP_ENC0_P0_3094 0x3094 #define CH_STATUS_2_DP_ENC0_P0_MASK GENMASK(7, 0) -#define MTK_DP_ENC0_P0_30A0 0x30a0 -#define DP_ENC0_30A0_MASK (BIT(7) | BIT(8) | BIT(12)) #define MTK_DP_ENC0_P0_30A4 0x30a4 #define AU_TS_CFG_DP_ENC0_P0_MASK GENMASK(7, 0) #define MTK_DP_ENC0_P0_30A8 0x30a8 @@ -171,8 +169,6 @@ #define MTK_DP_ENC0_P0_312C 0x312c #define ASP_HB2_DP_ENC0_P0_MASK GENMASK(7, 0) #define ASP_HB3_DP_ENC0_P0_MASK GENMASK(15, 8) -#define MTK_DP_ENC0_P0_3130 0x3130 -#define MTK_DP_ENC0_P0_3138 0x3138 #define MTK_DP_ENC0_P0_3154 0x3154 #define PGEN_HTOTAL_DP_ENC0_P0_MASK GENMASK(13, 0) #define MTK_DP_ENC0_P0_3158 0x3158 @@ -206,8 +202,6 @@ #define SDP_PACKET_TYPE_DP_ENC1_P0_MASK GENMASK(4, 0) #define SDP_PACKET_W_DP_ENC1_P0 BIT(5) #define SDP_PACKET_W_DP_ENC1_P0_MASK BIT(5) -#define MTK_DP_ENC1_P0_328C 0x328c -#define VSC_DATA_RDY_VESA_DP_ENC1_P0_MASK BIT(7) #define MTK_DP_ENC1_P0_3300 0x3300 #define VIDEO_AFIFO_RDY_SEL_DP_ENC1_P0_VAL 2 #define VIDEO_AFIFO_RDY_SEL_DP_ENC1_P0_MASK GENMASK(9, 8) From 1637c315282e97efcb95cc7dfafbb15efa9fa27f Mon Sep 17 00:00:00 2001 From: Bo-Chen Chen Date: Fri, 16 Sep 2022 21:38:21 +0800 Subject: [PATCH 105/119] drm/mediatek: dp: Fix compiler warning in mtk_dp_video_mute() Fix debug message formatting by using %s instead of 0x%x. Fixes: f70ac097a2cf ("drm/mediatek: Add MT8195 Embedded DisplayPort driver") Reported-by: Chun-Kuang Hu Signed-off-by: Bo-Chen Chen Reviewed-by: Matthias Brugger Acked-by: Chun-Kuang Hu Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Dmitry Osipenko Link: https://patchwork.freedesktop.org/patch/msgid/20220916133821.27980-4-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index c72c646e25e92..d58e98b2f83aa 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1222,8 +1222,8 @@ static void mtk_dp_video_mute(struct mtk_dp *mtk_dp, bool enable) mtk_dp->data->smc_cmd, enable, 0, 0, 0, 0, 0, &res); - dev_dbg(mtk_dp->dev, "smc cmd: 0x%x, p1: 0x%x, ret: 0x%lx-0x%lx\n", - mtk_dp->data->smc_cmd, enable, res.a0, res.a1); + dev_dbg(mtk_dp->dev, "smc cmd: 0x%x, p1: %s, ret: 0x%lx-0x%lx\n", + mtk_dp->data->smc_cmd, enable ? "enable" : "disable", res.a0, res.a1); } static void mtk_dp_audio_mute(struct mtk_dp *mtk_dp, bool mute) From e09523ad132d754f04474430e92835d24912cf29 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 13 Sep 2022 21:49:29 +0800 Subject: [PATCH 106/119] drm/mediatek: dp: change mtk_dp_driver to static mtk_dp_driver is only used in mtk_dp.c now, change it to static. Fixes: f70ac097a2cf ("drm/mediatek: Add MT8195 Embedded DisplayPort driver") Signed-off-by: Yang Yingliang Reviewed-by: Dmitry Osipenko Acked-by: Chun-Kuang Hu Signed-off-by: Dmitry Osipenko Link: https://patchwork.freedesktop.org/patch/msgid/20220913134929.1970187-1-yangyingliang@huawei.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index d58e98b2f83aa..9d085c05c49c3 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -2644,7 +2644,7 @@ static const struct of_device_id mtk_dp_of_match[] = { }; MODULE_DEVICE_TABLE(of, mtk_dp_of_match); -struct platform_driver mtk_dp_driver = { +static struct platform_driver mtk_dp_driver = { .probe = mtk_dp_probe, .remove = mtk_dp_remove, .driver = { From f47f537cbaa48427039f61256f68ce08986d8eb4 Mon Sep 17 00:00:00 2001 From: Robert Foss Date: Mon, 19 Sep 2022 12:20:08 +0200 Subject: [PATCH 107/119] Revert "Revert "drm/bridge: ti-sn65dsi86: Implement bridge connector operations for DP"" This commit was accidentally reverted instead of another commit, and therefore needs to be reinstated. This reverts commit 8c9c40ec83445b188fb6b59e119bf5c2de81b02d. Fixes: 8c9c40ec8344 ("Revert "drm/bridge: ti-sn65dsi86: Implement bridge connector operations for DP"") Signed-off-by: Robert Foss Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20220919102009.150503-2-robert.foss@linaro.org --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 6e053e2af2299..3c3561942eb66 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,7 @@ #define BPP_18_RGB BIT(0) #define SN_HPD_DISABLE_REG 0x5C #define HPD_DISABLE BIT(0) +#define HPD_DEBOUNCED_STATE BIT(4) #define SN_GPIO_IO_REG 0x5E #define SN_GPIO_INPUT_SHIFT 4 #define SN_GPIO_OUTPUT_SHIFT 0 @@ -1158,10 +1160,33 @@ static void ti_sn_bridge_atomic_post_disable(struct drm_bridge *bridge, pm_runtime_put_sync(pdata->dev); } +static enum drm_connector_status ti_sn_bridge_detect(struct drm_bridge *bridge) +{ + struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + int val = 0; + + pm_runtime_get_sync(pdata->dev); + regmap_read(pdata->regmap, SN_HPD_DISABLE_REG, &val); + pm_runtime_put_autosuspend(pdata->dev); + + return val & HPD_DEBOUNCED_STATE ? connector_status_connected + : connector_status_disconnected; +} + +static struct edid *ti_sn_bridge_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + + return drm_get_edid(connector, &pdata->aux.ddc); +} + static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .attach = ti_sn_bridge_attach, .detach = ti_sn_bridge_detach, .mode_valid = ti_sn_bridge_mode_valid, + .get_edid = ti_sn_bridge_get_edid, + .detect = ti_sn_bridge_detect, .atomic_pre_enable = ti_sn_bridge_atomic_pre_enable, .atomic_enable = ti_sn_bridge_atomic_enable, .atomic_disable = ti_sn_bridge_atomic_disable, @@ -1257,6 +1282,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP; + if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) + pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT; + drm_bridge_add(&pdata->bridge); ret = ti_sn_attach_host(pdata); From ed712d30a9d0b8a59d6ed001cc7711d7b9c5ce54 Mon Sep 17 00:00:00 2001 From: Robert Foss Date: Mon, 19 Sep 2022 12:20:09 +0200 Subject: [PATCH 108/119] Revert "drm/bridge: chrontel-ch7033: Add byteswap order setting" Revert this patch since it depends on devicetree functionality that previously has been reverted in the below commit. commit e798ba3374a1 ("Revert "dt-bindings: Add byteswap order to chrontel ch7033"") This reverts commit ce9564cfc9aea65e68eb343c599317633bc2321a. Signed-off-by: Robert Foss Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20220919102009.150503-3-robert.foss@linaro.org --- drivers/gpu/drm/bridge/chrontel-ch7033.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c index c5719908ce2db..ba060277c3fdf 100644 --- a/drivers/gpu/drm/bridge/chrontel-ch7033.c +++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c @@ -68,7 +68,6 @@ enum { BYTE_SWAP_GBR = 3, BYTE_SWAP_BRG = 4, BYTE_SWAP_BGR = 5, - BYTE_SWAP_MAX = 6, }; /* Page 0, Register 0x19 */ @@ -356,8 +355,6 @@ static void ch7033_bridge_mode_set(struct drm_bridge *bridge, int hsynclen = mode->hsync_end - mode->hsync_start; int vbporch = mode->vsync_start - mode->vdisplay; int vsynclen = mode->vsync_end - mode->vsync_start; - u8 byte_swap; - int ret; /* * Page 4 @@ -401,16 +398,8 @@ static void ch7033_bridge_mode_set(struct drm_bridge *bridge, regmap_write(priv->regmap, 0x15, vbporch); regmap_write(priv->regmap, 0x16, vsynclen); - /* Input color swap. Byte order is optional and will default to - * BYTE_SWAP_BGR to preserve backwards compatibility with existing - * driver. - */ - ret = of_property_read_u8(priv->bridge.of_node, "chrontel,byteswap", - &byte_swap); - if (!ret && byte_swap < BYTE_SWAP_MAX) - regmap_update_bits(priv->regmap, 0x18, SWAP, byte_swap); - else - regmap_update_bits(priv->regmap, 0x18, SWAP, BYTE_SWAP_BGR); + /* Input color swap. */ + regmap_update_bits(priv->regmap, 0x18, SWAP, BYTE_SWAP_BGR); /* Input clock and sync polarity. */ regmap_update_bits(priv->regmap, 0x19, 0x1, mode->clock >> 16); From 3cc3dd73c420dc70cd366f91a680035ef47edf4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 19 Sep 2022 14:00:33 +0200 Subject: [PATCH 109/119] dma-buf: fix dma_fence_default_wait() signaling check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That check must now come after grabing the spinlock, not before. Signed-off-by: Christian König Fixes: b96fb1e724ae ("dma-buf: dma_fence_wait must enable signaling") Acked-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20220919120618.113332-1-christian.koenig@amd.com --- drivers/dma-buf/dma-fence.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index a5fbf1c1e0ea2..406b4e26f538f 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -763,11 +763,11 @@ dma_fence_default_wait(struct dma_fence *fence, bool intr, signed long timeout) unsigned long flags; signed long ret = timeout ? timeout : 1; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - return ret; - spin_lock_irqsave(fence->lock, flags); + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + goto out; + if (intr && signal_pending(current)) { ret = -ERESTARTSYS; goto out; From ee34b77f681e9656d229b1df48ea67f019bb6335 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 19 Sep 2022 18:30:58 +0800 Subject: [PATCH 110/119] drm/atomic-helper: Fix kernel-doc drivers/gpu/drm/drm_atomic_helper.c:802: warning: expecting prototype for drm_atomic_helper_check_wb_connector_state(). Prototype was for drm_atomic_helper_check_wb_encoder_state() instead. Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=2216 Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220919103058.25561-1-jiapeng.chong@linux.alibaba.com --- drivers/gpu/drm/drm_atomic_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ee5fea48b5cb8..98cc3137c0625 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -786,7 +786,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, EXPORT_SYMBOL(drm_atomic_helper_check_modeset); /** - * drm_atomic_helper_check_wb_connector_state() - Check writeback encoder state + * drm_atomic_helper_check_wb_encoder_state() - Check writeback encoder state * @encoder: encoder state to check * @conn_state: connector state to check * From 7221941c4f3249f6e67090820c827326e2e4459f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 9 Sep 2022 12:59:44 +0200 Subject: [PATCH 111/119] drm/plane: Remove drm_plane_init() Open-code drm_plane_init() and remove the function from DRM. The implementation of drm_plane_init() is a simple wrapper around a call to drm_universal_plane_init(), so drivers can just use that instead. Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Reviewed-by: Lyude Paul # nouveau Acked-by: Jyri Sarha Link: https://patchwork.freedesktop.org/patch/msgid/20220909105947.6487-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_modeset_helper.c | 3 +- drivers/gpu/drm/drm_plane.c | 32 ---------------------- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 13 +++++---- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 7 +++-- drivers/gpu/drm/tilcdc/tilcdc_plane.c | 9 +++--- include/drm/drm_plane.h | 8 +----- 6 files changed, 17 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index bd609a9788481..611dd01fb6048 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -100,8 +100,7 @@ EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); * This is the minimal list of formats that seem to be safe for modeset use * with all current DRM drivers. Most hardware can actually support more * formats than this and drivers may specify a more accurate list when - * creating the primary plane. However drivers that still call - * drm_plane_init() will use this minimal format list as the default. + * creating the primary plane. */ static const uint32_t safe_modeset_formats[] = { DRM_FORMAT_XRGB8888, diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 726f2f163c269..0f14b4d3bb109 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -482,38 +482,6 @@ void drm_plane_unregister_all(struct drm_device *dev) } } -/** - * drm_plane_init - Initialize a legacy plane - * @dev: DRM device - * @plane: plane object to init - * @possible_crtcs: bitmask of possible CRTCs - * @funcs: callbacks for the new plane - * @formats: array of supported formats (DRM_FORMAT\_\*) - * @format_count: number of elements in @formats - * @is_primary: plane type (primary vs overlay) - * - * Legacy API to initialize a DRM plane. - * - * New drivers should call drm_universal_plane_init() instead. - * - * Returns: - * Zero on success, error code on failure. - */ -int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, - uint32_t possible_crtcs, - const struct drm_plane_funcs *funcs, - const uint32_t *formats, unsigned int format_count, - bool is_primary) -{ - enum drm_plane_type type; - - type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; - return drm_universal_plane_init(dev, plane, possible_crtcs, funcs, - formats, format_count, - NULL, type, NULL); -} -EXPORT_SYMBOL(drm_plane_init); - /** * drm_plane_cleanup - Clean up the core plane usage * @plane: plane to cleanup diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index 37e63e98cd08a..33f29736024a5 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -296,9 +296,10 @@ nv10_overlay_init(struct drm_device *device) break; } - ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */, - &nv10_plane_funcs, - formats, num_formats, false); + ret = drm_universal_plane_init(device, &plane->base, 3 /* both crtc's */, + &nv10_plane_funcs, + formats, num_formats, NULL, + DRM_PLANE_TYPE_OVERLAY, NULL); if (ret) goto err; @@ -475,9 +476,9 @@ nv04_overlay_init(struct drm_device *device) if (!plane) return; - ret = drm_plane_init(device, &plane->base, 1 /* single crtc */, - &nv04_plane_funcs, - formats, 2, false); + ret = drm_universal_plane_init(device, &plane->base, 1 /* single crtc */, + &nv04_plane_funcs, formats, 2, NULL, + DRM_PLANE_TYPE_OVERLAY, NULL); if (ret) goto err; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 54228424793a7..6c5f0cbe7d95b 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -252,9 +252,10 @@ int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index) splane->index = index; splane->alpha = 255; - ret = drm_plane_init(sdev->ddev, &splane->plane, 1, - &shmob_drm_plane_funcs, formats, - ARRAY_SIZE(formats), false); + ret = drm_universal_plane_init(sdev->ddev, &splane->plane, 1, + &shmob_drm_plane_funcs, + formats, ARRAY_SIZE(formats), NULL, + DRM_PLANE_TYPE_OVERLAY, NULL); return ret; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c index 0ccf791301cbd..cf77a8ce73980 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c @@ -105,11 +105,10 @@ int tilcdc_plane_init(struct drm_device *dev, struct tilcdc_drm_private *priv = dev->dev_private; int ret; - ret = drm_plane_init(dev, plane, 1, - &tilcdc_plane_funcs, - priv->pixelformats, - priv->num_pixelformats, - true); + ret = drm_universal_plane_init(dev, plane, 1, &tilcdc_plane_funcs, + priv->pixelformats, + priv->num_pixelformats, + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) { dev_err(dev->dev, "Failed to initialize plane: %d\n", ret); return ret; diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 89ea54652e874..910cb941f3d52 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -631,7 +631,7 @@ struct drm_plane { unsigned int format_count; /** * @format_default: driver hasn't supplied supported formats for the - * plane. Used by the drm_plane_init compatibility wrapper only. + * plane. Used by the non-atomic driver compatibility wrapper only. */ bool format_default; @@ -762,12 +762,6 @@ int drm_universal_plane_init(struct drm_device *dev, const uint64_t *format_modifiers, enum drm_plane_type type, const char *name, ...); -int drm_plane_init(struct drm_device *dev, - struct drm_plane *plane, - uint32_t possible_crtcs, - const struct drm_plane_funcs *funcs, - const uint32_t *formats, unsigned int format_count, - bool is_primary); void drm_plane_cleanup(struct drm_plane *plane); __printf(10, 11) From e71def057252c0b5189618ecbc7141b56db4a74b Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 9 Sep 2022 12:59:45 +0200 Subject: [PATCH 112/119] drm/plane: Allocate planes with drm_universal_plane_alloc() Provide drm_univeral_plane_alloc() to allocate and initialize a plane. Code for non-atomic drivers uses this pattern. Convert them to the new function. The modeset helpers contain a quirk for handling their color formats differently. Set the flag outside plane allocation. The new function is already deprecated to some extend. Drivers should rather use drmm_univeral_plane_alloc() or drm_universal_plane_init(). v2: * kerneldoc fixes (Javier) * grammar fixes in commit message Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: Lyude Paul # nouveau Link: https://patchwork.freedesktop.org/patch/msgid/20220909105947.6487-3-tzimmermann@suse.de --- drivers/gpu/drm/drm_modeset_helper.c | 61 +++++++++++-------------- drivers/gpu/drm/drm_plane.c | 38 +++++++++++++++ drivers/gpu/drm/nouveau/dispnv04/crtc.c | 41 ++++++----------- include/drm/drm_plane.h | 44 ++++++++++++++++++ 4 files changed, 121 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 611dd01fb6048..38040eebfa163 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -113,38 +113,6 @@ static const struct drm_plane_funcs primary_plane_funcs = { .destroy = drm_plane_helper_destroy, }; -static struct drm_plane *create_primary_plane(struct drm_device *dev) -{ - struct drm_plane *primary; - int ret; - - primary = kzalloc(sizeof(*primary), GFP_KERNEL); - if (primary == NULL) { - DRM_DEBUG_KMS("Failed to allocate primary plane\n"); - return NULL; - } - - /* - * Remove the format_default field from drm_plane when dropping - * this helper. - */ - primary->format_default = true; - - /* possible_crtc's will be filled in later by crtc_init */ - ret = drm_universal_plane_init(dev, primary, 0, - &primary_plane_funcs, - safe_modeset_formats, - ARRAY_SIZE(safe_modeset_formats), - NULL, - DRM_PLANE_TYPE_PRIMARY, NULL); - if (ret) { - kfree(primary); - primary = NULL; - } - - return primary; -} - /** * drm_crtc_init - Legacy CRTC initialization function * @dev: DRM device @@ -176,10 +144,33 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, const struct drm_crtc_funcs *funcs) { struct drm_plane *primary; + int ret; + + /* possible_crtc's will be filled in later by crtc_init */ + primary = __drm_universal_plane_alloc(dev, sizeof(*primary), 0, 0, + &primary_plane_funcs, + safe_modeset_formats, + ARRAY_SIZE(safe_modeset_formats), + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (IS_ERR(primary)) + return PTR_ERR(primary); - primary = create_primary_plane(dev); - return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs, - NULL); + /* + * Remove the format_default field from drm_plane when dropping + * this helper. + */ + primary->format_default = true; + + ret = drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs, NULL); + if (ret) + goto err_drm_plane_cleanup; + + return 0; + +err_drm_plane_cleanup: + drm_plane_cleanup(primary); + kfree(primary); + return ret; } EXPORT_SYMBOL(drm_crtc_init); diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 0f14b4d3bb109..33357629a7f52 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -448,6 +448,44 @@ void *__drmm_universal_plane_alloc(struct drm_device *dev, size_t size, } EXPORT_SYMBOL(__drmm_universal_plane_alloc); +void *__drm_universal_plane_alloc(struct drm_device *dev, size_t size, + size_t offset, uint32_t possible_crtcs, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, unsigned int format_count, + const uint64_t *format_modifiers, + enum drm_plane_type type, + const char *name, ...) +{ + void *container; + struct drm_plane *plane; + va_list ap; + int ret; + + if (drm_WARN_ON(dev, !funcs)) + return ERR_PTR(-EINVAL); + + container = kzalloc(size, GFP_KERNEL); + if (!container) + return ERR_PTR(-ENOMEM); + + plane = container + offset; + + va_start(ap, name); + ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs, + formats, format_count, format_modifiers, + type, name, ap); + va_end(ap); + if (ret) + goto err_kfree; + + return container; + +err_kfree: + kfree(container); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(__drm_universal_plane_alloc); + int drm_plane_register_all(struct drm_device *dev) { unsigned int num_planes = 0; diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 660c4cbc0b3d9..6b8a014b5e97e 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1281,32 +1281,6 @@ static const struct drm_plane_funcs nv04_primary_plane_funcs = { .destroy = drm_plane_helper_destroy, }; -static struct drm_plane * -create_primary_plane(struct drm_device *dev) -{ - struct drm_plane *primary; - int ret; - - primary = kzalloc(sizeof(*primary), GFP_KERNEL); - if (primary == NULL) { - DRM_DEBUG_KMS("Failed to allocate primary plane\n"); - return NULL; - } - - /* possible_crtc's will be filled in later by crtc_init */ - ret = drm_universal_plane_init(dev, primary, 0, - &nv04_primary_plane_funcs, - modeset_formats, - ARRAY_SIZE(modeset_formats), NULL, - DRM_PLANE_TYPE_PRIMARY, NULL); - if (ret) { - kfree(primary); - primary = NULL; - } - - return primary; -} - static int nv04_crtc_vblank_handler(struct nvif_notify *notify) { struct nouveau_crtc *nv_crtc = @@ -1321,6 +1295,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) { struct nouveau_display *disp = nouveau_display(dev); struct nouveau_crtc *nv_crtc; + struct drm_plane *primary; int ret; nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); @@ -1335,8 +1310,18 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) nv_crtc->save = nv_crtc_save; nv_crtc->restore = nv_crtc_restore; - drm_crtc_init_with_planes(dev, &nv_crtc->base, - create_primary_plane(dev), NULL, + primary = __drm_universal_plane_alloc(dev, sizeof(*primary), 0, 0, + &nv04_primary_plane_funcs, + modeset_formats, + ARRAY_SIZE(modeset_formats), NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (IS_ERR(primary)) { + ret = PTR_ERR(primary); + kfree(nv_crtc); + return ret; + } + + drm_crtc_init_with_planes(dev, &nv_crtc->base, primary, NULL, &nv04_crtc_funcs, NULL); drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 910cb941f3d52..447e664e49d50 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -809,6 +809,50 @@ void *__drmm_universal_plane_alloc(struct drm_device *dev, format_count, format_modifiers, \ plane_type, name, ##__VA_ARGS__)) +__printf(10, 11) +void *__drm_universal_plane_alloc(struct drm_device *dev, + size_t size, size_t offset, + uint32_t possible_crtcs, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, + unsigned int format_count, + const uint64_t *format_modifiers, + enum drm_plane_type plane_type, + const char *name, ...); + +/** + * drm_universal_plane_alloc() - Allocate and initialize an universal plane object + * @dev: DRM device + * @type: the type of the struct which contains struct &drm_plane + * @member: the name of the &drm_plane within @type + * @possible_crtcs: bitmask of possible CRTCs + * @funcs: callbacks for the new plane + * @formats: array of supported formats (DRM_FORMAT\_\*) + * @format_count: number of elements in @formats + * @format_modifiers: array of struct drm_format modifiers terminated by + * DRM_FORMAT_MOD_INVALID + * @plane_type: type of plane (overlay, primary, cursor) + * @name: printf style format string for the plane name, or NULL for default name + * + * Allocates and initializes a plane object of type @type. The caller + * is responsible for releasing the allocated memory with kfree(). + * + * Drivers are encouraged to use drmm_universal_plane_alloc() instead. + * + * Drivers that only support the DRM_FORMAT_MOD_LINEAR modifier support may set + * @format_modifiers to NULL. The plane will advertise the linear modifier. + * + * Returns: + * Pointer to new plane, or ERR_PTR on failure. + */ +#define drm_universal_plane_alloc(dev, type, member, possible_crtcs, funcs, formats, \ + format_count, format_modifiers, plane_type, name, ...) \ + ((type *)__drm_universal_plane_alloc(dev, sizeof(type), \ + offsetof(type, member), \ + possible_crtcs, funcs, formats, \ + format_count, format_modifiers, \ + plane_type, name, ##__VA_ARGS__)) + /** * drm_plane_index - find the index of a registered plane * @plane: plane to find index for From fa0706e9775c10a9028e0b8d74c274cd4a179fda Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 9 Sep 2022 12:59:46 +0200 Subject: [PATCH 113/119] drm/plane-helper: Warn if atomic drivers call non-atomic helpers The plane update and disable helpers are only useful for non-atomic drivers. Print a warning if an atomic driver calls them. Suggested-by: Daniel Vetter Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20220909105947.6487-4-tzimmermann@suse.de --- drivers/gpu/drm/drm_plane_helper.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index db04d9a32ce83..865bd999b187d 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -30,8 +30,10 @@ #include #include #include +#include #include #include +#include #include #define SUBPIXEL_MASK 0xffff @@ -195,10 +197,14 @@ int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *cr .x2 = crtc_x + crtc_w, .y2 = crtc_y + crtc_h, }; + struct drm_device *dev = plane->dev; struct drm_connector **connector_list; int num_connectors, ret; bool visible; + if (drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev))) + return -EINVAL; + ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, DRM_MODE_ROTATE_0, @@ -260,6 +266,10 @@ EXPORT_SYMBOL(drm_plane_helper_update_primary); int drm_plane_helper_disable_primary(struct drm_plane *plane, struct drm_modeset_acquire_ctx *ctx) { + struct drm_device *dev = plane->dev; + + drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev)); + return -EINVAL; } EXPORT_SYMBOL(drm_plane_helper_disable_primary); From 02d6f9a13ef3316da5c64540c5a376f07781c853 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 9 Sep 2022 12:59:47 +0200 Subject: [PATCH 114/119] drm/plane-helper: Provide DRM_PLANE_NON_ATOMIC_FUNCS initializer macro Provide DRM_PLANE_NON_ATOMIC_FUNCS, which initializes plane functions of non-atomic drivers to default values. The macro is not supposed to be used in new code, but helps with documenting and finding existing users. Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Reviewed-by: Lyude Paul # nouveau Link: https://patchwork.freedesktop.org/patch/msgid/20220909105947.6487-5-tzimmermann@suse.de --- drivers/gpu/drm/drm_modeset_helper.c | 4 +--- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 4 +--- include/drm/drm_plane_helper.h | 12 ++++++++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 38040eebfa163..f858dfedf2cfc 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -108,9 +108,7 @@ static const uint32_t safe_modeset_formats[] = { }; static const struct drm_plane_funcs primary_plane_funcs = { - .update_plane = drm_plane_helper_update_primary, - .disable_plane = drm_plane_helper_disable_primary, - .destroy = drm_plane_helper_destroy, + DRM_PLANE_NON_ATOMIC_FUNCS, }; /** diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 6b8a014b5e97e..ee92d576d2777 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1276,9 +1276,7 @@ static const uint32_t modeset_formats[] = { }; static const struct drm_plane_funcs nv04_primary_plane_funcs = { - .update_plane = drm_plane_helper_update_primary, - .disable_plane = drm_plane_helper_disable_primary, - .destroy = drm_plane_helper_destroy, + DRM_PLANE_NON_ATOMIC_FUNCS, }; static int nv04_crtc_vblank_handler(struct nvif_notify *notify) diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 7760b27b0323c..ff83d26216876 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -43,4 +43,16 @@ int drm_plane_helper_disable_primary(struct drm_plane *plane, void drm_plane_helper_destroy(struct drm_plane *plane); int drm_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state); +/** + * DRM_PLANE_NON_ATOMIC_FUNCS - Default plane functions for non-atomic drivers + * + * This macro initializes plane functions for non-atomic drivers to default + * values. Non-atomic interfaces are deprecated and should not be used in new + * drivers. + */ +#define DRM_PLANE_NON_ATOMIC_FUNCS \ + .update_plane = drm_plane_helper_update_primary, \ + .disable_plane = drm_plane_helper_disable_primary, \ + .destroy = drm_plane_helper_destroy + #endif From 71dee0361bd04f31c37525e69817654c6e23c97a Mon Sep 17 00:00:00 2001 From: Jammy Huang Date: Fri, 16 Sep 2022 16:50:58 +0800 Subject: [PATCH 115/119] drm/ast: Add resolution support for 1152x864@75 Add 1152x864 into support list. Signed-off-by: Jammy Huang Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220916085058.3386-1-jammy_huang@aspeedtech.com --- drivers/gpu/drm/ast/ast_mode.c | 9 +++++++++ drivers/gpu/drm/ast/ast_tables.h | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 103bd4fa698bd..b613344096377 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -113,6 +113,9 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, case 1024: vbios_mode->enh_table = &res_1024x768[refresh_rate_index]; break; + case 1152: + vbios_mode->enh_table = &res_1152x864[refresh_rate_index]; + break; case 1280: if (mode->crtc_vdisplay == 800) vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; @@ -1057,6 +1060,8 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode return MODE_OK; if ((mode->hdisplay == 1600) && (mode->vdisplay == 900)) return MODE_OK; + if ((mode->hdisplay == 1152) && (mode->vdisplay == 864)) + return MODE_OK; if ((ast->chip == AST2100) || (ast->chip == AST2200) || (ast->chip == AST2300) || (ast->chip == AST2400) || @@ -1089,6 +1094,10 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode if (mode->vdisplay == 768) status = MODE_OK; break; + case 1152: + if (mode->vdisplay == 864) + status = MODE_OK; + break; case 1280: if (mode->vdisplay == 1024) status = MODE_OK; diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h index dbe1cc620f6e6..0378c9bc079b0 100644 --- a/drivers/gpu/drm/ast/ast_tables.h +++ b/drivers/gpu/drm/ast/ast_tables.h @@ -272,6 +272,13 @@ static const struct ast_vbios_enhtable res_1600x1200[] = { (SyncPP | Charx8Dot), 0xFF, 1, 0x33 }, }; +static const struct ast_vbios_enhtable res_1152x864[] = { + {1600, 1152, 64, 128, 900, 864, 1, 3, VCLK108, /* 75Hz */ + (SyncPP | Charx8Dot | NewModeInfo), 75, 1, 0x3B }, + {1600, 1152, 64, 128, 900, 864, 1, 3, VCLK108, /* end */ + (SyncPP | Charx8Dot | NewModeInfo), 0xFF, 1, 0x3B }, +}; + /* 16:9 */ static const struct ast_vbios_enhtable res_1360x768[] = { {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */ From d6cbe630f3e9a5b11ba4082ff980ccc094224610 Mon Sep 17 00:00:00 2001 From: Jammy Huang Date: Fri, 16 Sep 2022 17:17:06 +0800 Subject: [PATCH 116/119] drm/ast: Fix video broken in some resolutions on ast2600 Some cases are not handled well for ast2600. Signed-off-by: Jammy Huang Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220916091706.4559-1-jammy_huang@aspeedtech.com --- drivers/gpu/drm/ast/ast_mode.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index b613344096377..1bc0220e6783e 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -313,7 +313,7 @@ static void ast_set_crtc_reg(struct ast_private *ast, u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0; u16 temp, precache = 0; - if ((ast->chip == AST2500) && + if ((ast->chip == AST2500 || ast->chip == AST2600) && (vbios_mode->enh_table->flags & AST2500PreCatchCRT)) precache = 40; @@ -354,6 +354,12 @@ static void ast_set_crtc_reg(struct ast_private *ast, ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAC, 0x00, jregAC); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAD, 0x00, jregAD); + // Workaround for HSync Time non octave pixels (1920x1080@60Hz HSync 44 pixels); + if ((ast->chip == AST2600) && (mode->crtc_vdisplay == 1080)) + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xFC, 0xFD, 0x02); + else + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xFC, 0xFD, 0x00); + /* vert timings */ temp = (mode->crtc_vtotal) - 2; if (temp & 0x100) @@ -431,7 +437,7 @@ static void ast_set_dclk_reg(struct ast_private *ast, { const struct ast_vbios_dclk_info *clk_info; - if (ast->chip == AST2500) + if ((ast->chip == AST2500) || (ast->chip == AST2600)) clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index]; else clk_info = &dclk_table[vbios_mode->enh_table->dclk_index]; From 110ae8a21bbe779a133c1672a1463105c9d50590 Mon Sep 17 00:00:00 2001 From: Minghao Chi Date: Mon, 19 Sep 2022 03:04:01 +0000 Subject: [PATCH 117/119] drm: bridge/dw-hdmi-ahb-audio: use strscpy() is more robust and safer The implementation of strscpy() is more robust and safer. That's now the recommended way to copy NUL terminated strings. Reported-by: Zeal Robot Signed-off-by: Minghao Chi Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20220919030401.211331-1-chi.minghao@zte.com.cn --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c index 7d2ed0ed2fe26..4efb62bcdb634 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c @@ -542,8 +542,8 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) if (ret < 0) return ret; - strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); - strlcpy(card->shortname, "DW-HDMI", sizeof(card->shortname)); + strscpy(card->driver, DRIVER_NAME, sizeof(card->driver)); + strscpy(card->shortname, "DW-HDMI", sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "%s rev 0x%02x, irq %d", card->shortname, revision, data->irq); @@ -561,7 +561,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) dw->pcm = pcm; pcm->private_data = dw; - strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); + strscpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dw_hdmi_ops); /* From a40c7f61d12fbd1e785e59140b9efd57127c0c33 Mon Sep 17 00:00:00 2001 From: Rafael Mendonca Date: Fri, 16 Sep 2022 17:47:51 -0300 Subject: [PATCH 118/119] drm/vmwgfx: Fix memory leak in vmw_mksstat_add_ioctl() If the copy of the description string from userspace fails, then the page for the instance descriptor doesn't get freed before returning -EFAULT, which leads to a memleak. Fixes: 7a7a933edd6c ("drm/vmwgfx: Introduce VMware mks-guest-stats") Signed-off-by: Rafael Mendonca Reviewed-by: Martin Krastev Signed-off-by: Zack Rusin Link: https://patchwork.freedesktop.org/patch/msgid/20220916204751.720716-1-rafaelmendsr@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c index 2aceac7856e21..089046fa21bea 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c @@ -1076,6 +1076,7 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data, if (desc_len < 0) { atomic_set(&dev_priv->mksstat_user_pids[slot], 0); + __free_page(page); return -EFAULT; } From 39dd0cc2e5bd0d5188dd69f27e18783cea7ff06a Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam Date: Thu, 22 Sep 2022 08:14:47 -0700 Subject: [PATCH 119/119] drm/amdgpu: Fix VRAM eviction issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A user reported that when he starts a game (MTGA) with wine, he observed an error msg failed to pin framebuffer with error -12. Found an issue with the VRAM mem type eviction decision condition logic. This patch will fix the if condition code error. Gitlab bug link: https://gitlab.freedesktop.org/drm/amd/-/issues/2159 Fixes: ded910f368a5 ("drm/amdgpu: Implement intersect/compatible functions") Signed-off-by: Arunpravin Paneer Selvam Link: https://patchwork.freedesktop.org/patch/msgid/20220922151447.265696-1-Arunpravin.PaneerSelvam@amd.com Reviewed-by: Christian König Signed-off-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index d1a2619fa89f8..73a517bcf5c11 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -746,7 +746,7 @@ static bool amdgpu_vram_mgr_intersects(struct ttm_resource_manager *man, (amdgpu_vram_mgr_block_size(block) >> PAGE_SHIFT); if (place->fpfn < lpfn && - (place->lpfn && place->lpfn > fpfn)) + (!place->lpfn || place->lpfn > fpfn)) return true; }