summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAshwin Santhosh <Ashwin.Santhosh@amd.com>2026-09-17 10:16:29 -0400
committerAlex Deucher <alexander.deucher@amd.com>2026-10-01 11:32:32 -0400
commitc50a6195df2e10325dcaef273fcdb9d078684bce (patch)
tree0e4cd196ece53100eb51a5aff567824e82069246 /drivers/gpu
parent0799087e2712fcc9efd849e3c99298ee2abac827 (diff)
downloadlinux-next-c50a6195df2e10325dcaef273fcdb9d078684bce.tar.gz
linux-next-c50a6195df2e10325dcaef273fcdb9d078684bce.zip
drm/amd/display: Program OPP formatter for plane-less ODM segments
why: When a display is disabled the surviving DSC stream is committed with no planes but the dynamic ODM policy still expands it to a four to one combine. The added plane-less segments skip program_pipe so their OPP formatter is never configured. The DPG blank then feeds an unprogrammed formatter and the OPTC input underflows which flashes grey on screen. how: Program the OPP formatter for each plane-less OPP head in update_odm and update_odm_sequence the same way program_pipe does for planed pipes. Both function pointers are checked for null before calling. Every ODM segment now feeds valid data to the OPTC so the four to one combine no longer underflows. Signed-off-by: Ashwin Santhosh <Ashwin.Santhosh@amd.com> Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com> Reviewed-by: Dillon Varone <dillon.varone@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c30
1 files changed, 30 insertions, 0 deletions
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 7780f37c615c..1d53240cd736 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
@@ -1740,6 +1740,22 @@ void dcn401_update_odm(struct dc *dc, struct dc_state *context,
opp_heads[i]->stream_res.opp,
opp_heads[i]->stream->timing.pixel_encoding,
resource_is_pipe_type(opp_heads[i], OTG_MASTER));
+
+ // Plane-less OPP heads are skipped by program_pipe, where the OPP
+ // formatter is normally configured, so set it up for them here.
+ if (!opp_heads[i]->plane_state &&
+ opp_heads[i]->stream_res.opp->funcs->opp_set_dyn_expansion &&
+ opp_heads[i]->stream_res.opp->funcs->opp_program_fmt) {
+ opp_heads[i]->stream_res.opp->funcs->opp_set_dyn_expansion(
+ opp_heads[i]->stream_res.opp,
+ COLOR_SPACE_YCBCR601,
+ opp_heads[i]->stream->timing.display_color_depth,
+ opp_heads[i]->stream->signal);
+ opp_heads[i]->stream_res.opp->funcs->opp_program_fmt(
+ opp_heads[i]->stream_res.opp,
+ &opp_heads[i]->stream->bit_depth_params,
+ &opp_heads[i]->stream->clamping);
+ }
}
update_dsc_for_odm_change(dc, context, otg_master);
@@ -1876,6 +1892,20 @@ void dcn401_update_odm_sequence(struct dc *dc, struct dc_state *context,
/* Add OPP program left edge extra pixel operation */
hwss_add_opp_program_left_edge_extra_pixel(seq_state, opp_heads[i]->stream_res.opp,
opp_heads[i]->stream->timing.pixel_encoding, resource_is_pipe_type(opp_heads[i], OTG_MASTER));
+
+ //Plane-less OPP heads are skipped by program_pipe, where the OPP
+ // formatter is normally configured, so set it up for them here.
+ if (!opp_heads[i]->plane_state &&
+ opp_heads[i]->stream_res.opp->funcs->opp_set_dyn_expansion &&
+ opp_heads[i]->stream_res.opp->funcs->opp_program_fmt) {
+ hwss_add_opp_set_dyn_expansion(seq_state, opp_heads[i]->stream_res.opp,
+ COLOR_SPACE_YCBCR601,
+ opp_heads[i]->stream->timing.display_color_depth,
+ opp_heads[i]->stream->signal);
+ hwss_add_opp_program_fmt(seq_state, opp_heads[i]->stream_res.opp,
+ &opp_heads[i]->stream->bit_depth_params,
+ &opp_heads[i]->stream->clamping);
+ }
}
/* Add DSC update operations to sequence */