drm/amd/display: Fix cursor issues with ODMs and HW rotations
authorNevenko Stupar <nevenko.stupar@amd.com>
Mon, 10 Jun 2024 19:32:05 +0000 (15:32 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 27 Jun 2024 21:10:36 +0000 (17:10 -0400)
[WHY & HOW]
Current code for cursor positions does not work properly
with different ODM options and HW rotations like ODM
2to1, 3to1 and 4to1, and has different issues depending on
angle of HW rotations.

[HOW]
Fixed these issues so to work properly when ODM is used with HW rotations.

Reviewed-by: Sridevi Arvindekar <sridevi.arvindekar@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Nevenko Stupar <nevenko.stupar@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/dpp/dcn401/dcn401_dpp_cm.c
drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c

index aef73bd1221a112e968e84288a2c9c8c9127f4c3..d0f8c9ff5232554a1fcb916e57a15f971b71c3a4 100644 (file)
@@ -153,58 +153,8 @@ void dpp401_set_cursor_position(
        uint32_t height)
 {
        struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
-       int x_pos = pos->x - param->recout.x;
-       int y_pos = pos->y - param->recout.y;
-       int x_hotspot = pos->x_hotspot;
-       int y_hotspot = pos->y_hotspot;
-       int rec_x_offset = x_pos - pos->x_hotspot;
-       int rec_y_offset = y_pos - pos->y_hotspot;
-       int cursor_height = (int)height;
-       int cursor_width = (int)width;
        uint32_t cur_en = pos->enable ? 1 : 0;
 
-       // Transform cursor width / height and hotspots for offset calculations
-       if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
-               swap(cursor_height, cursor_width);
-               swap(x_hotspot, y_hotspot);
-
-               if (param->rotation == ROTATION_ANGLE_90) {
-                       // hotspot = (-y, x)
-                       rec_x_offset = x_pos - (cursor_width - x_hotspot);
-                       rec_y_offset = y_pos - y_hotspot;
-               } else if (param->rotation == ROTATION_ANGLE_270) {
-                       // hotspot = (y, -x)
-                       rec_x_offset = x_pos - x_hotspot;
-                       rec_y_offset = y_pos - (cursor_height - y_hotspot);
-               }
-       } else if (param->rotation == ROTATION_ANGLE_180) {
-               // hotspot = (-x, -y)
-               if (!param->mirror)
-                       rec_x_offset = x_pos - (cursor_width - x_hotspot);
-
-               rec_y_offset = y_pos - (cursor_height - y_hotspot);
-       }
-
-       if (param->rotation == ROTATION_ANGLE_0 && !param->mirror) {
-               if (rec_x_offset >= (int)param->recout.width)
-                       cur_en = 0;  /* not visible beyond right edge*/
-
-               if (rec_y_offset >= (int)param->recout.height)
-                       cur_en = 0;  /* not visible beyond bottom edge*/
-       } else {
-               if (rec_x_offset > (int)param->recout.width)
-                       cur_en = 0;  /* not visible beyond right edge*/
-
-               if (rec_y_offset > (int)param->recout.height)
-                       cur_en = 0;  /* not visible beyond bottom edge*/
-       }
-
-       if (rec_x_offset + cursor_width <= 0)
-               cur_en = 0;  /* not visible beyond left edge*/
-
-       if (rec_y_offset + cursor_height <= 0)
-               cur_en = 0;  /* not visible beyond top edge*/
-
        REG_UPDATE(CURSOR0_CONTROL, CUR0_ENABLE, cur_en);
 
        dpp_base->pos.cur0_ctl.bits.cur0_enable = cur_en;
index 6692d57d5cce8560c74de2f0e6523995231e1d82..a893160ae77587517fc27790dc580e7a45efe90a 100644 (file)
@@ -654,12 +654,8 @@ void hubp401_cursor_set_position(
        struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
        int x_pos = pos->x - param->recout.x;
        int y_pos = pos->y - param->recout.y;
-       int x_hotspot = pos->x_hotspot;
-       int y_hotspot = pos->y_hotspot;
        int rec_x_offset = x_pos - pos->x_hotspot;
        int rec_y_offset = y_pos - pos->y_hotspot;
-       int cursor_height = (int)hubp->curs_attr.height;
-       int cursor_width = (int)hubp->curs_attr.width;
        uint32_t dst_x_offset;
        uint32_t cur_en = pos->enable ? 1 : 0;
 
@@ -672,28 +668,6 @@ void hubp401_cursor_set_position(
        if (hubp->curs_attr.address.quad_part == 0)
                return;
 
-       // Transform cursor width / height and hotspots for offset calculations
-       if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
-               swap(cursor_height, cursor_width);
-               swap(x_hotspot, y_hotspot);
-
-               if (param->rotation == ROTATION_ANGLE_90) {
-                       // hotspot = (-y, x)
-                       rec_x_offset = x_pos - (cursor_width - x_hotspot);
-                       rec_y_offset = y_pos - y_hotspot;
-               } else if (param->rotation == ROTATION_ANGLE_270) {
-                       // hotspot = (y, -x)
-                       rec_x_offset = x_pos - x_hotspot;
-                       rec_y_offset = y_pos - (cursor_height - y_hotspot);
-               }
-       } else if (param->rotation == ROTATION_ANGLE_180) {
-               // hotspot = (-x, -y)
-               if (!param->mirror)
-                       rec_x_offset = x_pos - (cursor_width - x_hotspot);
-
-               rec_y_offset = y_pos - (cursor_height - y_hotspot);
-       }
-
        dst_x_offset = (rec_x_offset >= 0) ? rec_x_offset : 0;
        dst_x_offset *= param->ref_clk_khz;
        dst_x_offset /= param->pixel_clk_khz;
@@ -705,18 +679,6 @@ void hubp401_cursor_set_position(
                        dc_fixpt_from_int(dst_x_offset),
                        param->h_scale_ratio));
 
-       if (rec_x_offset >= (int)param->recout.width)
-               cur_en = 0;  /* not visible beyond right edge*/
-
-       if (rec_x_offset + cursor_width <= 0)
-               cur_en = 0;  /* not visible beyond left edge*/
-
-       if (rec_y_offset >= (int)param->recout.height)
-               cur_en = 0;  /* not visible beyond bottom edge*/
-
-       if (rec_y_offset + cursor_height <= 0)
-               cur_en = 0;  /* not visible beyond top edge*/
-
        if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
                hubp->funcs->set_cursor_attributes(hubp, &hubp->curs_attr);
 
index 7a456618f31328eefc5c231a1f7f2e73e70bdc4b..8d0da56e4cc51b0c33df367547df665bdac44651 100644 (file)
@@ -1099,31 +1099,21 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
                .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
                .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
                .rotation = pipe_ctx->plane_state->rotation,
-               .mirror = pipe_ctx->plane_state->horizontal_mirror
+               .mirror = pipe_ctx->plane_state->horizontal_mirror,
+               .stream = pipe_ctx->stream
        };
-       bool pipe_split_on = false;
        bool odm_combine_on = (pipe_ctx->next_odm_pipe != NULL) ||
                (pipe_ctx->prev_odm_pipe != NULL);
        int prev_odm_width = 0;
        int prev_odm_offset = 0;
-       int next_odm_width = 0;
-       int next_odm_offset = 0;
-       struct pipe_ctx *next_odm_pipe = NULL;
        struct pipe_ctx *prev_odm_pipe = NULL;
 
        int x_pos = pos_cpy.x;
        int y_pos = pos_cpy.y;
+       int recout_x_pos = 0;
+       int recout_y_pos = 0;
 
-       if ((pipe_ctx->top_pipe != NULL) || (pipe_ctx->bottom_pipe != NULL)) {
-               if ((pipe_ctx->plane_state->src_rect.width != pipe_ctx->plane_res.scl_data.viewport.width) ||
-                       (pipe_ctx->plane_state->src_rect.height != pipe_ctx->plane_res.scl_data.viewport.height)) {
-                       pipe_split_on = true;
-               }
-       }
-
-
-       /**
-        * DCN4 moved cursor composition after Scaler, so in HW it is in
+       /* DCN4 moved cursor composition after Scaler, so in HW it is in
         * recout space and for HW Cursor position programming need to
         * translate to recout space.
         *
@@ -1148,8 +1138,7 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
        y_pos = pipe_ctx->stream->dst.y + y_pos * pipe_ctx->stream->dst.height /
                pipe_ctx->stream->src.height;
 
-       /**
-        * If the cursor's source viewport is clipped then we need to
+       /* If the cursor's source viewport is clipped then we need to
         * translate the cursor to appear in the correct position on
         * the screen.
         *
@@ -1169,38 +1158,15 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
         * next/prev_odm_offset is to account for scaled modes that have underscan
         */
        if (odm_combine_on) {
-               next_odm_pipe = pipe_ctx->next_odm_pipe;
                prev_odm_pipe = pipe_ctx->prev_odm_pipe;
 
-               while (next_odm_pipe != NULL) {
-                       next_odm_width += next_odm_pipe->plane_res.scl_data.recout.width;
-                       next_odm_offset += next_odm_pipe->plane_res.scl_data.recout.x;
-                       next_odm_pipe = next_odm_pipe->next_odm_pipe;
-               }
                while (prev_odm_pipe != NULL) {
                        prev_odm_width += prev_odm_pipe->plane_res.scl_data.recout.width;
                        prev_odm_offset += prev_odm_pipe->plane_res.scl_data.recout.x;
                        prev_odm_pipe = prev_odm_pipe->prev_odm_pipe;
                }
 
-               if (param.rotation == ROTATION_ANGLE_0) {
-                       x_pos -= (prev_odm_width + prev_odm_offset);
-               }
-       }
-
-       /**
-        * If the position is negative then we need to add to the hotspot
-        * to shift the cursor outside the plane.
-        */
-
-       if (x_pos < 0) {
-               pos_cpy.x_hotspot -= x_pos;
-               x_pos = 0;
-       }
-
-       if (y_pos < 0) {
-               pos_cpy.y_hotspot -= y_pos;
-               y_pos = 0;
+               x_pos -= (prev_odm_width + prev_odm_offset);
        }
 
        pos_cpy.x = (uint32_t)x_pos;
@@ -1209,86 +1175,23 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
        if (pos_cpy.enable && dcn401_can_pipe_disable_cursor(pipe_ctx))
                pos_cpy.enable = false;
 
-       if (param.rotation == ROTATION_ANGLE_270) {
-               // Swap axis and mirror vertically
-               uint32_t temp_x = pos_cpy.x;
+       x_pos = pos_cpy.x - param.recout.x;
+       y_pos = pos_cpy.y - param.recout.y;
 
-               int recout_height =
-                       pipe_ctx->plane_res.scl_data.recout.height;
-               int recout_y =
-                       pipe_ctx->plane_res.scl_data.recout.y;
+       recout_x_pos = x_pos - pos_cpy.x_hotspot;
+       recout_y_pos = y_pos - pos_cpy.y_hotspot;
 
-               /**
-                * Display groups that are 1xnY, have pos_cpy.x > 2 * recout.height
-                * For pipe split cases:
-                * - apply offset of recout.y to normalize pos_cpy.x
-                * - calculate the pos_cpy.y as before
-                * - shift pos_cpy.y back by same offset to get final value
-                * - since we iterate through both pipes, use the lower
-                *   recout.y for offset
-                * For non pipe split cases, use the same calculation for
-                *  pos_cpy.y as the 180 degree rotation case below,
-                *  but use pos_cpy.x as our input because we are rotating
-                *  270 degrees
-                */
-               if (pipe_split_on || odm_combine_on) {
-                       int pos_cpy_x_offset;
-                       int other_pipe_recout_y;
-
-                       if (pipe_split_on) {
-                               if (pipe_ctx->bottom_pipe) {
-                                       other_pipe_recout_y =
-                                               pipe_ctx->bottom_pipe->plane_res.scl_data.recout.y;
-                               } else {
-                                       other_pipe_recout_y =
-                                               pipe_ctx->top_pipe->plane_res.scl_data.recout.y;
-                               }
-                               pos_cpy_x_offset = (recout_y > other_pipe_recout_y) ?
-                                       other_pipe_recout_y : recout_y;
-                               pos_cpy.x -= pos_cpy_x_offset;
-                               if (pos_cpy.x > recout_height) {
-                                       pos_cpy.x = pos_cpy.x - recout_height;
-                                       pos_cpy.y = recout_height - pos_cpy.x;
-                               } else {
-                                       pos_cpy.y = 2 * recout_height - pos_cpy.x;
-                               }
-                               pos_cpy.y += pos_cpy_x_offset;
+       if (recout_x_pos >= (int)param.recout.width)
+               pos_cpy.enable = false;  /* not visible beyond right edge*/
 
-                       } else {
-                               pos_cpy.x = pipe_ctx->plane_res.scl_data.recout.width + next_odm_width + next_odm_offset - pos_cpy.y;
-                               pos_cpy.y = temp_x;
-                       }
-               }
-       } else if (param.rotation == ROTATION_ANGLE_180) {
-               // Mirror horizontally and vertically
-               int recout_width =
-                       pipe_ctx->plane_res.scl_data.recout.width;
-               int recout_x =
-                       pipe_ctx->plane_res.scl_data.recout.x;
-
-               if (!param.mirror) {
-                       if (odm_combine_on) {
-                               pos_cpy.x = pipe_ctx->plane_res.scl_data.recout.width + next_odm_width - pos_cpy.x;
-                       } else if (pipe_split_on) {
-                               if (pos_cpy.x >= recout_width + recout_x) {
-                                       pos_cpy.x = 2 * recout_width
-                                               - pos_cpy.x + 2 * recout_x;
-                               } else {
-                                       uint32_t temp_x = pos_cpy.x;
-
-                                       pos_cpy.x = 2 * recout_x - pos_cpy.x;
-                                       if (temp_x >= recout_x +
-                                               (int)hubp->curs_attr.width || pos_cpy.x
-                                               <= (int)hubp->curs_attr.width +
-                                               pipe_ctx->plane_state->src_rect.x) {
-                                               pos_cpy.x = temp_x + recout_width;
-                                       }
-                               }
-                       }
+       if (recout_y_pos >= (int)param.recout.height)
+               pos_cpy.enable = false;  /* not visible beyond bottom edge*/
 
-               }
+       if (recout_x_pos + (int)hubp->curs_attr.width <= 0)
+               pos_cpy.enable = false;  /* not visible beyond left edge*/
 
-       }
+       if (recout_y_pos + (int)hubp->curs_attr.height <= 0)
+               pos_cpy.enable = false;  /* not visible beyond top edge*/
 
        hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
        dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width, hubp->curs_attr.height);