]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: Fix cursor pos at overlay plane edges on DCN4
authorIvan Lipski <ivan.lipski@amd.com>
Mon, 2 Feb 2026 20:57:19 +0000 (15:57 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 23 Feb 2026 19:39:31 +0000 (14:39 -0500)
[Why&How]
On DCN4, when cursor straddles the left/top edge of an overlay plane, the
recout-relative position becomes negative. These negative values wrap
to large positive numbers when cast to uint32_t, causing the cursor on the
the overlay plane to disappear.

Fix by adding hotspot adjustment and position clamping after the
recout-relative calculation, matching the existing ODM/MPC slice
boundary handling.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c

index b91517b9fedcf203c6f353cd232a271282a32431..f604c30e8493f4410c668f5197992c30f1dbd91c 100644 (file)
@@ -1202,6 +1202,25 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
        x_pos = pos_cpy.x - param.recout.x;
        y_pos = pos_cpy.y - param.recout.y;
 
+       /**
+        * If the cursor position is negative after recout adjustment, we need
+        * to shift the hotspot to compensate and clamp position to 0. This
+        * handles the case where cursor straddles the left/top edge of an
+        * overlay plane - the cursor is partially visible and needs correct
+        * hotspot adjustment to render the visible portion.
+        */
+       if (x_pos < 0) {
+               pos_cpy.x_hotspot -= x_pos;
+               if (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION)
+                       adjust_hotspot_between_slices_for_2x_magnify(hubp->curs_attr.width, &pos_cpy);
+               x_pos = 0;
+       }
+
+       if (y_pos < 0) {
+               pos_cpy.y_hotspot -= y_pos;
+               y_pos = 0;
+       }
+
        recout_x_pos = x_pos - pos_cpy.x_hotspot;
        recout_y_pos = y_pos - pos_cpy.y_hotspot;