On Thu, 2022-03-10 at 02:47 +0200, Ville Syrjala wrote: > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > Get rid of the ugly intel_dp dependency, and one more crtc->config > usage by storing the DRRS state under intel_crtc. intel_drrs_enable() > copies what it needs from the crtc state, after which DRRS can be > blissfully ignorant of anything going on around it. > > This also lets multiple pipes do DRRS simultanously and entirely > independently. > > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/i915/display/intel_crtc.c | 2 + > drivers/gpu/drm/i915/display/intel_ddi.c | 8 +- > drivers/gpu/drm/i915/display/intel_display.c | 2 +- > .../drm/i915/display/intel_display_debugfs.c | 97 ++---- > .../drm/i915/display/intel_display_types.h | 14 + > drivers/gpu/drm/i915/display/intel_dp.c | 4 +- > drivers/gpu/drm/i915/display/intel_drrs.c | 300 +++++++----------- > drivers/gpu/drm/i915/display/intel_drrs.h | 20 +- > drivers/gpu/drm/i915/i915_drv.h | 15 - > 9 files changed, 171 insertions(+), 291 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c > index 65827481c1b1..f655c1622877 100644 > --- a/drivers/gpu/drm/i915/display/intel_crtc.c > +++ b/drivers/gpu/drm/i915/display/intel_crtc.c > @@ -24,6 +24,7 @@ > #include "intel_display_debugfs.h" > #include "intel_display_trace.h" > #include "intel_display_types.h" > +#include "intel_drrs.h" > #include "intel_dsi.h" > #include "intel_pipe_crc.h" > #include "intel_psr.h" > @@ -367,6 +368,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) > > intel_color_init(crtc); > > + intel_crtc_drrs_init(crtc); > intel_crtc_crc_init(crtc); > > cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE); > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c > index 3e6d86a54850..a3bf4e876fb4 100644 > --- a/drivers/gpu/drm/i915/display/intel_ddi.c > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c > @@ -2820,7 +2820,7 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state, > if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink) > intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); > > - intel_drrs_enable(intel_dp, crtc_state); > + intel_drrs_enable(crtc_state); > > if (crtc_state->has_audio) > intel_audio_codec_enable(encoder, crtc_state, conn_state); > @@ -2963,7 +2963,7 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state, > intel_audio_codec_disable(encoder, > old_crtc_state, old_conn_state); > > - intel_drrs_disable(intel_dp, old_crtc_state); > + intel_drrs_disable(old_crtc_state); > intel_psr_disable(intel_dp, old_crtc_state); > intel_edp_backlight_off(old_conn_state); > /* Disable the decompression in DP Sink */ > @@ -3013,12 +3013,12 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, > const struct intel_crtc_state *crtc_state, > const struct drm_connector_state *conn_state) > { > - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > > intel_ddi_set_dp_msa(crtc_state, conn_state); > > intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); > - intel_drrs_update(intel_dp, crtc_state); > + intel_drrs_update(state, crtc); > > intel_backlight_update(state, encoder, crtc_state, conn_state); > drm_connector_update_privacy_screen(conn_state); > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c > index b7c418677372..4c7c74665819 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.c > +++ b/drivers/gpu/drm/i915/display/intel_display.c > @@ -1229,7 +1229,7 @@ static void intel_post_plane_update(struct intel_atomic_state *state, > > hsw_ips_post_update(state, crtc); > intel_fbc_post_update(state, crtc); > - intel_drrs_page_flip(state, crtc); > + intel_drrs_page_flip(crtc); > > if (needs_async_flip_vtd_wa(old_crtc_state) && > !needs_async_flip_vtd_wa(new_crtc_state)) > diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c > index 798bf233a60f..bbf6ebd18414 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c > +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c > @@ -1143,87 +1143,44 @@ static int i915_ddb_info(struct seq_file *m, void *unused) > return 0; > } > > -static void drrs_status_per_crtc(struct seq_file *m, > - struct drm_device *dev, > - struct intel_crtc *crtc) > +static int i915_drrs_status(struct seq_file *m, void *unused) > { > - struct drm_i915_private *dev_priv = to_i915(dev); > - struct i915_drrs *drrs = &dev_priv->drrs; > - struct drm_connector *connector; > + struct drm_i915_private *dev_priv = node_to_i915(m->private); > struct drm_connector_list_iter conn_iter; > + struct intel_connector *connector; > + struct intel_crtc *crtc; > > - drm_connector_list_iter_begin(dev, &conn_iter); > - drm_for_each_connector_iter(connector, &conn_iter) { > - bool supported = false; > + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); > + for_each_intel_connector_iter(connector, &conn_iter) { > + seq_printf(m, "[CONNECTOR:%d:%s]:\n", > + connector->base.base.id, connector->base.name); > > - if (connector->state->crtc != &crtc->base) > - continue; > - > - seq_printf(m, "%s:\n", connector->name); > - > - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && > - drrs->type == DRRS_TYPE_SEAMLESS) > - supported = true; > - > - seq_printf(m, "\tDRRS Supported: %s\n", str_yes_no(supported)); > + seq_printf(m, "\tDRRS Supported: %s\n", > + str_yes_no(connector->panel.downclock_mode)); > } > drm_connector_list_iter_end(&conn_iter); > > seq_puts(m, "\n"); > > - if (to_intel_crtc_state(crtc->base.state)->has_drrs) { > - struct intel_panel *panel; > + for_each_intel_crtc(&dev_priv->drm, crtc) { > + seq_printf(m, "[CRTC:%d:%s]:\n", > + crtc->base.base.id, crtc->base.name); > + > + mutex_lock(&crtc->drrs.mutex); > > - mutex_lock(&drrs->mutex); > /* DRRS Supported */ > - seq_puts(m, "\tDRRS Enabled: Yes\n"); > + seq_printf(m, "\tDRRS Enabled: %s\n", > + str_yes_no(intel_drrs_is_enabled(crtc))); > > - /* disable_drrs() will make drrs->dp NULL */ > - if (!drrs->dp) { > - seq_puts(m, "Idleness DRRS: Disabled\n"); > - mutex_unlock(&drrs->mutex); > - return; > - } > - > - panel = &drrs->dp->attached_connector->panel; > - seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X", > - drrs->busy_frontbuffer_bits); > - > - seq_puts(m, "\n\t\t"); > + seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X", > + crtc->drrs.busy_frontbuffer_bits); > > seq_printf(m, "DRRS refresh rate: %s\n", > - drrs->refresh_rate == DRRS_REFRESH_RATE_LOW ? > + crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ? > "low" : "high"); > - seq_puts(m, "\n\t\t"); > > - mutex_unlock(&drrs->mutex); > - } else { > - /* DRRS not supported. Print the VBT parameter*/ > - seq_puts(m, "\tDRRS Enabled : No"); > + mutex_unlock(&crtc->drrs.mutex); > } > - seq_puts(m, "\n"); > -} > - > -static int i915_drrs_status(struct seq_file *m, void *unused) > -{ > - struct drm_i915_private *dev_priv = node_to_i915(m->private); > - struct drm_device *dev = &dev_priv->drm; > - struct intel_crtc *crtc; > - int active_crtc_cnt = 0; > - > - drm_modeset_lock_all(dev); > - for_each_intel_crtc(dev, crtc) { > - if (crtc->base.state->active) { > - active_crtc_cnt++; > - seq_printf(m, "\nCRTC %d: ", active_crtc_cnt); > - > - drrs_status_per_crtc(m, dev, crtc); > - } > - } > - drm_modeset_unlock_all(dev); > - > - if (!active_crtc_cnt) > - seq_puts(m, "No active crtc found\n"); > > return 0; > } > @@ -1917,26 +1874,18 @@ static int i915_drrs_ctl_set(void *data, u64 val) > > drm_connector_list_iter_begin(dev, &conn_iter); > drm_for_each_connector_iter(connector, &conn_iter) { > - struct intel_encoder *encoder; > - struct intel_dp *intel_dp; > - > if (!(crtc_state->uapi.connector_mask & > drm_connector_mask(connector))) > continue; > > - encoder = intel_attached_encoder(to_intel_connector(connector)); > - if (encoder->type != INTEL_OUTPUT_EDP) > - continue; > - > drm_dbg(&dev_priv->drm, > "Manually %sabling DRRS. %llu\n", > val ? "en" : "dis", val); > > - intel_dp = enc_to_intel_dp(encoder); > if (val) > - intel_drrs_enable(intel_dp, crtc_state); > + intel_drrs_enable(crtc_state); > else > - intel_drrs_disable(intel_dp, crtc_state); > + intel_drrs_disable(crtc_state); > } > drm_connector_list_iter_end(&conn_iter); > > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h > index 86b2fa675124..e34800ab6924 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_types.h > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h > @@ -1252,6 +1252,11 @@ enum intel_pipe_crc_source { > INTEL_PIPE_CRC_SOURCE_MAX, > }; > > +enum drrs_refresh_rate { > + DRRS_REFRESH_RATE_HIGH, > + DRRS_REFRESH_RATE_LOW, > +}; > + > #define INTEL_PIPE_CRC_ENTRIES_NR 128 > struct intel_pipe_crc { > spinlock_t lock; > @@ -1294,6 +1299,15 @@ struct intel_crtc { > } active; > } wm; > > + struct { > + struct mutex mutex; > + struct delayed_work work; > + enum drrs_refresh_rate refresh_rate; > + unsigned int busy_frontbuffer_bits; > + enum transcoder cpu_transcoder; > + struct intel_link_m_n m_n, m2_n2; > + } drrs; > + > int scanline_offset; > > struct { > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c > index 619546441eae..725c3350c923 100644 > --- a/drivers/gpu/drm/i915/display/intel_dp.c > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > @@ -1895,8 +1895,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, > > intel_vrr_compute_config(pipe_config, conn_state); > intel_psr_compute_config(intel_dp, pipe_config, conn_state); > - intel_drrs_compute_config(intel_dp, pipe_config, output_bpp, > - constant_n); > + intel_drrs_compute_config(pipe_config, intel_connector, > + output_bpp, constant_n); > intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state); > intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state); > > diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c > index c97b5dee8cae..246dd0c71194 100644 > --- a/drivers/gpu/drm/i915/display/intel_drrs.c > +++ b/drivers/gpu/drm/i915/display/intel_drrs.c > @@ -65,15 +65,14 @@ static bool can_enable_drrs(struct intel_connector *connector, > return false; > > return connector->panel.downclock_mode && > - i915->drrs.type == DRRS_TYPE_SEAMLESS; > + i915->vbt.drrs_type == DRRS_TYPE_SEAMLESS; > } > > void > -intel_drrs_compute_config(struct intel_dp *intel_dp, > - struct intel_crtc_state *pipe_config, > +intel_drrs_compute_config(struct intel_crtc_state *pipe_config, > + struct intel_connector *connector, > int output_bpp, bool constant_n) > { > - struct intel_connector *connector = intel_dp->attached_connector; > struct drm_i915_private *i915 = to_i915(connector->base.dev); > int pixel_clock; > > @@ -102,12 +101,11 @@ intel_drrs_compute_config(struct intel_dp *intel_dp, > } > > static void > -intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state, > +intel_drrs_set_refresh_rate_pipeconf(struct intel_crtc *crtc, > enum drrs_refresh_rate refresh_rate) > { > - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; > + enum transcoder cpu_transcoder = crtc->drrs.cpu_transcoder; > u32 val, bit; > > if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) > @@ -126,240 +124,166 @@ intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state, > } > > static void > -intel_drrs_set_refresh_rate_m_n(const struct intel_crtc_state *crtc_state, > +intel_drrs_set_refresh_rate_m_n(struct intel_crtc *crtc, > enum drrs_refresh_rate refresh_rate) > { > - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > - > - intel_cpu_transcoder_set_m1_n1(crtc, crtc_state->cpu_transcoder, > + intel_cpu_transcoder_set_m1_n1(crtc, crtc->drrs.cpu_transcoder, > refresh_rate == DRRS_REFRESH_RATE_LOW ? > - &crtc_state->dp_m2_n2 : &crtc_state->dp_m_n); > + &crtc->drrs.m2_n2 : &crtc->drrs.m_n); > } > > -static void intel_drrs_set_state(struct drm_i915_private *dev_priv, > - const struct intel_crtc_state *crtc_state, > +bool intel_drrs_is_enabled(struct intel_crtc *crtc) > +{ > + return crtc->drrs.cpu_transcoder != INVALID_TRANSCODER; > +} > + > +static void intel_drrs_set_state(struct intel_crtc *crtc, > enum drrs_refresh_rate refresh_rate) > { > - struct intel_dp *intel_dp = dev_priv->drrs.dp; > - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > > - if (!intel_dp) { > - drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n"); > + if (refresh_rate == crtc->drrs.refresh_rate) > return; > - } > - > - if (!crtc) { > - drm_dbg_kms(&dev_priv->drm, > - "DRRS: intel_crtc not initialized\n"); > - return; > - } > - > - if (dev_priv->drrs.type != DRRS_TYPE_SEAMLESS) { > - drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n"); > - return; > - } > - > - if (refresh_rate == dev_priv->drrs.refresh_rate) > - return; > - > - if (!crtc_state->hw.active) { > - drm_dbg_kms(&dev_priv->drm, > - "eDP encoder disabled. CRTC not Active\n"); > - return; > - } > > if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) > - intel_drrs_set_refresh_rate_m_n(crtc_state, refresh_rate); > + intel_drrs_set_refresh_rate_m_n(crtc, refresh_rate); > else if (DISPLAY_VER(dev_priv) > 6) > - intel_drrs_set_refresh_rate_pipeconf(crtc_state, refresh_rate); > + intel_drrs_set_refresh_rate_pipeconf(crtc, refresh_rate); > > - dev_priv->drrs.refresh_rate = refresh_rate; > - > - drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %s\n", > - refresh_rate == DRRS_REFRESH_RATE_LOW ? "low" : "high"); > -} > - > -static void > -intel_drrs_enable_locked(struct intel_dp *intel_dp) > -{ > - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); > - > - dev_priv->drrs.busy_frontbuffer_bits = 0; > - dev_priv->drrs.dp = intel_dp; > + crtc->drrs.refresh_rate = refresh_rate; > } > > /** > * intel_drrs_enable - init drrs struct if supported > - * @intel_dp: DP struct > * @crtc_state: A pointer to the active crtc state. > * > * Initializes frontbuffer_bits and drrs.dp > */ > -void intel_drrs_enable(struct intel_dp *intel_dp, > - const struct intel_crtc_state *crtc_state) > +void intel_drrs_enable(const struct intel_crtc_state *crtc_state) > { > - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > > if (!crtc_state->has_drrs) > return; > > - drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n"); > + drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Enabling DRRS\n", > + crtc->base.base.id, crtc->base.name); > > - mutex_lock(&dev_priv->drrs.mutex); > + mutex_lock(&crtc->drrs.mutex); > > - if (dev_priv->drrs.dp) { > - drm_warn(&dev_priv->drm, "DRRS already enabled\n"); > - goto unlock; > - } > + crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder; > + crtc->drrs.m_n = crtc_state->dp_m_n; > + crtc->drrs.m2_n2 = crtc_state->dp_m2_n2; > + crtc->drrs.busy_frontbuffer_bits = 0; > > - intel_drrs_enable_locked(intel_dp); > - > -unlock: > - mutex_unlock(&dev_priv->drrs.mutex); > -} > - > -static void > -intel_drrs_disable_locked(struct intel_dp *intel_dp, > - const struct intel_crtc_state *crtc_state) > -{ > - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); > - > - intel_drrs_set_state(dev_priv, crtc_state, DRRS_REFRESH_RATE_HIGH); > - dev_priv->drrs.dp = NULL; > + mutex_unlock(&crtc->drrs.mutex); > } > > /** > * intel_drrs_disable - Disable DRRS > - * @intel_dp: DP struct > - * @old_crtc_state: Pointer to old crtc_state. > + * @old_crtc_state: old crtc_state. > * > */ > -void intel_drrs_disable(struct intel_dp *intel_dp, > - const struct intel_crtc_state *old_crtc_state) > +void intel_drrs_disable(const struct intel_crtc_state *old_crtc_state) > { > - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); > + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > > if (!old_crtc_state->has_drrs) > return; > > - mutex_lock(&dev_priv->drrs.mutex); > - if (!dev_priv->drrs.dp) { > - mutex_unlock(&dev_priv->drrs.mutex); > - return; > - } > + drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Disabling DRRS\n", > + crtc->base.base.id, crtc->base.name); > > - intel_drrs_disable_locked(intel_dp, old_crtc_state); > - mutex_unlock(&dev_priv->drrs.mutex); > + mutex_lock(&crtc->drrs.mutex); > > - cancel_delayed_work_sync(&dev_priv->drrs.work); > + if (intel_drrs_is_enabled(crtc)) > + intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); > + > + crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; > + crtc->drrs.busy_frontbuffer_bits = 0; > + > + mutex_unlock(&crtc->drrs.mutex); > + > + cancel_delayed_work_sync(&crtc->drrs.work); > } > > /** > - * intel_drrs_update - Update DRRS state > - * @intel_dp: Intel DP > - * @crtc_state: new CRTC state > - * > - * This function will update DRRS states, disabling or enabling DRRS when > - * executing fastsets. For full modeset, intel_drrs_disable() and > - * intel_drrs_enable() should be called instead. > + * intel_drrs_update - Update DRRS during fastset > + * @state: atomic state > + * @crtc: crtc > */ > -void > -intel_drrs_update(struct intel_dp *intel_dp, > - const struct intel_crtc_state *crtc_state) > +void intel_drrs_update(struct intel_atomic_state *state, > + struct intel_crtc *crtc) > { > - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); > + const struct intel_crtc_state *old_crtc_state = > + intel_atomic_get_old_crtc_state(state, crtc); > + const struct intel_crtc_state *new_crtc_state = > + intel_atomic_get_new_crtc_state(state, crtc); > > - if (dev_priv->drrs.type != DRRS_TYPE_SEAMLESS) > + if (old_crtc_state->has_drrs == new_crtc_state->has_drrs) > return; > > - mutex_lock(&dev_priv->drrs.mutex); > - > - /* New state matches current one? */ > - if (crtc_state->has_drrs == !!dev_priv->drrs.dp) > - goto unlock; > - > - if (crtc_state->has_drrs) > - intel_drrs_enable_locked(intel_dp); > + if (new_crtc_state->has_drrs) > + intel_drrs_enable(new_crtc_state); > else > - intel_drrs_disable_locked(intel_dp, crtc_state); > - > -unlock: > - mutex_unlock(&dev_priv->drrs.mutex); > + intel_drrs_disable(old_crtc_state); > } > > static void intel_drrs_downclock_work(struct work_struct *work) > { > - struct drm_i915_private *dev_priv = > - container_of(work, typeof(*dev_priv), drrs.work.work); > - struct intel_dp *intel_dp; > + struct intel_crtc *crtc = container_of(work, typeof(*crtc), drrs.work.work); > > - mutex_lock(&dev_priv->drrs.mutex); > + mutex_lock(&crtc->drrs.mutex); > > - intel_dp = dev_priv->drrs.dp; > + if (intel_drrs_is_enabled(crtc) && !crtc->drrs.busy_frontbuffer_bits) > + intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_LOW); > > - if (!intel_dp) > - goto unlock; > - > - /* > - * The delayed work can race with an invalidate hence we need to > - * recheck. > - */ > - > - if (!dev_priv->drrs.busy_frontbuffer_bits) { > - struct intel_crtc *crtc = > - to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); > - > - intel_drrs_set_state(dev_priv, crtc->config, > - DRRS_REFRESH_RATE_LOW); > - } > - > -unlock: > - mutex_unlock(&dev_priv->drrs.mutex); > + mutex_unlock(&crtc->drrs.mutex); > } > > static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, > unsigned int frontbuffer_bits, > bool invalidate) > { > - struct intel_dp *intel_dp; > - struct drm_crtc *crtc; > - enum pipe pipe; > + struct intel_crtc *crtc; > > - if (dev_priv->drrs.type != DRRS_TYPE_SEAMLESS) > + if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) > return; > > - cancel_delayed_work(&dev_priv->drrs.work); > + for_each_intel_crtc(&dev_priv->drm, crtc) { > + enum pipe pipe = crtc->pipe; > > - mutex_lock(&dev_priv->drrs.mutex); > + cancel_delayed_work(&crtc->drrs.work); Not a good idea cancel work at this point, you could be canceling work even if CRTC of eDP is not being updated. > > - intel_dp = dev_priv->drrs.dp; > - if (!intel_dp) { > - mutex_unlock(&dev_priv->drrs.mutex); > - return; > + mutex_lock(&crtc->drrs.mutex); > + > + if (!intel_drrs_is_enabled(crtc)) { > + mutex_unlock(&crtc->drrs.mutex); > + continue; > + } > + > + frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe); > + if (invalidate) > + crtc->drrs.busy_frontbuffer_bits |= frontbuffer_bits; > + else > + crtc->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits; > + > + /* flush/invalidate means busy screen hence upclock */ > + if (frontbuffer_bits) > + intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); > + > + /* > + * flush also means no more activity hence schedule downclock, if all > + * other fbs are quiescent too > + */ > + if (!invalidate && !crtc->drrs.busy_frontbuffer_bits) > + schedule_delayed_work(&crtc->drrs.work, > + msecs_to_jiffies(1000)); > + > + mutex_unlock(&crtc->drrs.mutex); > } > - > - crtc = dp_to_dig_port(intel_dp)->base.base.crtc; > - pipe = to_intel_crtc(crtc)->pipe; > - > - frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe); > - if (invalidate) > - dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits; > - else > - dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits; > - > - /* flush/invalidate means busy screen hence upclock */ > - if (frontbuffer_bits) > - intel_drrs_set_state(dev_priv, to_intel_crtc(crtc)->config, > - DRRS_REFRESH_RATE_HIGH); > - > - /* > - * flush also means no more activity hence schedule downclock, if all > - * other fbs are quiescent too > - */ > - if (!invalidate && !dev_priv->drrs.busy_frontbuffer_bits) > - schedule_delayed_work(&dev_priv->drrs.work, > - msecs_to_jiffies(1000)); > - mutex_unlock(&dev_priv->drrs.mutex); > } > > /** > @@ -396,22 +320,36 @@ void intel_drrs_flush(struct drm_i915_private *dev_priv, > intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false); > } > > -void intel_drrs_page_flip(struct intel_atomic_state *state, > - struct intel_crtc *crtc) > +void intel_drrs_page_flip(struct intel_crtc *crtc) > { > - struct drm_i915_private *dev_priv = to_i915(state->base.dev); > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > unsigned int frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); > > intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false); > } > > /** > - * intel_drrs_init - Init basic DRRS work and mutex. > + * intel_crtc_drrs_init - Init DRRS for CRTC > + * @crtc: crtc > + * > + * This function is called only once at driver load to initialize basic > + * DRRS stuff. > + * > + */ > +void intel_crtc_drrs_init(struct intel_crtc *crtc) > +{ > + INIT_DELAYED_WORK(&crtc->drrs.work, intel_drrs_downclock_work); > + mutex_init(&crtc->drrs.mutex); > + crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; > +} > + > +/** > + * intel_drrs_init - Init DRRS for eDP connector > * @connector: eDP connector > * @fixed_mode: preferred mode of panel > * > - * This function is called only once at driver load to initialize basic > - * DRRS stuff. > + * This function is called only once at driver load to initialize > + * DRRS support for the connector. > * > * Returns: > * Downclock mode if panel supports it, else return NULL. > @@ -424,10 +362,7 @@ intel_drrs_init(struct intel_connector *connector, > { > struct drm_i915_private *dev_priv = to_i915(connector->base.dev); > struct intel_encoder *encoder = connector->encoder; > - struct drm_display_mode *downclock_mode = NULL; > - > - INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_drrs_downclock_work); > - mutex_init(&dev_priv->drrs.mutex); > + struct drm_display_mode *downclock_mode; > > if (DISPLAY_VER(dev_priv) <= 6) { > drm_dbg_kms(&dev_priv->drm, > @@ -460,9 +395,6 @@ intel_drrs_init(struct intel_connector *connector, > return NULL; > } > > - dev_priv->drrs.type = dev_priv->vbt.drrs_type; > - > - dev_priv->drrs.refresh_rate = DRRS_REFRESH_RATE_HIGH; > drm_dbg_kms(&dev_priv->drm, > "[CONNECTOR:%d:%s] seamless DRRS supported\n", > connector->base.base.id, connector->base.name); > diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h > index 6bca7692f59f..9347cf451789 100644 > --- a/drivers/gpu/drm/i915/display/intel_drrs.h > +++ b/drivers/gpu/drm/i915/display/intel_drrs.h > @@ -13,23 +13,21 @@ struct intel_atomic_state; > struct intel_crtc; > struct intel_crtc_state; > struct intel_connector; > -struct intel_dp; > > -void intel_drrs_enable(struct intel_dp *intel_dp, > - const struct intel_crtc_state *crtc_state); > -void intel_drrs_disable(struct intel_dp *intel_dp, > - const struct intel_crtc_state *crtc_state); > -void intel_drrs_update(struct intel_dp *intel_dp, > - const struct intel_crtc_state *crtc_state); > +bool intel_drrs_is_enabled(struct intel_crtc *crtc); > +void intel_drrs_enable(const struct intel_crtc_state *crtc_state); > +void intel_drrs_disable(const struct intel_crtc_state *crtc_state); > +void intel_drrs_update(struct intel_atomic_state *state, > + struct intel_crtc *crtc); > void intel_drrs_invalidate(struct drm_i915_private *dev_priv, > unsigned int frontbuffer_bits); > void intel_drrs_flush(struct drm_i915_private *dev_priv, > unsigned int frontbuffer_bits); > -void intel_drrs_page_flip(struct intel_atomic_state *state, > - struct intel_crtc *crtc); > -void intel_drrs_compute_config(struct intel_dp *intel_dp, > - struct intel_crtc_state *pipe_config, > +void intel_drrs_page_flip(struct intel_crtc *crtc); > +void intel_drrs_compute_config(struct intel_crtc_state *pipe_config, > + struct intel_connector *connector, > int output_bpp, bool constant_n); > +void intel_crtc_drrs_init(struct intel_crtc *crtc); > struct drm_display_mode *intel_drrs_init(struct intel_connector *connector, > const struct drm_display_mode *fixed_mode); > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 7d622d1afe93..26df561a4e94 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -196,26 +196,12 @@ struct drm_i915_display_funcs { > > #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ > > -enum drrs_refresh_rate { > - DRRS_REFRESH_RATE_HIGH, > - DRRS_REFRESH_RATE_LOW, > -}; > - > enum drrs_type { > DRRS_TYPE_NONE, > DRRS_TYPE_STATIC, > DRRS_TYPE_SEAMLESS, > }; > > -struct i915_drrs { > - struct mutex mutex; > - struct delayed_work work; > - struct intel_dp *dp; > - unsigned busy_frontbuffer_bits; > - enum drrs_refresh_rate refresh_rate; > - enum drrs_type type; > -}; > - > #define QUIRK_LVDS_SSC_DISABLE (1<<1) > #define QUIRK_INVERT_BRIGHTNESS (1<<2) > #define QUIRK_BACKLIGHT_PRESENT (1<<3) > @@ -537,7 +523,6 @@ struct drm_i915_private { > > struct i915_hotplug hotplug; > struct intel_fbc *fbc[I915_MAX_FBCS]; > - struct i915_drrs drrs; > struct intel_opregion opregion; > struct intel_vbt_data vbt; >