Message ID | 20210122232647.22688-6-manasi.d.navare@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [CI,v5,01/18] drm/i915/display/vrr: Create VRR file and add VRR capability check | expand |
On Fri, Jan 22, 2021 at 03:26:35PM -0800, Manasi Navare wrote: > This forces a complete modeset if vrr drm crtc state goes > from enabled to disabled and vice versa. > This patch also computes vrr state variables from the mode timings > and based on the vrr property set by userspace as well as hardware's > vrr capability. > > v2: > *Rebase > v3: > * Vmin = max (vtotal, vmin) (Manasi) > v4: > * set crtc_state->vrr.enable = 0 for disable request > v5: > * drm_dbg_kms, squash crtc states def patch (Jani N) > v6: > * Move vrr modeset check to separate function (Jani N) > v7: > * Ville's fixes - vmin, vmax rename, fix rounding dir > * Add pipeline full, flipline to crtc state > * Pass conn state to vrr_compute_config (Ville) > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> > Cc: Jani Nikula <jani.nikula@linux.intel.com> > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> > --- > drivers/gpu/drm/i915/display/intel_display.c | 9 +++ > .../drm/i915/display/intel_display_types.h | 7 ++ > drivers/gpu/drm/i915/display/intel_dp.c | 1 + > drivers/gpu/drm/i915/display/intel_vrr.c | 70 +++++++++++++++++++ > drivers/gpu/drm/i915/display/intel_vrr.h | 8 +++ > 5 files changed, 95 insertions(+) > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c > index 2f878b7f9be8..7fc3ffdbc9b6 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.c > +++ b/drivers/gpu/drm/i915/display/intel_display.c > @@ -58,6 +58,7 @@ > #include "display/intel_sdvo.h" > #include "display/intel_tv.h" > #include "display/intel_vdsc.h" > +#include "display/intel_vrr.h" > > #include "gem/i915_gem_object.h" > > @@ -11316,6 +11317,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, > > PIPE_CONF_CHECK_I(mst_master_transcoder); > > + PIPE_CONF_CHECK_BOOL(vrr.enable); > + PIPE_CONF_CHECK_I(vrr.vmin); > + PIPE_CONF_CHECK_I(vrr.vmax); > + PIPE_CONF_CHECK_I(vrr.flipline); > + PIPE_CONF_CHECK_I(vrr.pipeline_full); > + > #undef PIPE_CONF_CHECK_X > #undef PIPE_CONF_CHECK_I > #undef PIPE_CONF_CHECK_BOOL > @@ -12473,6 +12480,8 @@ static int intel_atomic_check(struct drm_device *dev, > new_crtc_state->uapi.mode_changed = true; > } > > + intel_vrr_check_modeset(state); > + > ret = drm_atomic_helper_check_modeset(dev, &state->base); > if (ret) > goto fail; > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h > index 927a8aeae324..b5bac4c81de1 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_types.h > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h > @@ -1151,6 +1151,13 @@ struct intel_crtc_state { > struct intel_dsb *dsb; > > u32 psr2_man_track_ctl; > + > + /* Variable Refresh Rate state */ > + struct { > + bool enable; > + u8 pipeline_full; > + u16 flipline, vmin, vmax; > + } vrr; > }; > > enum intel_pipe_crc_source { > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c > index e6efa0fc31ea..6c1aaaf587c2 100644 > --- a/drivers/gpu/drm/i915/display/intel_dp.c > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > @@ -1827,6 +1827,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, > if (!HAS_DDI(dev_priv)) > intel_dp_set_clock(encoder, pipe_config); > > + intel_vrr_compute_config(pipe_config, conn_state); > intel_psr_compute_config(intel_dp, pipe_config); > intel_dp_drrs_compute_config(intel_dp, pipe_config, output_bpp, > constant_n); > diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c > index b0503edbfdfe..346ea3c16cc8 100644 > --- a/drivers/gpu/drm/i915/display/intel_vrr.c > +++ b/drivers/gpu/drm/i915/display/intel_vrr.c > @@ -29,3 +29,73 @@ bool intel_vrr_is_capable(struct drm_connector *connector) > drm_dp_sink_can_do_video_without_timing_msa(intel_dp->dpcd) && > info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10; > } > + > +void > +intel_vrr_check_modeset(struct intel_atomic_state *state) > +{ > + int i; > + struct intel_crtc_state *old_crtc_state, *new_crtc_state; > + struct intel_crtc *crtc; > + > + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, > + new_crtc_state, i) { > + if (new_crtc_state->uapi.vrr_enabled != > + old_crtc_state->uapi.vrr_enabled) > + new_crtc_state->uapi.mode_changed = true; > + } > +} > + > +void > +intel_vrr_compute_config(struct intel_crtc_state *crtc_state, > + struct drm_connector_state *conn_state) > +{ > + struct intel_connector *connector = > + to_intel_connector(conn_state->connector); > + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; > + const struct drm_display_info *info = &connector->base.display_info; > + int vmin, vmax; > + > + if (!intel_vrr_is_capable(&connector->base)) > + return; > + > + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) > + return; > + > + if (!crtc_state->uapi.vrr_enabled) > + return; > + > + vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000, > + adjusted_mode->crtc_htotal * info->monitor_range.max_vfreq); > + vmax = adjusted_mode->crtc_clock * 1000 / > + (adjusted_mode->crtc_htotal * info->monitor_range.min_vfreq); > + > + vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal); > + vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal); > + > + if (vmin >= vmax) > + return; > + > + /* > + * flipline determines the min vblank length the hardware will > + * generate, and flipline>=vmin+1, hence we reduce vmin by one > + * to make sure we can get the actual min vblank length. > + */ > + crtc_state->vrr.vmin = vmin - 1; > + crtc_state->vrr.vmax = vmax; > + crtc_state->vrr.enable = true; > + > + crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1; > + > + /* > + * FIXME: s/4/framestart_delay+1/ to get consistent Should say just framestart_delay here since it now includes the +1 > + * earliest/latest points for register latching regardless > + * of the framestart_delay used? > + * > + * FIXME: this really needs the extra scanline to provide consistent > + * behaviour for all framestart_delay values. Otherwise with > + * framestart_delay==3 we will end up extending the min vblank by And this should say framestart_delay==4 > + * one extra line. > + */ > + crtc_state->vrr.pipeline_full = > + min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - 4 - 1); > +} > diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h > index 3700acec5d09..67c477d6d1a4 100644 > --- a/drivers/gpu/drm/i915/display/intel_vrr.h > +++ b/drivers/gpu/drm/i915/display/intel_vrr.h > @@ -9,7 +9,15 @@ > #include <linux/types.h> > > struct drm_connector; > +struct drm_connector_state; > +struct intel_atomic_state; > +struct intel_crtc; > +struct intel_crtc_state; > +struct intel_dp; > > bool intel_vrr_is_capable(struct drm_connector *connector); > +void intel_vrr_check_modeset(struct intel_atomic_state *state); > +void intel_vrr_compute_config(struct intel_crtc_state *crtc_state, > + struct drm_connector_state *conn_state); > > #endif /* __INTEL_VRR_H__ */ > -- > 2.19.1
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2f878b7f9be8..7fc3ffdbc9b6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -58,6 +58,7 @@ #include "display/intel_sdvo.h" #include "display/intel_tv.h" #include "display/intel_vdsc.h" +#include "display/intel_vrr.h" #include "gem/i915_gem_object.h" @@ -11316,6 +11317,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(mst_master_transcoder); + PIPE_CONF_CHECK_BOOL(vrr.enable); + PIPE_CONF_CHECK_I(vrr.vmin); + PIPE_CONF_CHECK_I(vrr.vmax); + PIPE_CONF_CHECK_I(vrr.flipline); + PIPE_CONF_CHECK_I(vrr.pipeline_full); + #undef PIPE_CONF_CHECK_X #undef PIPE_CONF_CHECK_I #undef PIPE_CONF_CHECK_BOOL @@ -12473,6 +12480,8 @@ static int intel_atomic_check(struct drm_device *dev, new_crtc_state->uapi.mode_changed = true; } + intel_vrr_check_modeset(state); + ret = drm_atomic_helper_check_modeset(dev, &state->base); if (ret) goto fail; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 927a8aeae324..b5bac4c81de1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1151,6 +1151,13 @@ struct intel_crtc_state { struct intel_dsb *dsb; u32 psr2_man_track_ctl; + + /* Variable Refresh Rate state */ + struct { + bool enable; + u8 pipeline_full; + u16 flipline, vmin, vmax; + } vrr; }; enum intel_pipe_crc_source { diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e6efa0fc31ea..6c1aaaf587c2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1827,6 +1827,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (!HAS_DDI(dev_priv)) intel_dp_set_clock(encoder, pipe_config); + intel_vrr_compute_config(pipe_config, conn_state); intel_psr_compute_config(intel_dp, pipe_config); intel_dp_drrs_compute_config(intel_dp, pipe_config, output_bpp, constant_n); diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index b0503edbfdfe..346ea3c16cc8 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -29,3 +29,73 @@ bool intel_vrr_is_capable(struct drm_connector *connector) drm_dp_sink_can_do_video_without_timing_msa(intel_dp->dpcd) && info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10; } + +void +intel_vrr_check_modeset(struct intel_atomic_state *state) +{ + int i; + struct intel_crtc_state *old_crtc_state, *new_crtc_state; + struct intel_crtc *crtc; + + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { + if (new_crtc_state->uapi.vrr_enabled != + old_crtc_state->uapi.vrr_enabled) + new_crtc_state->uapi.mode_changed = true; + } +} + +void +intel_vrr_compute_config(struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct intel_connector *connector = + to_intel_connector(conn_state->connector); + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + const struct drm_display_info *info = &connector->base.display_info; + int vmin, vmax; + + if (!intel_vrr_is_capable(&connector->base)) + return; + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) + return; + + if (!crtc_state->uapi.vrr_enabled) + return; + + vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000, + adjusted_mode->crtc_htotal * info->monitor_range.max_vfreq); + vmax = adjusted_mode->crtc_clock * 1000 / + (adjusted_mode->crtc_htotal * info->monitor_range.min_vfreq); + + vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal); + vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal); + + if (vmin >= vmax) + return; + + /* + * flipline determines the min vblank length the hardware will + * generate, and flipline>=vmin+1, hence we reduce vmin by one + * to make sure we can get the actual min vblank length. + */ + crtc_state->vrr.vmin = vmin - 1; + crtc_state->vrr.vmax = vmax; + crtc_state->vrr.enable = true; + + crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1; + + /* + * FIXME: s/4/framestart_delay+1/ to get consistent + * earliest/latest points for register latching regardless + * of the framestart_delay used? + * + * FIXME: this really needs the extra scanline to provide consistent + * behaviour for all framestart_delay values. Otherwise with + * framestart_delay==3 we will end up extending the min vblank by + * one extra line. + */ + crtc_state->vrr.pipeline_full = + min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - 4 - 1); +} diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h index 3700acec5d09..67c477d6d1a4 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.h +++ b/drivers/gpu/drm/i915/display/intel_vrr.h @@ -9,7 +9,15 @@ #include <linux/types.h> struct drm_connector; +struct drm_connector_state; +struct intel_atomic_state; +struct intel_crtc; +struct intel_crtc_state; +struct intel_dp; bool intel_vrr_is_capable(struct drm_connector *connector); +void intel_vrr_check_modeset(struct intel_atomic_state *state); +void intel_vrr_compute_config(struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state); #endif /* __INTEL_VRR_H__ */