From: Clay King clayking@amd.com
[ Upstream commit 306cbcc6f687d791ab3cc8fbbe30f5286fd0d1e5 ]
[Why & How] Previously, when calculating dto phase, we would incorrectly fail when phase <=0 without additionally checking for the integer value. This meant that calculations would incorrectly fail when the desired pixel clock was an exact multiple of the reference clock.
Reviewed-by: Dillon Varone dillon.varone@amd.com Signed-off-by: Clay King clayking@amd.com Signed-off-by: Alex Hung alex.hung@amd.com Tested-by: Dan Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES
**Why This Is A Bug** - The DTO phase for DP pixel rate is computed as an integer/fractional split: `dto_integer = pixclk_hz / refclk_hz` and `dto_phase_hz = pixclk_hz - dto_integer * refclk_hz` in `drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c:619-620`. - Both `dto_phase_hz` and `dto_integer` are `uint64_t`. The old check `if (dto_phase_hz <= 0)` (effectively `== 0` for unsigned) incorrectly treated a valid “exact multiple” case (phase = 0, integer > 0) as an error. - The fix changes the guard to `if (dto_phase_hz <= 0 && dto_integer <= 0)` at `drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c:622`, only failing when both integer and phase are zero (i.e., `pixclk_hz == 0`), which is the truly invalid case.
**Impact of the Old Behavior** - On a false failure, the function returns early and skips programming DTO registers and enabling the DTO: - DTO writes skipped: `DP_DTO_PHASE` and `DP_DTO_MODULO` at `drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c:665-666`, and `DPDTOx_INT` at `drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c:670-683`. - DTO enable toggle skipped: `DP_DTO_ENABLE` and `PIPE_DTO_SRC_SEL` at `drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c:691-694`. - This function is used when programming DP (non-TMDS) pixel clocks via `dcn401_program_pix_clk`, which calls `set_dp_dto` for DP streams at `drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c:1104-1106`. A premature return leaves the DP DTO disabled or misconfigured, causing mode set failures or blank displays when the requested pixel clock is an exact multiple of the reference clock.
**Scope and Containment** - Affects only DCN4.01’s `dccg401_set_dp_dto` and only for non-TMDS (DP/eDP) signals; TMDS/HDMI paths are explicitly excluded earlier in the function (`dc_is_tmds_signal` guard at `drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c:608`). - No external API changes and no architectural changes; it is a one-line conditional fix in a single file.
**Risk Assessment** - Very low risk: - Mathematically correct: a fractional DTO with zero phase is expected and valid for exact ratios; blocking it was the bug. - The new condition only rejects the clearly invalid `pixclk_hz == 0` case (integer == 0 and phase == 0). - Limited to DCN4.01 hardware path and the DP DTO programming sequence.
**Stable Criteria** - Fixes a user-visible functional bug (DP modes that are exact multiples of the reference clock failing). - Small and self-contained change, minimal regression risk, no feature addition, no broad subsystem churn. - Conforms to stable rules for important bug fixes.
Given the clear, localized bugfix that prevents spurious failures and restores valid DTO programming for exact multiple clocks, this commit is an excellent candidate for backporting to stable trees that include DCN4.01.
drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c index 668ee2d405fdf..0b8ed9b94d3c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c @@ -619,7 +619,7 @@ void dccg401_set_dp_dto( dto_integer = div_u64(params->pixclk_hz, dto_modulo_hz); dto_phase_hz = params->pixclk_hz - dto_integer * dto_modulo_hz;
- if (dto_phase_hz <= 0) { + if (dto_phase_hz <= 0 && dto_integer <= 0) { /* negative pixel rate should never happen */ BREAK_TO_DEBUGGER(); return;