On Thu, May 14, 2026 at 12:04 PM <[email protected]> wrote: > > From: Ivan Lipski <[email protected]> > > [Why&How] > dccg21_init() calls dccg2_init() which hardcodes 100MHz refclk values > for MICROSECOND_TIME_BASE_DIV and MILLISECOND_TIME_BASE_DIV. DCN21 > uses 48MHz refclk, so the wrong values corrupt DCCG timing and cause eDP > link training failure on cold boot. > > Write the correct 48MHz values directly instead of calling dccg2_init(). > > Fixes: b7dfeea1e168 ("drm/amd/display: Add missing DCCG register entries for > DCN20-DCN316") > > v2: > Fixed typo > > Reported-by: Max Chernoff <[email protected]> > Tested-by: Max Chernoff <[email protected]> > Signed-off-by: Ivan Lipski <[email protected]>
Acked-by: Alex Deucher <[email protected]> For a future patch, it would be a nice clean up to read the ref clock from the driver and program the clock as needed rather than requiring a separate callback for each chip and using a hardcoded programming sequence. Alex > --- > .../drm/amd/display/dc/dccg/dcn21/dcn21_dccg.c | 15 +++++++++++++-- > 1 file changed, 13 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn21/dcn21_dccg.c > b/drivers/gpu/drm/amd/display/dc/dccg/dcn21/dcn21_dccg.c > index bdc3ce5d4f47..be167bbd42b5 100644 > --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn21/dcn21_dccg.c > +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn21/dcn21_dccg.c > @@ -105,15 +105,26 @@ static void dccg21_update_dpp_dto(struct dccg *dccg, > int dpp_inst, int req_dppcl > * dccg2_init() unconditionally overwrites MICROSECOND_TIME_BASE_DIV to > * 0x00120264, destroying the marker before it can be read. > * > - * Guard the call: if the S0i3 marker is present, skip dccg2_init() so the > + * Guard the call: if the S0i3 marker is present, skip init so the > * WA can function correctly. bios_golden_init() will handle init in that > case. > + * > + * DCN21 uses 48MHz refclk, not 100MHz, so we must explicitly set the correct > + * values (48MHz is taken from rn_clk_mgr_construct()). > */ > static void dccg21_init(struct dccg *dccg) > { > + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); > + > if (dccg2_is_s0i3_golden_init_wa_done(dccg)) > return; > > - dccg2_init(dccg); > + /* 48MHz refclk from rn_clk_mgr_construct() */ > + REG_WRITE(MICROSECOND_TIME_BASE_DIV, 0x00120230); > + REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x0010bb80); > + REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x0e01003c); > + > + if (REG(REFCLK_CNTL)) > + REG_WRITE(REFCLK_CNTL, 0); > } > > static const struct dccg_funcs dccg21_funcs = { > -- > 2.43.0 >
