Message ID | 20241016143134.26903-7-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 has several restrictions on the > destination window size. Check for those and reject the > configuration if things aren't entirely proper. > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Acked-by: Jani Nikula <jani.nikula@intel.com> > --- > drivers/gpu/drm/i915/display/intel_panel.c | 55 ++++++++++++++++++++++ > 1 file changed, 55 insertions(+) > > diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c > index 593e41907d53..d66ce8537f7d 100644 > --- a/drivers/gpu/drm/i915/display/intel_panel.c > +++ b/drivers/gpu/drm/i915/display/intel_panel.c > @@ -383,6 +383,57 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, > "current (BIOS)"); > } > > +static int intel_pch_pfit_check_dst_window(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); > + const struct drm_display_mode *adjusted_mode = > + &crtc_state->hw.adjusted_mode; > + const struct drm_rect *dst = &crtc_state->pch_pfit.dst; > + int width = drm_rect_width(dst); > + int height = drm_rect_height(dst); > + int x = dst->x1; > + int y = dst->y1; > + > + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE && > + (y & 1 || height & 1)) { > + drm_dbg_kms(display->drm, > + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") misaligned for interlaced output\n", > + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); > + return -EINVAL; > + } > + > + /* > + * "Restriction : When pipe scaling is enabled, the scaled > + * output must equal the pipe active area, so Pipe active > + * size = (2 * PF window position) + PF window size." > + * > + * The vertical direction seems more forgiving than the > + * horizontal direction, but still has some issues so > + * let's follow the same hard rule for both. > + */ > + if (adjusted_mode->crtc_hdisplay != 2 * x + width || > + adjusted_mode->crtc_vdisplay != 2 * y + height) { > + drm_dbg_kms(display->drm, > + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") not centered\n", > + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); > + return -EINVAL; > + } > + > + /* > + * "Restriction : The X position must not be programmed > + * to be 1 (28:16=0 0000 0000 0001b)." > + */ > + if (x == 1) { > + drm_dbg_kms(display->drm, > + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") badly positioned\n", > + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); > + return -EINVAL; > + } > + > + return 0; > +} > + > static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_state) > { > struct intel_display *display = to_intel_display(crtc_state); > @@ -575,6 +626,10 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, > if (DISPLAY_VER(display) >= 9) > return 0; > > + ret = intel_pch_pfit_check_dst_window(crtc_state); > + if (ret) > + return ret; > + > ret = intel_pch_pfit_check_src_size(crtc_state); > if (ret) > return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 593e41907d53..d66ce8537f7d 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -383,6 +383,57 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, "current (BIOS)"); } +static int intel_pch_pfit_check_dst_window(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); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + const struct drm_rect *dst = &crtc_state->pch_pfit.dst; + int width = drm_rect_width(dst); + int height = drm_rect_height(dst); + int x = dst->x1; + int y = dst->y1; + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE && + (y & 1 || height & 1)) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") misaligned for interlaced output\n", + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); + return -EINVAL; + } + + /* + * "Restriction : When pipe scaling is enabled, the scaled + * output must equal the pipe active area, so Pipe active + * size = (2 * PF window position) + PF window size." + * + * The vertical direction seems more forgiving than the + * horizontal direction, but still has some issues so + * let's follow the same hard rule for both. + */ + if (adjusted_mode->crtc_hdisplay != 2 * x + width || + adjusted_mode->crtc_vdisplay != 2 * y + height) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") not centered\n", + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); + return -EINVAL; + } + + /* + * "Restriction : The X position must not be programmed + * to be 1 (28:16=0 0000 0000 0001b)." + */ + if (x == 1) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") badly positioned\n", + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); + return -EINVAL; + } + + return 0; +} + static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); @@ -575,6 +626,10 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, if (DISPLAY_VER(display) >= 9) return 0; + ret = intel_pch_pfit_check_dst_window(crtc_state); + if (ret) + return ret; + ret = intel_pch_pfit_check_src_size(crtc_state); if (ret) return ret;