Re: [PATCH 1/4] drm/i915/display: Limit max joined dotclock on joiner pipes available
Jani Nikula <[email protected]>
| Newsgroups | org.freedesktop.lists.intel-gfx,org.freedesktop.lists.intel-xe |
|---|---|
| Organization | Intel Finland Oy - BIC 0357606-4 - c/o Alberga Business Park, 6 krs Bertel Jungin Aukio 5, 02600 Espoo, Finland |
| Message-ID | <[email protected]> |
On Mon, 10 Aug 2026, "Nautiyal, Ankit K" <[email protected]> wrote: > On 8/7/2026 6:04 PM, Jani Nikula wrote: >> Multiplying the max dotclock based on joiner availability on the >> platform alone does not take into account the actual pipes (possibly >> with some fused) available for joining. >> >> Limit the max joined dotclock based on the actual pipes available for >> joining. Add helpers for figuring out the valid primary pipes, based on >> having the required joiners and amount of consecutive pipes available. >> >> v2: Check for consecutive pipes available (Ankit) >> >> Cc: Ankit Nautiyal <[email protected]> >> Signed-off-by: Jani Nikula <[email protected]> >> --- >> drivers/gpu/drm/i915/display/intel_display.c | 51 +++++++++++++++++++- >> drivers/gpu/drm/i915/display/intel_display.h | 1 + >> 2 files changed, 50 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c >> index 829d7a411dcc..c958b2a92cc7 100644 >> --- a/drivers/gpu/drm/i915/display/intel_display.c >> +++ b/drivers/gpu/drm/i915/display/intel_display.c >> @@ -193,6 +193,53 @@ is_trans_port_sync_mode(const struct intel_crtc_state *crtc_state) >> is_trans_port_sync_slave(crtc_state); >> } >> >> +/* >> + * Return a bitmask of all the start indices of consecutive bitfields of size >> + * width in mask. >> + */ >> +static unsigned long find_consecutive_bits(unsigned long mask, int width) >> +{ >> + unsigned long bit, out_mask = 0; >> + >> + if (!width) >> + return 0; >> + >> + for_each_set_bit(bit, &mask, BITS_PER_TYPE(mask)) { >> + /* For each set bit, see if the following bits are set also */ >> + unsigned long bitfield = GENMASK(bit + width - 1, bit); >> + >> + if ((mask & bitfield) == bitfield) >> + out_mask |= BIT(bit); >> + } >> + >> + return out_mask; > > This is very clever! > > This fits very nicely with the part where we want to check if joiner is > supported "for a specific crtc" during compute_config phase. Yay, thanks! > This works even for width = 1 as well, but it's better to handle the > case separately as you have already done, it's intuitive and avoids > iterating through the bits. > > Reviewed-by: Ankit Nautiyal <[email protected]> Thanks for the review, pushed the lot to din. BR, Jani. > > >> +} >> + >> +/* >> + * Return a bitmask of all valid joiner primary pipes for joining >> + * num_joined_pipes pipes. For completeness, return all valid pipes for >> + * num_joined_pipes == 1. >> + * >> + * Return 0 if the platform doesn't support joining for the requested number of >> + * pipes, or there are not enough consecutive pipes available. >> + */ >> +u8 intel_joiner_valid_primary_pipe_mask(struct intel_display *display, int num_joined_pipes) >> +{ >> + if (num_joined_pipes == 1) { >> + return DISPLAY_RUNTIME_INFO(display)->pipe_mask; >> + } else if (num_joined_pipes == 2) { >> + if (!HAS_UNCOMPRESSED_JOINER(display) && !HAS_BIGJOINER(display)) >> + return 0; >> + } else if (num_joined_pipes == 4) { >> + if (!HAS_ULTRAJOINER(display)) >> + return 0; >> + } else { >> + return 0; >> + } >> + >> + return find_consecutive_bits(DISPLAY_RUNTIME_INFO(display)->pipe_mask, num_joined_pipes); >> +} >> + >> static enum pipe joiner_primary_pipe(const struct intel_crtc_state *crtc_state) >> { >> return ffs(crtc_state->joiner_pipes) - 1; >> @@ -8113,9 +8160,9 @@ static int max_dotclock(struct intel_display *display) >> { >> int max_dotclock = display->cdclk.max_dotclk_freq; >> >> - if (HAS_ULTRAJOINER(display)) >> + if (intel_joiner_valid_primary_pipe_mask(display, 4)) >> max_dotclock *= 4; >> - else if (HAS_UNCOMPRESSED_JOINER(display) || HAS_BIGJOINER(display)) >> + else if (intel_joiner_valid_primary_pipe_mask(display, 2)) >> max_dotclock *= 2; >> >> return max_dotclock; >> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h >> index 57ea4f2edf2a..e7ecae9d2d21 100644 >> --- a/drivers/gpu/drm/i915/display/intel_display.h >> +++ b/drivers/gpu/drm/i915/display/intel_display.h >> @@ -373,6 +373,7 @@ intel_cpu_transcoder_mode_valid(struct intel_display *display, >> enum phy intel_port_to_phy(struct intel_display *display, enum port port); >> bool is_trans_port_sync_mode(const struct intel_crtc_state *state); >> bool is_trans_port_sync_master(const struct intel_crtc_state *state); >> +u8 intel_joiner_valid_primary_pipe_mask(struct intel_display *display, int num_joined_pipes); >> u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state); >> bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state); >> bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state); -- Jani Nikula, Intel