Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: ODM + MPO window on only one half of ODM

[Why]
For ODM + MPO window on one half of ODM, only 3 pipes should
be allocated and scaling parameters adjusted to handle this case

[How]
Fix pipe allocation when MPO viewport is only on one side of ODM
split, and modify scaling paramters.
Added diags test cases for ODM + windows MPO, where MPO window is
on right half, left half, and both halves or ODM.

Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Acked-by: Pavle Kotarac <Pavle.Kotarac@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Eric Bernstein <eric.bernstein@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Eric Bernstein and committed by
Alex Deucher
b4771435 47e62dbd

+71 -21
+60 -21
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
··· 734 734 (*split_idx)++; 735 735 split_pipe = split_pipe->top_pipe; 736 736 } 737 + 738 + /* MPO window on right side of ODM split */ 739 + if (split_pipe && split_pipe->prev_odm_pipe && !pipe_ctx->prev_odm_pipe) 740 + (*split_idx)++; 737 741 } else { 738 742 /*Get odm split index*/ 739 743 struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; ··· 784 780 /* 785 781 * Only the leftmost ODM pipe should be offset by a nonzero distance 786 782 */ 787 - if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) { 783 + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->prev_odm_pipe && !pipe_ctx->prev_odm_pipe) { 784 + /* MPO window on right side of ODM split */ 785 + data->recout.x = stream->dst.x + (surf_clip.x - stream->dst.width/2) * 786 + stream->dst.width / stream->src.width; 787 + } else if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) { 788 788 data->recout.x = stream->dst.x; 789 789 if (stream->src.x < surf_clip.x) 790 790 data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width ··· 986 978 * stream->dst.height / stream->src.height; 987 979 if (pipe_ctx->prev_odm_pipe && split_idx) 988 980 ro_lb = data->h_active * split_idx - recout_full_x; 981 + else if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->prev_odm_pipe) 982 + ro_lb = data->h_active * split_idx - recout_full_x + data->recout.x; 989 983 else 990 984 ro_lb = data->recout.x - recout_full_x; 991 985 ro_tb = data->recout.y - recout_full_y; ··· 1086 1076 timing->v_border_top + timing->v_border_bottom; 1087 1077 if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) 1088 1078 pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; 1079 + /* ODM + windows MPO, where window is on either right or left ODM half */ 1080 + else if (pipe_ctx->top_pipe && (pipe_ctx->top_pipe->next_odm_pipe || pipe_ctx->top_pipe->prev_odm_pipe)) 1081 + pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx->top_pipe) + 1; 1089 1082 1090 1083 /* depends on h_active */ 1091 1084 calculate_recout(pipe_ctx); ··· 1096 1083 calculate_scaling_ratios(pipe_ctx); 1097 1084 /* depends on scaling ratios and recout, does not calculate offset yet */ 1098 1085 calculate_viewport_size(pipe_ctx); 1099 - 1100 - /* Stopgap for validation of ODM + MPO on one side of screen case */ 1101 - if (pipe_ctx->plane_res.scl_data.viewport.height < 1 || 1102 - pipe_ctx->plane_res.scl_data.viewport.width < 1) 1103 - return false; 1104 1086 1105 1087 /* 1106 1088 * LB calculations depend on vp size, h/v_active and scaling ratios ··· 1445 1437 if (head_pipe != free_pipe) { 1446 1438 tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe); 1447 1439 ASSERT(tail_pipe); 1448 - free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 1449 - free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1450 - free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 1451 - free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1452 - free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1453 - free_pipe->clock_source = tail_pipe->clock_source; 1454 - free_pipe->top_pipe = tail_pipe; 1455 - tail_pipe->bottom_pipe = free_pipe; 1456 - if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) { 1457 - free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe; 1458 - tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe; 1459 - } 1460 - if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) { 1461 - free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe; 1462 - tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe; 1440 + 1441 + /* ODM + window MPO, where MPO window is on right half only */ 1442 + if (free_pipe->plane_state && 1443 + (free_pipe->plane_state->clip_rect.x >= free_pipe->stream->src.width/2) && 1444 + tail_pipe->next_odm_pipe) { 1445 + free_pipe->stream_res.tg = tail_pipe->next_odm_pipe->stream_res.tg; 1446 + free_pipe->stream_res.abm = tail_pipe->next_odm_pipe->stream_res.abm; 1447 + free_pipe->stream_res.opp = tail_pipe->next_odm_pipe->stream_res.opp; 1448 + free_pipe->stream_res.stream_enc = tail_pipe->next_odm_pipe->stream_res.stream_enc; 1449 + free_pipe->stream_res.audio = tail_pipe->next_odm_pipe->stream_res.audio; 1450 + free_pipe->clock_source = tail_pipe->next_odm_pipe->clock_source; 1451 + 1452 + free_pipe->top_pipe = tail_pipe->next_odm_pipe; 1453 + tail_pipe->next_odm_pipe->bottom_pipe = free_pipe; 1454 + } else { 1455 + free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 1456 + free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1457 + free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 1458 + free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1459 + free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1460 + free_pipe->clock_source = tail_pipe->clock_source; 1461 + 1462 + free_pipe->top_pipe = tail_pipe; 1463 + tail_pipe->bottom_pipe = free_pipe; 1464 + 1465 + if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) { 1466 + free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe; 1467 + tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe; 1468 + } 1469 + if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) { 1470 + free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe; 1471 + tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe; 1472 + } 1463 1473 } 1464 1474 } 1475 + 1476 + /* ODM + window MPO, where MPO window is on left half only */ 1477 + if (free_pipe->plane_state && 1478 + (free_pipe->plane_state->clip_rect.x + free_pipe->plane_state->clip_rect.width <= 1479 + free_pipe->stream->src.x + free_pipe->stream->src.width/2)) { 1480 + break; 1481 + } 1482 + /* ODM + window MPO, where MPO window is on right half only */ 1483 + if (free_pipe->plane_state && 1484 + (free_pipe->plane_state->clip_rect.x >= free_pipe->stream->src.width/2)) { 1485 + break; 1486 + } 1487 + 1465 1488 head_pipe = head_pipe->next_odm_pipe; 1466 1489 } 1467 1490 /* assign new surfaces*/
+11
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
··· 1761 1761 int pipe_idx = sec_pipe->pipe_idx; 1762 1762 const struct resource_pool *pool = dc->res_pool; 1763 1763 1764 + if (pri_pipe->plane_state) { 1765 + /* ODM + window MPO, where MPO window is on left half only */ 1766 + if (pri_pipe->plane_state->clip_rect.x + pri_pipe->plane_state->clip_rect.width <= 1767 + pri_pipe->stream->src.x + pri_pipe->stream->src.width/2) 1768 + return true; 1769 + 1770 + /* ODM + window MPO, where MPO window is on right half only */ 1771 + if (pri_pipe->plane_state->clip_rect.x >= pri_pipe->stream->src.width/2) 1772 + return true; 1773 + } 1774 + 1764 1775 *sec_pipe = *pri_pipe; 1765 1776 1766 1777 sec_pipe->pipe_idx = pipe_idx;