]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/display: Use overlay cursor when color pipeline is active
authorAlex Hung <alex.hung@amd.com>
Wed, 25 Mar 2026 02:03:25 +0000 (20:03 -0600)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 17 Apr 2026 19:23:43 +0000 (15:23 -0400)
Force overlay cursor mode when an underlying plane has a non-bypassed
color pipeline to avoid incorrect cursor transformation.

Reviewed-by: Sun peng (Leo) Li <sunpeng.li@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index f4be2724471d299d56625bcccad61e76b6b70e42..1ecac2174119e11e2cf2a26f38bbf9f2c326ff28 100644 (file)
@@ -95,6 +95,7 @@
 #include <drm/drm_utils.h>
 #include <drm/drm_vblank.h>
 #include <drm/drm_audio_component.h>
+#include <drm/drm_colorop.h>
 #include <drm/drm_gem_atomic_helper.h>
 
 #include <media/cec-notifier.h>
@@ -12338,6 +12339,38 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
  * available.
  */
 
+/**
+ * dm_plane_color_pipeline_active() - Check if a plane's color pipeline active.
+ * @state: DRM atomic state
+ * @plane: DRM plane to check
+ * @use_old: if true, inspect the old colorop states; otherwise the new ones
+ *
+ * A color pipeline may be selected (color_pipeline != NULL) but still is
+ * inactive if every colorop in the chain is bypassed.  Only return
+ * true when at least one colorop has bypass == false, meaning the cursor
+ * would be subjected to the transformation in native mode.
+ *
+ * Return: true if the pipeline modifies pixels, false otherwise.
+ */
+static bool dm_plane_color_pipeline_active(struct drm_atomic_state *state,
+                                          struct drm_plane *plane,
+                                          bool use_old)
+{
+       struct drm_colorop *colorop;
+       struct drm_colorop_state *old_colorop_state, *new_colorop_state;
+       int i;
+
+       for_each_oldnew_colorop_in_state(state, colorop, old_colorop_state, new_colorop_state, i) {
+               struct drm_colorop_state *cstate = use_old ? old_colorop_state : new_colorop_state;
+
+               if (cstate->colorop->plane != plane)
+                       continue;
+               if (!cstate->bypass)
+                       return true;
+       }
+       return false;
+}
+
 /**
  * dm_crtc_get_cursor_mode() - Determine the required cursor mode on crtc
  * @adev: amdgpu device
@@ -12349,8 +12382,8 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
  * the dm_crtc_state.
  *
  * The cursor should be enabled in overlay mode if there exists an underlying
- * plane - on which the cursor may be blended - that is either YUV formatted, or
- * scaled differently from the cursor.
+ * plane - on which the cursor may be blended - that is either YUV formatted,
+ * scaled differently from the cursor, or has a color pipeline active.
  *
  * Since zpos info is required, drm_atomic_normalize_zpos must be called before
  * calling this function.
@@ -12388,7 +12421,7 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
 
        /*
         * Cursor mode can change if a plane's format changes, scale changes, is
-        * enabled/disabled, or z-order changes.
+        * enabled/disabled, z-order changes, or color management properties change.
         */
        for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) {
                int new_scale_w, new_scale_h, old_scale_w, old_scale_h;
@@ -12413,6 +12446,12 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
                        consider_mode_change = true;
                        break;
                }
+
+               if (dm_plane_color_pipeline_active(state, plane, true) !=
+                   dm_plane_color_pipeline_active(state, plane, false)) {
+                       consider_mode_change = true;
+                       break;
+               }
        }
 
        if (!consider_mode_change && !crtc_state->zpos_changed)
@@ -12453,6 +12492,12 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
                        return 0;
                }
 
+               /* Underlying plane has an active color pipeline - cursor would be transformed */
+               if (dm_plane_color_pipeline_active(state, plane, false)) {
+                       *cursor_mode = DM_CURSOR_OVERLAY_MODE;
+                       return 0;
+               }
+
                dm_get_plane_scale(plane_state,
                                   &underlying_scale_w, &underlying_scale_h);
                dm_get_plane_scale(cursor_state,
@@ -12832,7 +12877,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                        goto fail;
                } else if (required_cursor_mode == DM_CURSOR_OVERLAY_MODE) {
                        drm_dbg_driver(crtc->dev,
-                                      "[CRTC:%d:%s] Cannot enable native cursor due to scaling or YUV restrictions\n",
+                                      "[CRTC:%d:%s] Cannot enable native cursor due to scaling, YUV, or color pipeline restrictions\n",
                                       crtc->base.id, crtc->name);
                        ret = -EINVAL;
                        goto fail;