Re: [PATCH 1/4] drm/i915/display: Limit max joined dotclock on joiner pipes available
"Nautiyal, Ankit K" <[email protected]>
| Newsgroups | org.freedesktop.lists.intel-gfx,org.freedesktop.lists.intel-xe |
|---|---|
| Message-ID | <[email protected]> |
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. 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]> > +} > + > +/* > + * 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);