[PATCH 05/39] drm/amd/display: Fix cursor issues with ODMs and HW rotations
Alex Hung
alex.hung at amd.com
Thu Jun 20 16:11:11 UTC 2024
From: Nevenko Stupar <nevenko.stupar at amd.com>
[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 at amd.com>
Acked-by: Alex Hung <alex.hung at amd.com>
Signed-off-by: Nevenko Stupar <nevenko.stupar at amd.com>
---
.../amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c | 50 -------
.../amd/display/dc/hubp/dcn401/dcn401_hubp.c | 38 -----
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 135 +++---------------
3 files changed, 19 insertions(+), 204 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
index aef73bd1221a..d0f8c9ff5232 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
index 6692d57d5cce..a893160ae775 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 7a456618f313..8d0da56e4cc5 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -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, ¶m);
dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height);
--
2.34.1
More information about the amd-gfx
mailing list