drm/amd/display: Program CURSOR_DST_X_OFFSET in viewport space
authorAlvin Lee <alvin.lee2@amd.com>
Thu, 13 Jun 2024 20:10:16 +0000 (16:10 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 27 Jun 2024 21:10:37 +0000 (17:10 -0400)
[WHAT & HOW]
According to register specifications, the CURSOR_DST_X_OFFSET
is relative to the start of the data viewport, not RECOUT space.
In this case we must transform the cursor coordinates passed to
hubp401_cursor_set_position into viewport space to program this
register. This fixes an underflow issue that occurs in scaled
mode with low refresh rate.

Reviewed-by: Nevenko Stupar <nevenko.stupar@amd.com>
Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Alvin Lee <alvin.lee2@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c

index a893160ae77587517fc27790dc580e7a45efe90a..3f9ca9b40949f489f38128d94aae535e8a5c2922 100644 (file)
@@ -656,7 +656,9 @@ void hubp401_cursor_set_position(
        int y_pos = pos->y - param->recout.y;
        int rec_x_offset = x_pos - pos->x_hotspot;
        int rec_y_offset = y_pos - pos->y_hotspot;
-       uint32_t dst_x_offset;
+       int dst_x_offset;
+       int x_pos_viewport = x_pos * param->viewport.width / param->recout.width;
+       int x_hot_viewport = pos->x_hotspot * param->viewport.width / param->recout.width;
        uint32_t cur_en = pos->enable ? 1 : 0;
 
        hubp->curs_pos = *pos;
@@ -668,7 +670,13 @@ void hubp401_cursor_set_position(
        if (hubp->curs_attr.address.quad_part == 0)
                return;
 
-       dst_x_offset = (rec_x_offset >= 0) ? rec_x_offset : 0;
+       /* Translate the x position of the cursor from rect
+        * space into viewport space. CURSOR_DST_X_OFFSET
+        * is the offset relative to viewport start position.
+        */
+       dst_x_offset = x_pos_viewport - x_hot_viewport *
+                       (1 + hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION);
+       dst_x_offset = (dst_x_offset >= 0) ? dst_x_offset : 0;
        dst_x_offset *= param->ref_clk_khz;
        dst_x_offset /= param->pixel_clk_khz;