Message ID | 20241016143134.26903-2-ville.syrjala@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/i915/pfit: Panel fitter stuff | expand |
On Wed, 16 Oct 2024, Ville Syrjala <ville.syrjala@linux.intel.com> wrote: > From: Ville Syrjälä <ville.syrjala@linux.intel.com> > > The ILK-BDW panel fitter imposes extra limits on the maximum > pipe source size we can use. Check for that. > > Only HSW/BDW are really affected by this since on older platforms > the max hdisplay/vdisplay matches the max PIPESRC. But we'll > put in the limits for all the platforms just to keep things > clear. > > Note that pch_panel_fitting() is also used on SKL+, but we'll > skip the checks for those as it's all supposed to be handled > in the unified scaler code. > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Looks sensible, but I'm just not going to dig through all the old specs to verify all of this, and I don't expect anyone else to do it either. I'll take your word for it, and I trust you to fix any fallout as well. With that, Acked-by: Jani Nikula <jani.nikula@intel.com> > --- > drivers/gpu/drm/i915/display/intel_panel.c | 52 +++++++++++++++++++++- > 1 file changed, 51 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c > index 71454ddef20f..b77017144818 100644 > --- a/drivers/gpu/drm/i915/display/intel_panel.c > +++ b/drivers/gpu/drm/i915/display/intel_panel.c > @@ -383,15 +383,54 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, > "current (BIOS)"); > } > > +static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_state) > +{ > + struct intel_display *display = to_intel_display(crtc_state); > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); > + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); > + int max_src_w, max_src_h; > + > + if (DISPLAY_VER(display) >= 8) { > + max_src_w = 4096; > + max_src_h = 4096; > + } else if (DISPLAY_VER(display) >= 7) { > + /* > + * PF0 7x5 capable > + * PF1 3x3 capable (could be switched to 7x5 > + * mode on HSW when PF2 unused) > + * PF2 3x3 capable > + * > + * This assumes we use a 1:1 mapping between pipe and PF. > + */ > + max_src_w = crtc->pipe == PIPE_A ? 4096 : 2048; > + max_src_h = 4096; > + } else { > + max_src_w = 4096; > + max_src_h = 4096; > + } > + > + if (pipe_src_w > max_src_w || pipe_src_h > max_src_h) { > + drm_dbg_kms(display->drm, > + "[CRTC:%d:%s] source size (%dx%d) exceeds pfit max (%dx%d)\n", > + crtc->base.base.id, crtc->base.name, > + pipe_src_w, pipe_src_h, max_src_w, max_src_h); > + return -EINVAL; > + } > + > + return 0; > +} > + > /* adjusted_mode has been preset to be the panel's fixed mode */ > static int pch_panel_fitting(struct intel_crtc_state *crtc_state, > const struct drm_connector_state *conn_state) > { > + struct intel_display *display = to_intel_display(crtc_state); > const struct drm_display_mode *adjusted_mode = > &crtc_state->hw.adjusted_mode; > int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); > int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); > - int x, y, width, height; > + int ret, x, y, width, height; > > /* Native modes don't need fitting */ > if (adjusted_mode->crtc_hdisplay == pipe_src_w && > @@ -453,6 +492,17 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, > x, y, width, height); > crtc_state->pch_pfit.enabled = true; > > + /* > + * SKL+ have unified scalers for pipes/planes so the > + * checks are done in a single place for all scalers. > + */ > + if (DISPLAY_VER(display) >= 9) > + return 0; > + > + ret = intel_pch_pfit_check_src_size(crtc_state); > + if (ret) > + return ret; > + > return 0; > }
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 71454ddef20f..b77017144818 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -383,15 +383,54 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, "current (BIOS)"); } +static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + int max_src_w, max_src_h; + + if (DISPLAY_VER(display) >= 8) { + max_src_w = 4096; + max_src_h = 4096; + } else if (DISPLAY_VER(display) >= 7) { + /* + * PF0 7x5 capable + * PF1 3x3 capable (could be switched to 7x5 + * mode on HSW when PF2 unused) + * PF2 3x3 capable + * + * This assumes we use a 1:1 mapping between pipe and PF. + */ + max_src_w = crtc->pipe == PIPE_A ? 4096 : 2048; + max_src_h = 4096; + } else { + max_src_w = 4096; + max_src_h = 4096; + } + + if (pipe_src_w > max_src_w || pipe_src_h > max_src_h) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] source size (%dx%d) exceeds pfit max (%dx%d)\n", + crtc->base.base.id, crtc->base.name, + pipe_src_w, pipe_src_h, max_src_w, max_src_h); + return -EINVAL; + } + + return 0; +} + /* adjusted_mode has been preset to be the panel's fixed mode */ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + struct intel_display *display = to_intel_display(crtc_state); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); - int x, y, width, height; + int ret, x, y, width, height; /* Native modes don't need fitting */ if (adjusted_mode->crtc_hdisplay == pipe_src_w && @@ -453,6 +492,17 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, x, y, width, height); crtc_state->pch_pfit.enabled = true; + /* + * SKL+ have unified scalers for pipes/planes so the + * checks are done in a single place for all scalers. + */ + if (DISPLAY_VER(display) >= 9) + return 0; + + ret = intel_pch_pfit_check_src_size(crtc_state); + if (ret) + return ret; + return 0; }