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

drm/amd/display: Avoid pipe split when plane is too small

[Why]
The minimum plane size we can support in DML is 16x16. If we try to pass
a 16x16 plane with dynamic pipe split then validation will fail since it
tries to split it into two pipes, each 8x8.

Some userspace doesn't check that the commit fails and because the
commit fails the old state is retained, resulting in corruption.

[How]
Add a workaround to avoid pipe split if any plane is 16x16 or smaller.

Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Nicholas Kazlauskas and committed by
Alex Deucher
b6dbb8ff 63731e73

+33 -2
+20 -1
drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
··· 690 690 struct dc_debug_options *dbg, 691 691 struct dc_state *context) 692 692 { 693 + int i; 694 + 695 + for (i = 0; i < MAX_PIPES; i++) { 696 + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 697 + 698 + /** 699 + * Workaround for avoiding pipe-split in cases where we'd split 700 + * planes that are too small, resulting in splits that aren't 701 + * valid for the scaler. 702 + */ 703 + if (pipe->plane_state && 704 + (pipe->plane_state->dst_rect.width <= 16 || 705 + pipe->plane_state->dst_rect.height <= 16 || 706 + pipe->plane_state->src_rect.width <= 16 || 707 + pipe->plane_state->src_rect.height <= 16)) { 708 + hack_disable_optional_pipe_split(v); 709 + return; 710 + } 711 + } 712 + 693 713 if (dbg->pipe_split_policy == MPC_SPLIT_AVOID) 694 714 hack_disable_optional_pipe_split(v); 695 715 ··· 721 701 dbg->force_single_disp_pipe_split) 722 702 hack_force_pipe_split(v, context->streams[0]->timing.pix_clk_100hz); 723 703 } 724 - 725 704 726 705 unsigned int get_highest_allowed_voltage_level(uint32_t hw_internal_rev, uint32_t pci_revision_id) 727 706 {
+13 -1
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
··· 2606 2606 } else if (dc->debug.force_single_disp_pipe_split) 2607 2607 force_split = true; 2608 2608 2609 - /* TODO: fix dc bugs and remove this split threshold thing */ 2610 2609 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2611 2610 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 2612 2611 2612 + /** 2613 + * Workaround for avoiding pipe-split in cases where we'd split 2614 + * planes that are too small, resulting in splits that aren't 2615 + * valid for the scaler. 2616 + */ 2617 + if (pipe->plane_state && 2618 + (pipe->plane_state->dst_rect.width <= 16 || 2619 + pipe->plane_state->dst_rect.height <= 16 || 2620 + pipe->plane_state->src_rect.width <= 16 || 2621 + pipe->plane_state->src_rect.height <= 16)) 2622 + avoid_split = true; 2623 + 2624 + /* TODO: fix dc bugs and remove this split threshold thing */ 2613 2625 if (pipe->stream && !pipe->prev_odm_pipe && 2614 2626 (!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state)) 2615 2627 ++plane_count;