diff options
| author | Wang, Sung-huai <Danny.Wang@amd.com> | 2026-08-31 16:25:30 +0800 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-09-17 11:38:26 -0400 |
| commit | a3bc27586dde44301f97de69a8f1025310083102 (patch) | |
| tree | f08a0b3594c16f9d37acbaf4e10162384f5ad757 /drivers/gpu/drm/amd/display | |
| parent | ec0c15a270bab226ece0d1698f95a5fc00e71392 (diff) | |
| download | linux-next-a3bc27586dde44301f97de69a8f1025310083102.tar.gz linux-next-a3bc27586dde44301f97de69a8f1025310083102.zip | |
drm/amd/display: Add is_odm_enabled callback to skip init_odm on active ODM pipes
[Why]
dcn10_init_pipes unconditionally calls init_odm on all enabled TGs,
resetting ODM combine state even when it should be preserved.
[How]
Add is_odm_enabled callback to timing_generator_funcs and
guard init_odm to skip when ODM is already active.
Reviewed-by: Aric Cyr <aric.cyr@amd.com>
Signed-off-by: Danny Wang <Danny.Wang@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display')
7 files changed, 18 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index 270b6f2d4377..7fa329229ae0 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -1750,7 +1750,9 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context) if (tg->funcs->is_tg_enabled(tg)) { if (tg->funcs->init_odm) - tg->funcs->init_odm(tg); + if (!tg->funcs->is_odm_enabled || + !tg->funcs->is_odm_enabled(tg)) + tg->funcs->init_odm(tg); } tg->funcs->tg_init(tg); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 2eaba65894ab..52d4d57358cd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -512,6 +512,7 @@ struct timing_generator_funcs { uint32_t vtotal_change_limit); void (*init_odm)(struct timing_generator *tg); + bool (*is_odm_enabled)(struct timing_generator *tg); void (*wait_drr_doublebuffer_pending_clear)(struct timing_generator *tg); void (*set_long_vtotal)(struct timing_generator *optc, const struct long_vtotal_params *params); void (*wait_odm_doublebuffer_pending_clear)(struct timing_generator *tg); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c index 3ace83e1b50f..ce9cd32b807a 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c @@ -221,6 +221,15 @@ void optc31_set_drr( } } +bool optc3_is_odm_enabled(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t num_segments = 0; + + REG_GET(OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, &num_segments); + return num_segments > 0; +} + void optc3_init_odm(struct timing_generator *optc) { struct optc *optc1 = DCN10TG_FROM_TG(optc); @@ -503,6 +512,7 @@ static const struct timing_generator_funcs dcn31_tg_funcs = { .setup_manual_trigger = optc2_setup_manual_trigger, .get_hw_timing = optc1_get_hw_timing, .init_odm = optc3_init_odm, + .is_odm_enabled = optc3_is_odm_enabled, .is_two_pixels_per_container = optc1_is_two_pixels_per_container, .read_otg_state = optc31_read_otg_state, .optc_read_reg_state = optc31_read_reg_state, diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h index 119a954fe3e5..19d90c65a22b 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h @@ -274,6 +274,7 @@ bool optc31_immediate_disable_crtc(struct timing_generator *optc); void optc31_set_drr(struct timing_generator *optc, const struct drr_params *params); void optc3_init_odm(struct timing_generator *optc); +bool optc3_is_odm_enabled(struct timing_generator *optc); void optc31_read_otg_state(struct timing_generator *optc, struct dcn_otg_state *s); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c index 7250478a5092..f5faa49680ef 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c @@ -247,6 +247,7 @@ static const struct timing_generator_funcs dcn314_tg_funcs = { .setup_manual_trigger = optc2_setup_manual_trigger, .get_hw_timing = optc1_get_hw_timing, .init_odm = optc3_init_odm, + .is_odm_enabled = optc3_is_odm_enabled, .set_odm_bypass = optc314_set_odm_bypass, .set_odm_combine = optc314_set_odm_combine, .set_h_timing_div_manual_mode = optc314_set_h_timing_div_manual_mode, diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c index 897f857db448..406446e5eae5 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c @@ -614,6 +614,7 @@ static const struct timing_generator_funcs dcn35_tg_funcs = { .setup_manual_trigger = optc2_setup_manual_trigger, .get_hw_timing = optc1_get_hw_timing, .init_odm = optc3_init_odm, + .is_odm_enabled = optc3_is_odm_enabled, .set_long_vtotal = optc35_set_long_vtotal, .is_two_pixels_per_container = optc1_is_two_pixels_per_container, .read_otg_state = optc31_read_otg_state, diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c index fd9c2b6b8b3c..1e4f2051d732 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c @@ -261,6 +261,7 @@ static struct timing_generator_funcs dcn42_tg_funcs = { .setup_manual_trigger = optc2_setup_manual_trigger, .get_hw_timing = optc1_get_hw_timing, .init_odm = optc3_init_odm, + .is_odm_enabled = optc3_is_odm_enabled, .set_long_vtotal = optc35_set_long_vtotal, .is_two_pixels_per_container = optc1_is_two_pixels_per_container, .get_optc_double_buffer_pending = optc3_get_optc_double_buffer_pending, |
