Message ID | 1396680208-19390-1-git-send-email-vandana.kannan@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Reviewed-by: Jani Nikula <jani.nikula@intel.com> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote: > From: Pradeep Bhat <pradeep.bhat@intel.com> > > This patch computes and stored 2nd M/N/TU for switching to different > refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle > between alternate refresh rates programmed in 2nd M/N/TU registers. > > v2: Daniel's review comments > Computing M2/N2 in compute_config and storing it in crtc_config > > v3: Modified reference to edp_downclock and edp_downclock_avail based on the > changes made to move them from dev_private to intel_panel. > > v4: Modified references to is_drrs_supported based on the changes made to > rename it to drrs_support. > > v5: Jani's review comments > Removed superfluous return statements. Changed support for Gen 7 and above. > Corrected indentation. Re-structured the code which finds crtc and connector > from encoder. Changed some logs to be less verbose. > > v6: Modifying i915_drrs to include only intel connector as intel_dp can be > derived from intel connector when required. > > v7: As per internal review comments, acquiring mutex just before accessing > drrs RR. As per Chris's review comments, added documentation about the use > of locking in the function. > > v8: Incorporated Jani's review comments. > Removed reference to edp_downclock. > > v9: Jani's review comments. Modified comment in set_drrs. Changed index to > type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting > registers fo DRRS. > > Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com> > Signed-off-by: Vandana Kannan <vandana.kannan@intel.com> > Cc: Jani Nikula <jani.nikula@linux.intel.com> > --- > drivers/gpu/drm/i915/i915_drv.h | 5 ++ > drivers/gpu/drm/i915/i915_reg.h | 1 + > drivers/gpu/drm/i915/intel_dp.c | 110 +++++++++++++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/intel_drv.h | 6 ++- > 4 files changed, 121 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 55addaa..9da8d83 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -633,6 +633,10 @@ struct i915_fbc { > } no_fbc_reason; > }; > > +struct i915_drrs { > + struct intel_connector *connector; > +}; > + > struct i915_psr { > bool sink_support; > bool source_ok; > @@ -1320,6 +1324,7 @@ struct drm_i915_private { > struct timer_list hotplug_reenable_timer; > > struct i915_fbc fbc; > + struct i915_drrs drrs; > struct intel_opregion opregion; > struct intel_vbt_data vbt; > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 2315366..d6dddc2 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -3346,6 +3346,7 @@ enum punit_power_well { > #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */ > #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */ > #define PIPECONF_INTERLACE_MODE_MASK (7 << 21) > +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20) > #define PIPECONF_CXSR_DOWNCLOCK (1<<16) > #define PIPECONF_COLOR_RANGE_SELECT (1 << 13) > #define PIPECONF_BPC_MASK (0x7 << 5) > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index 517a8cc..b50b170 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder, > } > } > > +static void > +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n) > +{ > + struct drm_device *dev = crtc->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum transcoder transcoder = crtc->config.cpu_transcoder; > + > + I915_WRITE(PIPE_DATA_M2(transcoder), > + TU_SIZE(m_n->tu) | m_n->gmch_m); > + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n); > + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m); > + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n); > +} > + > bool > intel_dp_compute_config(struct intel_encoder *encoder, > struct intel_crtc_config *pipe_config) > @@ -841,6 +855,14 @@ found: > pipe_config->port_clock, > &pipe_config->dp_m_n); > > + if (intel_connector->panel.downclock_mode != NULL && > + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) { > + intel_link_compute_m_n(bpp, lane_count, > + intel_connector->panel.downclock_mode->clock, > + pipe_config->port_clock, > + &pipe_config->dp_m2_n2); > + } > + > intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); > > return true; > @@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, > I915_READ(pp_div_reg)); > } > > +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_encoder *encoder; > + struct intel_dp *intel_dp = NULL; > + struct intel_crtc_config *config = NULL; > + struct intel_crtc *intel_crtc = NULL; > + struct intel_connector *intel_connector = dev_priv->drrs.connector; > + u32 reg, val; > + enum edp_drrs_refresh_rate_type index = DRRS_HIGH_RR; > + > + if (refresh_rate <= 0) { > + DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n"); > + return; > + } > + > + if (intel_connector == NULL) { > + DRM_DEBUG_KMS("DRRS supported for eDP only.\n"); > + return; > + } > + > + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) { > + DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n"); > + return; > + } > + > + encoder = intel_attached_encoder(&intel_connector->base); > + intel_dp = enc_to_intel_dp(&encoder->base); > + intel_crtc = encoder->new_crtc; > + > + if (!intel_crtc) { > + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n"); > + return; > + } > + > + config = &intel_crtc->config; > + > + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) { > + DRM_DEBUG_KMS("Only Seamless DRRS supported.\n"); > + return; > + } > + > + if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate) > + index = DRRS_LOW_RR; > + > + if (index == intel_dp->drrs_state.refresh_rate_type) { > + DRM_DEBUG_KMS( > + "DRRS requested for previously set RR...ignoring\n"); > + return; > + } > + > + if (!intel_crtc->active) { > + DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n"); > + return; > + } > + > + if (INTEL_INFO(dev)->gen > 6 && INTEL_INFO(dev)->gen < 8) { > + reg = PIPECONF(intel_crtc->config.cpu_transcoder); > + val = I915_READ(reg); > + if (index > DRRS_HIGH_RR) { > + val |= PIPECONF_EDP_RR_MODE_SWITCH; > + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2); > + } else { > + val &= ~PIPECONF_EDP_RR_MODE_SWITCH; > + } > + I915_WRITE(reg, val); > + } > + > + /* > + * mutex taken to ensure that there is no race between differnt > + * drrs calls trying to update refresh rate. This scenario may occur > + * in future when idleness detection based DRRS in kernel and > + * possible calls from user space to set differnt RR are made. > + */ > + > + mutex_lock(&intel_dp->drrs_state.mutex); > + > + intel_dp->drrs_state.refresh_rate_type = index; > + > + mutex_unlock(&intel_dp->drrs_state.mutex); > + > + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate); > +} > + > static struct drm_display_mode * > intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, > struct intel_connector *intel_connector, > @@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, > return NULL; > } > > + dev_priv->drrs.connector = intel_connector; > + > + mutex_init(&intel_dp->drrs_state.mutex); > + > intel_dp->drrs_state.type = dev_priv->vbt.drrs_type; > > intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR; > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 286d4fb..37d56e5 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -305,6 +305,9 @@ struct intel_crtc_config { > int pipe_bpp; > struct intel_link_m_n dp_m_n; > > + /* m2_n2 for eDP downclock */ > + struct intel_link_m_n dp_m2_n2; > + > /* > * Frequence the dpll for the port should run at. Differs from the > * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also > @@ -534,6 +537,7 @@ struct intel_dp { > struct { > enum drrs_support_type type; > enum edp_drrs_refresh_rate_type refresh_rate_type; > + struct mutex mutex; > } drrs_state; > > }; > @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp); > void intel_edp_psr_enable(struct intel_dp *intel_dp); > void intel_edp_psr_disable(struct intel_dp *intel_dp); > void intel_edp_psr_update(struct drm_device *dev); > - > +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate); > > /* intel_dsi.c */ > bool intel_dsi_init(struct drm_device *dev); > -- > 1.9.1 >
On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote: > > Reviewed-by: Jani Nikula <jani.nikula@intel.com> > > > On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote: > > From: Pradeep Bhat <pradeep.bhat@intel.com> > > > > This patch computes and stored 2nd M/N/TU for switching to different > > refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle > > between alternate refresh rates programmed in 2nd M/N/TU registers. > > > > v2: Daniel's review comments > > Computing M2/N2 in compute_config and storing it in crtc_config > > > > v3: Modified reference to edp_downclock and edp_downclock_avail based on the > > changes made to move them from dev_private to intel_panel. > > > > v4: Modified references to is_drrs_supported based on the changes made to > > rename it to drrs_support. > > > > v5: Jani's review comments > > Removed superfluous return statements. Changed support for Gen 7 and above. > > Corrected indentation. Re-structured the code which finds crtc and connector > > from encoder. Changed some logs to be less verbose. > > > > v6: Modifying i915_drrs to include only intel connector as intel_dp can be > > derived from intel connector when required. > > > > v7: As per internal review comments, acquiring mutex just before accessing > > drrs RR. As per Chris's review comments, added documentation about the use > > of locking in the function. > > > > v8: Incorporated Jani's review comments. > > Removed reference to edp_downclock. > > > > v9: Jani's review comments. Modified comment in set_drrs. Changed index to > > type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting > > registers fo DRRS. > > > > Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com> > > Signed-off-by: Vandana Kannan <vandana.kannan@intel.com> > > Cc: Jani Nikula <jani.nikula@linux.intel.com> Queued for -next, thanks for the patch. -Daniel > > --- > > drivers/gpu/drm/i915/i915_drv.h | 5 ++ > > drivers/gpu/drm/i915/i915_reg.h | 1 + > > drivers/gpu/drm/i915/intel_dp.c | 110 +++++++++++++++++++++++++++++++++++++++ > > drivers/gpu/drm/i915/intel_drv.h | 6 ++- > > 4 files changed, 121 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > > index 55addaa..9da8d83 100644 > > --- a/drivers/gpu/drm/i915/i915_drv.h > > +++ b/drivers/gpu/drm/i915/i915_drv.h > > @@ -633,6 +633,10 @@ struct i915_fbc { > > } no_fbc_reason; > > }; > > > > +struct i915_drrs { > > + struct intel_connector *connector; > > +}; > > + > > struct i915_psr { > > bool sink_support; > > bool source_ok; > > @@ -1320,6 +1324,7 @@ struct drm_i915_private { > > struct timer_list hotplug_reenable_timer; > > > > struct i915_fbc fbc; > > + struct i915_drrs drrs; > > struct intel_opregion opregion; > > struct intel_vbt_data vbt; > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > > index 2315366..d6dddc2 100644 > > --- a/drivers/gpu/drm/i915/i915_reg.h > > +++ b/drivers/gpu/drm/i915/i915_reg.h > > @@ -3346,6 +3346,7 @@ enum punit_power_well { > > #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */ > > #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */ > > #define PIPECONF_INTERLACE_MODE_MASK (7 << 21) > > +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20) > > #define PIPECONF_CXSR_DOWNCLOCK (1<<16) > > #define PIPECONF_COLOR_RANGE_SELECT (1 << 13) > > #define PIPECONF_BPC_MASK (0x7 << 5) > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > > index 517a8cc..b50b170 100644 > > --- a/drivers/gpu/drm/i915/intel_dp.c > > +++ b/drivers/gpu/drm/i915/intel_dp.c > > @@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder, > > } > > } > > > > +static void > > +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n) > > +{ > > + struct drm_device *dev = crtc->base.dev; > > + struct drm_i915_private *dev_priv = dev->dev_private; > > + enum transcoder transcoder = crtc->config.cpu_transcoder; > > + > > + I915_WRITE(PIPE_DATA_M2(transcoder), > > + TU_SIZE(m_n->tu) | m_n->gmch_m); > > + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n); > > + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m); > > + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n); > > +} > > + > > bool > > intel_dp_compute_config(struct intel_encoder *encoder, > > struct intel_crtc_config *pipe_config) > > @@ -841,6 +855,14 @@ found: > > pipe_config->port_clock, > > &pipe_config->dp_m_n); > > > > + if (intel_connector->panel.downclock_mode != NULL && > > + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) { > > + intel_link_compute_m_n(bpp, lane_count, > > + intel_connector->panel.downclock_mode->clock, > > + pipe_config->port_clock, > > + &pipe_config->dp_m2_n2); > > + } > > + > > intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); > > > > return true; > > @@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, > > I915_READ(pp_div_reg)); > > } > > > > +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) > > +{ > > + struct drm_i915_private *dev_priv = dev->dev_private; > > + struct intel_encoder *encoder; > > + struct intel_dp *intel_dp = NULL; > > + struct intel_crtc_config *config = NULL; > > + struct intel_crtc *intel_crtc = NULL; > > + struct intel_connector *intel_connector = dev_priv->drrs.connector; > > + u32 reg, val; > > + enum edp_drrs_refresh_rate_type index = DRRS_HIGH_RR; > > + > > + if (refresh_rate <= 0) { > > + DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n"); > > + return; > > + } > > + > > + if (intel_connector == NULL) { > > + DRM_DEBUG_KMS("DRRS supported for eDP only.\n"); > > + return; > > + } > > + > > + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) { > > + DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n"); > > + return; > > + } > > + > > + encoder = intel_attached_encoder(&intel_connector->base); > > + intel_dp = enc_to_intel_dp(&encoder->base); > > + intel_crtc = encoder->new_crtc; > > + > > + if (!intel_crtc) { > > + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n"); > > + return; > > + } > > + > > + config = &intel_crtc->config; > > + > > + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) { > > + DRM_DEBUG_KMS("Only Seamless DRRS supported.\n"); > > + return; > > + } > > + > > + if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate) > > + index = DRRS_LOW_RR; > > + > > + if (index == intel_dp->drrs_state.refresh_rate_type) { > > + DRM_DEBUG_KMS( > > + "DRRS requested for previously set RR...ignoring\n"); > > + return; > > + } > > + > > + if (!intel_crtc->active) { > > + DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n"); > > + return; > > + } > > + > > + if (INTEL_INFO(dev)->gen > 6 && INTEL_INFO(dev)->gen < 8) { > > + reg = PIPECONF(intel_crtc->config.cpu_transcoder); > > + val = I915_READ(reg); > > + if (index > DRRS_HIGH_RR) { > > + val |= PIPECONF_EDP_RR_MODE_SWITCH; > > + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2); > > + } else { > > + val &= ~PIPECONF_EDP_RR_MODE_SWITCH; > > + } > > + I915_WRITE(reg, val); > > + } > > + > > + /* > > + * mutex taken to ensure that there is no race between differnt > > + * drrs calls trying to update refresh rate. This scenario may occur > > + * in future when idleness detection based DRRS in kernel and > > + * possible calls from user space to set differnt RR are made. > > + */ > > + > > + mutex_lock(&intel_dp->drrs_state.mutex); > > + > > + intel_dp->drrs_state.refresh_rate_type = index; > > + > > + mutex_unlock(&intel_dp->drrs_state.mutex); > > + > > + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate); > > +} > > + > > static struct drm_display_mode * > > intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, > > struct intel_connector *intel_connector, > > @@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, > > return NULL; > > } > > > > + dev_priv->drrs.connector = intel_connector; > > + > > + mutex_init(&intel_dp->drrs_state.mutex); > > + > > intel_dp->drrs_state.type = dev_priv->vbt.drrs_type; > > > > intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR; > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > > index 286d4fb..37d56e5 100644 > > --- a/drivers/gpu/drm/i915/intel_drv.h > > +++ b/drivers/gpu/drm/i915/intel_drv.h > > @@ -305,6 +305,9 @@ struct intel_crtc_config { > > int pipe_bpp; > > struct intel_link_m_n dp_m_n; > > > > + /* m2_n2 for eDP downclock */ > > + struct intel_link_m_n dp_m2_n2; > > + > > /* > > * Frequence the dpll for the port should run at. Differs from the > > * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also > > @@ -534,6 +537,7 @@ struct intel_dp { > > struct { > > enum drrs_support_type type; > > enum edp_drrs_refresh_rate_type refresh_rate_type; > > + struct mutex mutex; > > } drrs_state; > > > > }; > > @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp); > > void intel_edp_psr_enable(struct intel_dp *intel_dp); > > void intel_edp_psr_disable(struct intel_dp *intel_dp); > > void intel_edp_psr_update(struct drm_device *dev); > > - > > +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate); > > > > /* intel_dsi.c */ > > bool intel_dsi_init(struct drm_device *dev); > > -- > > 1.9.1 > > > > -- > Jani Nikula, Intel Open Source Technology Center > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote: > > Reviewed-by: Jani Nikula <jani.nikula@intel.com> > > > On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote: > > From: Pradeep Bhat <pradeep.bhat@intel.com> > > > > This patch computes and stored 2nd M/N/TU for switching to different > > refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle > > between alternate refresh rates programmed in 2nd M/N/TU registers. > > > > v2: Daniel's review comments > > Computing M2/N2 in compute_config and storing it in crtc_config > > > > v3: Modified reference to edp_downclock and edp_downclock_avail based on the > > changes made to move them from dev_private to intel_panel. > > > > v4: Modified references to is_drrs_supported based on the changes made to > > rename it to drrs_support. > > > > v5: Jani's review comments > > Removed superfluous return statements. Changed support for Gen 7 and above. > > Corrected indentation. Re-structured the code which finds crtc and connector > > from encoder. Changed some logs to be less verbose. > > > > v6: Modifying i915_drrs to include only intel connector as intel_dp can be > > derived from intel connector when required. > > > > v7: As per internal review comments, acquiring mutex just before accessing > > drrs RR. As per Chris's review comments, added documentation about the use > > of locking in the function. > > > > v8: Incorporated Jani's review comments. > > Removed reference to edp_downclock. > > > > v9: Jani's review comments. Modified comment in set_drrs. Changed index to > > type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting > > registers fo DRRS. > > > > Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com> > > Signed-off-by: Vandana Kannan <vandana.kannan@intel.com> > > Cc: Jani Nikula <jani.nikula@linux.intel.com> Queued for -next, thanks for the patch. One thing that's missing though is the state readout and cross-check support for this new bit of crtc->config data. We need to add that before putting this to real use. -Daniel > > --- > > drivers/gpu/drm/i915/i915_drv.h | 5 ++ > > drivers/gpu/drm/i915/i915_reg.h | 1 + > > drivers/gpu/drm/i915/intel_dp.c | 110 +++++++++++++++++++++++++++++++++++++++ > > drivers/gpu/drm/i915/intel_drv.h | 6 ++- > > 4 files changed, 121 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > > index 55addaa..9da8d83 100644 > > --- a/drivers/gpu/drm/i915/i915_drv.h > > +++ b/drivers/gpu/drm/i915/i915_drv.h > > @@ -633,6 +633,10 @@ struct i915_fbc { > > } no_fbc_reason; > > }; > > > > +struct i915_drrs { > > + struct intel_connector *connector; > > +}; > > + > > struct i915_psr { > > bool sink_support; > > bool source_ok; > > @@ -1320,6 +1324,7 @@ struct drm_i915_private { > > struct timer_list hotplug_reenable_timer; > > > > struct i915_fbc fbc; > > + struct i915_drrs drrs; > > struct intel_opregion opregion; > > struct intel_vbt_data vbt; > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > > index 2315366..d6dddc2 100644 > > --- a/drivers/gpu/drm/i915/i915_reg.h > > +++ b/drivers/gpu/drm/i915/i915_reg.h > > @@ -3346,6 +3346,7 @@ enum punit_power_well { > > #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */ > > #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */ > > #define PIPECONF_INTERLACE_MODE_MASK (7 << 21) > > +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20) > > #define PIPECONF_CXSR_DOWNCLOCK (1<<16) > > #define PIPECONF_COLOR_RANGE_SELECT (1 << 13) > > #define PIPECONF_BPC_MASK (0x7 << 5) > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > > index 517a8cc..b50b170 100644 > > --- a/drivers/gpu/drm/i915/intel_dp.c > > +++ b/drivers/gpu/drm/i915/intel_dp.c > > @@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder, > > } > > } > > > > +static void > > +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n) > > +{ > > + struct drm_device *dev = crtc->base.dev; > > + struct drm_i915_private *dev_priv = dev->dev_private; > > + enum transcoder transcoder = crtc->config.cpu_transcoder; > > + > > + I915_WRITE(PIPE_DATA_M2(transcoder), > > + TU_SIZE(m_n->tu) | m_n->gmch_m); > > + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n); > > + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m); > > + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n); > > +} > > + > > bool > > intel_dp_compute_config(struct intel_encoder *encoder, > > struct intel_crtc_config *pipe_config) > > @@ -841,6 +855,14 @@ found: > > pipe_config->port_clock, > > &pipe_config->dp_m_n); > > > > + if (intel_connector->panel.downclock_mode != NULL && > > + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) { > > + intel_link_compute_m_n(bpp, lane_count, > > + intel_connector->panel.downclock_mode->clock, > > + pipe_config->port_clock, > > + &pipe_config->dp_m2_n2); > > + } > > + > > intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); > > > > return true; > > @@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, > > I915_READ(pp_div_reg)); > > } > > > > +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) > > +{ > > + struct drm_i915_private *dev_priv = dev->dev_private; > > + struct intel_encoder *encoder; > > + struct intel_dp *intel_dp = NULL; > > + struct intel_crtc_config *config = NULL; > > + struct intel_crtc *intel_crtc = NULL; > > + struct intel_connector *intel_connector = dev_priv->drrs.connector; > > + u32 reg, val; > > + enum edp_drrs_refresh_rate_type index = DRRS_HIGH_RR; > > + > > + if (refresh_rate <= 0) { > > + DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n"); > > + return; > > + } > > + > > + if (intel_connector == NULL) { > > + DRM_DEBUG_KMS("DRRS supported for eDP only.\n"); > > + return; > > + } > > + > > + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) { > > + DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n"); > > + return; > > + } > > + > > + encoder = intel_attached_encoder(&intel_connector->base); > > + intel_dp = enc_to_intel_dp(&encoder->base); > > + intel_crtc = encoder->new_crtc; > > + > > + if (!intel_crtc) { > > + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n"); > > + return; > > + } > > + > > + config = &intel_crtc->config; > > + > > + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) { > > + DRM_DEBUG_KMS("Only Seamless DRRS supported.\n"); > > + return; > > + } > > + > > + if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate) > > + index = DRRS_LOW_RR; > > + > > + if (index == intel_dp->drrs_state.refresh_rate_type) { > > + DRM_DEBUG_KMS( > > + "DRRS requested for previously set RR...ignoring\n"); > > + return; > > + } > > + > > + if (!intel_crtc->active) { > > + DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n"); > > + return; > > + } > > + > > + if (INTEL_INFO(dev)->gen > 6 && INTEL_INFO(dev)->gen < 8) { > > + reg = PIPECONF(intel_crtc->config.cpu_transcoder); > > + val = I915_READ(reg); > > + if (index > DRRS_HIGH_RR) { > > + val |= PIPECONF_EDP_RR_MODE_SWITCH; > > + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2); > > + } else { > > + val &= ~PIPECONF_EDP_RR_MODE_SWITCH; > > + } > > + I915_WRITE(reg, val); > > + } > > + > > + /* > > + * mutex taken to ensure that there is no race between differnt > > + * drrs calls trying to update refresh rate. This scenario may occur > > + * in future when idleness detection based DRRS in kernel and > > + * possible calls from user space to set differnt RR are made. > > + */ > > + > > + mutex_lock(&intel_dp->drrs_state.mutex); > > + > > + intel_dp->drrs_state.refresh_rate_type = index; > > + > > + mutex_unlock(&intel_dp->drrs_state.mutex); > > + > > + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate); > > +} > > + > > static struct drm_display_mode * > > intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, > > struct intel_connector *intel_connector, > > @@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, > > return NULL; > > } > > > > + dev_priv->drrs.connector = intel_connector; > > + > > + mutex_init(&intel_dp->drrs_state.mutex); > > + > > intel_dp->drrs_state.type = dev_priv->vbt.drrs_type; > > > > intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR; > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > > index 286d4fb..37d56e5 100644 > > --- a/drivers/gpu/drm/i915/intel_drv.h > > +++ b/drivers/gpu/drm/i915/intel_drv.h > > @@ -305,6 +305,9 @@ struct intel_crtc_config { > > int pipe_bpp; > > struct intel_link_m_n dp_m_n; > > > > + /* m2_n2 for eDP downclock */ > > + struct intel_link_m_n dp_m2_n2; > > + > > /* > > * Frequence the dpll for the port should run at. Differs from the > > * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also > > @@ -534,6 +537,7 @@ struct intel_dp { > > struct { > > enum drrs_support_type type; > > enum edp_drrs_refresh_rate_type refresh_rate_type; > > + struct mutex mutex; > > } drrs_state; > > > > }; > > @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp); > > void intel_edp_psr_enable(struct intel_dp *intel_dp); > > void intel_edp_psr_disable(struct intel_dp *intel_dp); > > void intel_edp_psr_update(struct drm_device *dev); > > - > > +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate); > > > > /* intel_dsi.c */ > > bool intel_dsi_init(struct drm_device *dev); > > -- > > 1.9.1 > > > > -- > Jani Nikula, Intel Open Source Technology Center > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Apr-10-2014 2:28 PM, Daniel Vetter wrote: > On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote: >> >> Reviewed-by: Jani Nikula <jani.nikula@intel.com> >> >> >> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote: >>> From: Pradeep Bhat <pradeep.bhat@intel.com> >>> >>> This patch computes and stored 2nd M/N/TU for switching to different >>> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle >>> between alternate refresh rates programmed in 2nd M/N/TU registers. >>> >>> v2: Daniel's review comments >>> Computing M2/N2 in compute_config and storing it in crtc_config >>> >>> v3: Modified reference to edp_downclock and edp_downclock_avail based on the >>> changes made to move them from dev_private to intel_panel. >>> >>> v4: Modified references to is_drrs_supported based on the changes made to >>> rename it to drrs_support. >>> >>> v5: Jani's review comments >>> Removed superfluous return statements. Changed support for Gen 7 and above. >>> Corrected indentation. Re-structured the code which finds crtc and connector >>> from encoder. Changed some logs to be less verbose. >>> >>> v6: Modifying i915_drrs to include only intel connector as intel_dp can be >>> derived from intel connector when required. >>> >>> v7: As per internal review comments, acquiring mutex just before accessing >>> drrs RR. As per Chris's review comments, added documentation about the use >>> of locking in the function. >>> >>> v8: Incorporated Jani's review comments. >>> Removed reference to edp_downclock. >>> >>> v9: Jani's review comments. Modified comment in set_drrs. Changed index to >>> type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting >>> registers fo DRRS. >>> >>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com> >>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com> >>> Cc: Jani Nikula <jani.nikula@linux.intel.com> > > Queued for -next, thanks for the patch. One thing that's missing though is > the state readout and cross-check support for this new bit of crtc->config > data. We need to add that before putting this to real use. > -Daniel > Hi Daniel, Could you please elaborate on your input above - on the missing code and cross-checking for support part? -Vandana >>> --- >>> drivers/gpu/drm/i915/i915_drv.h | 5 ++ >>> drivers/gpu/drm/i915/i915_reg.h | 1 + >>> drivers/gpu/drm/i915/intel_dp.c | 110 +++++++++++++++++++++++++++++++++++++++ >>> drivers/gpu/drm/i915/intel_drv.h | 6 ++- >>> 4 files changed, 121 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h >>> index 55addaa..9da8d83 100644 >>> --- a/drivers/gpu/drm/i915/i915_drv.h >>> +++ b/drivers/gpu/drm/i915/i915_drv.h >>> @@ -633,6 +633,10 @@ struct i915_fbc { >>> } no_fbc_reason; >>> }; >>> >>> +struct i915_drrs { >>> + struct intel_connector *connector; >>> +}; >>> + >>> struct i915_psr { >>> bool sink_support; >>> bool source_ok; >>> @@ -1320,6 +1324,7 @@ struct drm_i915_private { >>> struct timer_list hotplug_reenable_timer; >>> >>> struct i915_fbc fbc; >>> + struct i915_drrs drrs; >>> struct intel_opregion opregion; >>> struct intel_vbt_data vbt; >>> >>> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h >>> index 2315366..d6dddc2 100644 >>> --- a/drivers/gpu/drm/i915/i915_reg.h >>> +++ b/drivers/gpu/drm/i915/i915_reg.h >>> @@ -3346,6 +3346,7 @@ enum punit_power_well { >>> #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */ >>> #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */ >>> #define PIPECONF_INTERLACE_MODE_MASK (7 << 21) >>> +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20) >>> #define PIPECONF_CXSR_DOWNCLOCK (1<<16) >>> #define PIPECONF_COLOR_RANGE_SELECT (1 << 13) >>> #define PIPECONF_BPC_MASK (0x7 << 5) >>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c >>> index 517a8cc..b50b170 100644 >>> --- a/drivers/gpu/drm/i915/intel_dp.c >>> +++ b/drivers/gpu/drm/i915/intel_dp.c >>> @@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder, >>> } >>> } >>> >>> +static void >>> +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n) >>> +{ >>> + struct drm_device *dev = crtc->base.dev; >>> + struct drm_i915_private *dev_priv = dev->dev_private; >>> + enum transcoder transcoder = crtc->config.cpu_transcoder; >>> + >>> + I915_WRITE(PIPE_DATA_M2(transcoder), >>> + TU_SIZE(m_n->tu) | m_n->gmch_m); >>> + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n); >>> + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m); >>> + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n); >>> +} >>> + >>> bool >>> intel_dp_compute_config(struct intel_encoder *encoder, >>> struct intel_crtc_config *pipe_config) >>> @@ -841,6 +855,14 @@ found: >>> pipe_config->port_clock, >>> &pipe_config->dp_m_n); >>> >>> + if (intel_connector->panel.downclock_mode != NULL && >>> + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) { >>> + intel_link_compute_m_n(bpp, lane_count, >>> + intel_connector->panel.downclock_mode->clock, >>> + pipe_config->port_clock, >>> + &pipe_config->dp_m2_n2); >>> + } >>> + >>> intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); >>> >>> return true; >>> @@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, >>> I915_READ(pp_div_reg)); >>> } >>> >>> +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) >>> +{ >>> + struct drm_i915_private *dev_priv = dev->dev_private; >>> + struct intel_encoder *encoder; >>> + struct intel_dp *intel_dp = NULL; >>> + struct intel_crtc_config *config = NULL; >>> + struct intel_crtc *intel_crtc = NULL; >>> + struct intel_connector *intel_connector = dev_priv->drrs.connector; >>> + u32 reg, val; >>> + enum edp_drrs_refresh_rate_type index = DRRS_HIGH_RR; >>> + >>> + if (refresh_rate <= 0) { >>> + DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n"); >>> + return; >>> + } >>> + >>> + if (intel_connector == NULL) { >>> + DRM_DEBUG_KMS("DRRS supported for eDP only.\n"); >>> + return; >>> + } >>> + >>> + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) { >>> + DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n"); >>> + return; >>> + } >>> + >>> + encoder = intel_attached_encoder(&intel_connector->base); >>> + intel_dp = enc_to_intel_dp(&encoder->base); >>> + intel_crtc = encoder->new_crtc; >>> + >>> + if (!intel_crtc) { >>> + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n"); >>> + return; >>> + } >>> + >>> + config = &intel_crtc->config; >>> + >>> + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) { >>> + DRM_DEBUG_KMS("Only Seamless DRRS supported.\n"); >>> + return; >>> + } >>> + >>> + if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate) >>> + index = DRRS_LOW_RR; >>> + >>> + if (index == intel_dp->drrs_state.refresh_rate_type) { >>> + DRM_DEBUG_KMS( >>> + "DRRS requested for previously set RR...ignoring\n"); >>> + return; >>> + } >>> + >>> + if (!intel_crtc->active) { >>> + DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n"); >>> + return; >>> + } >>> + >>> + if (INTEL_INFO(dev)->gen > 6 && INTEL_INFO(dev)->gen < 8) { >>> + reg = PIPECONF(intel_crtc->config.cpu_transcoder); >>> + val = I915_READ(reg); >>> + if (index > DRRS_HIGH_RR) { >>> + val |= PIPECONF_EDP_RR_MODE_SWITCH; >>> + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2); >>> + } else { >>> + val &= ~PIPECONF_EDP_RR_MODE_SWITCH; >>> + } >>> + I915_WRITE(reg, val); >>> + } >>> + >>> + /* >>> + * mutex taken to ensure that there is no race between differnt >>> + * drrs calls trying to update refresh rate. This scenario may occur >>> + * in future when idleness detection based DRRS in kernel and >>> + * possible calls from user space to set differnt RR are made. >>> + */ >>> + >>> + mutex_lock(&intel_dp->drrs_state.mutex); >>> + >>> + intel_dp->drrs_state.refresh_rate_type = index; >>> + >>> + mutex_unlock(&intel_dp->drrs_state.mutex); >>> + >>> + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate); >>> +} >>> + >>> static struct drm_display_mode * >>> intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, >>> struct intel_connector *intel_connector, >>> @@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, >>> return NULL; >>> } >>> >>> + dev_priv->drrs.connector = intel_connector; >>> + >>> + mutex_init(&intel_dp->drrs_state.mutex); >>> + >>> intel_dp->drrs_state.type = dev_priv->vbt.drrs_type; >>> >>> intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR; >>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h >>> index 286d4fb..37d56e5 100644 >>> --- a/drivers/gpu/drm/i915/intel_drv.h >>> +++ b/drivers/gpu/drm/i915/intel_drv.h >>> @@ -305,6 +305,9 @@ struct intel_crtc_config { >>> int pipe_bpp; >>> struct intel_link_m_n dp_m_n; >>> >>> + /* m2_n2 for eDP downclock */ >>> + struct intel_link_m_n dp_m2_n2; >>> + >>> /* >>> * Frequence the dpll for the port should run at. Differs from the >>> * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also >>> @@ -534,6 +537,7 @@ struct intel_dp { >>> struct { >>> enum drrs_support_type type; >>> enum edp_drrs_refresh_rate_type refresh_rate_type; >>> + struct mutex mutex; >>> } drrs_state; >>> >>> }; >>> @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp); >>> void intel_edp_psr_enable(struct intel_dp *intel_dp); >>> void intel_edp_psr_disable(struct intel_dp *intel_dp); >>> void intel_edp_psr_update(struct drm_device *dev); >>> - >>> +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate); >>> >>> /* intel_dsi.c */ >>> bool intel_dsi_init(struct drm_device *dev); >>> -- >>> 1.9.1 >>> >> >> -- >> Jani Nikula, Intel Open Source Technology Center >> _______________________________________________ >> Intel-gfx mailing list >> Intel-gfx@lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx >
On Fri, Apr 11, 2014 at 02:48:53PM +0530, Vandana Kannan wrote: > On Apr-10-2014 2:28 PM, Daniel Vetter wrote: > > On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote: > >> > >> Reviewed-by: Jani Nikula <jani.nikula@intel.com> > >> > >> > >> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote: > >>> From: Pradeep Bhat <pradeep.bhat@intel.com> > >>> > >>> This patch computes and stored 2nd M/N/TU for switching to different > >>> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle > >>> between alternate refresh rates programmed in 2nd M/N/TU registers. > >>> > >>> v2: Daniel's review comments > >>> Computing M2/N2 in compute_config and storing it in crtc_config > >>> > >>> v3: Modified reference to edp_downclock and edp_downclock_avail based on the > >>> changes made to move them from dev_private to intel_panel. > >>> > >>> v4: Modified references to is_drrs_supported based on the changes made to > >>> rename it to drrs_support. > >>> > >>> v5: Jani's review comments > >>> Removed superfluous return statements. Changed support for Gen 7 and above. > >>> Corrected indentation. Re-structured the code which finds crtc and connector > >>> from encoder. Changed some logs to be less verbose. > >>> > >>> v6: Modifying i915_drrs to include only intel connector as intel_dp can be > >>> derived from intel connector when required. > >>> > >>> v7: As per internal review comments, acquiring mutex just before accessing > >>> drrs RR. As per Chris's review comments, added documentation about the use > >>> of locking in the function. > >>> > >>> v8: Incorporated Jani's review comments. > >>> Removed reference to edp_downclock. > >>> > >>> v9: Jani's review comments. Modified comment in set_drrs. Changed index to > >>> type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting > >>> registers fo DRRS. > >>> > >>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com> > >>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com> > >>> Cc: Jani Nikula <jani.nikula@linux.intel.com> > > > > Queued for -next, thanks for the patch. One thing that's missing though is > > the state readout and cross-check support for this new bit of crtc->config > > data. We need to add that before putting this to real use. > > -Daniel > > > Hi Daniel, > > Could you please elaborate on your input above - on the missing code and > cross-checking for support part? If you add new state to crtc->config then you need to add the relevan readout code for that state (see the code in check_crtc_state) and ofc also add it to intel_pipe_config_compare. This is a debug feature of our driver to make sure we never lose track of things and thus far has been extremely helpful in catching issues early. -Daniel
On Apr-11-2014 2:56 PM, Daniel Vetter wrote: > On Fri, Apr 11, 2014 at 02:48:53PM +0530, Vandana Kannan wrote: >> On Apr-10-2014 2:28 PM, Daniel Vetter wrote: >>> On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote: >>>> >>>> Reviewed-by: Jani Nikula <jani.nikula@intel.com> >>>> >>>> >>>> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote: >>>>> From: Pradeep Bhat <pradeep.bhat@intel.com> >>>>> >>>>> This patch computes and stored 2nd M/N/TU for switching to different >>>>> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle >>>>> between alternate refresh rates programmed in 2nd M/N/TU registers. >>>>> >>>>> v2: Daniel's review comments >>>>> Computing M2/N2 in compute_config and storing it in crtc_config >>>>> >>>>> v3: Modified reference to edp_downclock and edp_downclock_avail based on the >>>>> changes made to move them from dev_private to intel_panel. >>>>> >>>>> v4: Modified references to is_drrs_supported based on the changes made to >>>>> rename it to drrs_support. >>>>> >>>>> v5: Jani's review comments >>>>> Removed superfluous return statements. Changed support for Gen 7 and above. >>>>> Corrected indentation. Re-structured the code which finds crtc and connector >>>>> from encoder. Changed some logs to be less verbose. >>>>> >>>>> v6: Modifying i915_drrs to include only intel connector as intel_dp can be >>>>> derived from intel connector when required. >>>>> >>>>> v7: As per internal review comments, acquiring mutex just before accessing >>>>> drrs RR. As per Chris's review comments, added documentation about the use >>>>> of locking in the function. >>>>> >>>>> v8: Incorporated Jani's review comments. >>>>> Removed reference to edp_downclock. >>>>> >>>>> v9: Jani's review comments. Modified comment in set_drrs. Changed index to >>>>> type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting >>>>> registers fo DRRS. >>>>> >>>>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com> >>>>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com> >>>>> Cc: Jani Nikula <jani.nikula@linux.intel.com> >>> >>> Queued for -next, thanks for the patch. One thing that's missing though is >>> the state readout and cross-check support for this new bit of crtc->config >>> data. We need to add that before putting this to real use. >>> -Daniel >>> >> Hi Daniel, >> >> Could you please elaborate on your input above - on the missing code and >> cross-checking for support part? > > If you add new state to crtc->config then you need to add the relevan > readout code for that state (see the code in check_crtc_state) and ofc > also add it to intel_pipe_config_compare. > > This is a debug feature of our driver to make sure we never lose track of > things and thus far has been extremely helpful in catching issues early. > -Daniel > I have submitted a patch adding this piece of code. Please have a look.. http://lists.freedesktop.org/archives/intel-gfx/2014-April/043569.html - Vandana
On Apr-11-2014 4:51 PM, Vandana Kannan wrote: > On Apr-11-2014 2:56 PM, Daniel Vetter wrote: >> On Fri, Apr 11, 2014 at 02:48:53PM +0530, Vandana Kannan wrote: >>> On Apr-10-2014 2:28 PM, Daniel Vetter wrote: >>>> On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote: >>>>> >>>>> Reviewed-by: Jani Nikula <jani.nikula@intel.com> >>>>> >>>>> >>>>> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote: >>>>>> From: Pradeep Bhat <pradeep.bhat@intel.com> >>>>>> >>>>>> This patch computes and stored 2nd M/N/TU for switching to different >>>>>> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle >>>>>> between alternate refresh rates programmed in 2nd M/N/TU registers. >>>>>> >>>>>> v2: Daniel's review comments >>>>>> Computing M2/N2 in compute_config and storing it in crtc_config >>>>>> >>>>>> v3: Modified reference to edp_downclock and edp_downclock_avail based on the >>>>>> changes made to move them from dev_private to intel_panel. >>>>>> >>>>>> v4: Modified references to is_drrs_supported based on the changes made to >>>>>> rename it to drrs_support. >>>>>> >>>>>> v5: Jani's review comments >>>>>> Removed superfluous return statements. Changed support for Gen 7 and above. >>>>>> Corrected indentation. Re-structured the code which finds crtc and connector >>>>>> from encoder. Changed some logs to be less verbose. >>>>>> >>>>>> v6: Modifying i915_drrs to include only intel connector as intel_dp can be >>>>>> derived from intel connector when required. >>>>>> >>>>>> v7: As per internal review comments, acquiring mutex just before accessing >>>>>> drrs RR. As per Chris's review comments, added documentation about the use >>>>>> of locking in the function. >>>>>> >>>>>> v8: Incorporated Jani's review comments. >>>>>> Removed reference to edp_downclock. >>>>>> >>>>>> v9: Jani's review comments. Modified comment in set_drrs. Changed index to >>>>>> type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting >>>>>> registers fo DRRS. >>>>>> >>>>>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com> >>>>>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com> >>>>>> Cc: Jani Nikula <jani.nikula@linux.intel.com> >>>> >>>> Queued for -next, thanks for the patch. One thing that's missing though is >>>> the state readout and cross-check support for this new bit of crtc->config >>>> data. We need to add that before putting this to real use. >>>> -Daniel >>>> >>> Hi Daniel, >>> >>> Could you please elaborate on your input above - on the missing code and >>> cross-checking for support part? >> >> If you add new state to crtc->config then you need to add the relevan >> readout code for that state (see the code in check_crtc_state) and ofc >> also add it to intel_pipe_config_compare. >> >> This is a debug feature of our driver to make sure we never lose track of >> things and thus far has been extremely helpful in catching issues early. >> -Daniel >> > I have submitted a patch adding this piece of code. Please have a look.. > http://lists.freedesktop.org/archives/intel-gfx/2014-April/043569.html > > - Vandana > Hi Daniel, Please help review the patch http://lists.freedesktop.org/archives/intel-gfx/2014-April/043569.html which is based on your review comments above. -Vandana
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 55addaa..9da8d83 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -633,6 +633,10 @@ struct i915_fbc { } no_fbc_reason; }; +struct i915_drrs { + struct intel_connector *connector; +}; + struct i915_psr { bool sink_support; bool source_ok; @@ -1320,6 +1324,7 @@ struct drm_i915_private { struct timer_list hotplug_reenable_timer; struct i915_fbc fbc; + struct i915_drrs drrs; struct intel_opregion opregion; struct intel_vbt_data vbt; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2315366..d6dddc2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3346,6 +3346,7 @@ enum punit_power_well { #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */ #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */ #define PIPECONF_INTERLACE_MODE_MASK (7 << 21) +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20) #define PIPECONF_CXSR_DOWNCLOCK (1<<16) #define PIPECONF_COLOR_RANGE_SELECT (1 << 13) #define PIPECONF_BPC_MASK (0x7 << 5) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 517a8cc..b50b170 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder, } } +static void +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum transcoder transcoder = crtc->config.cpu_transcoder; + + I915_WRITE(PIPE_DATA_M2(transcoder), + TU_SIZE(m_n->tu) | m_n->gmch_m); + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n); + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m); + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n); +} + bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) @@ -841,6 +855,14 @@ found: pipe_config->port_clock, &pipe_config->dp_m_n); + if (intel_connector->panel.downclock_mode != NULL && + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) { + intel_link_compute_m_n(bpp, lane_count, + intel_connector->panel.downclock_mode->clock, + pipe_config->port_clock, + &pipe_config->dp_m2_n2); + } + intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); return true; @@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, I915_READ(pp_div_reg)); } +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_encoder *encoder; + struct intel_dp *intel_dp = NULL; + struct intel_crtc_config *config = NULL; + struct intel_crtc *intel_crtc = NULL; + struct intel_connector *intel_connector = dev_priv->drrs.connector; + u32 reg, val; + enum edp_drrs_refresh_rate_type index = DRRS_HIGH_RR; + + if (refresh_rate <= 0) { + DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n"); + return; + } + + if (intel_connector == NULL) { + DRM_DEBUG_KMS("DRRS supported for eDP only.\n"); + return; + } + + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) { + DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n"); + return; + } + + encoder = intel_attached_encoder(&intel_connector->base); + intel_dp = enc_to_intel_dp(&encoder->base); + intel_crtc = encoder->new_crtc; + + if (!intel_crtc) { + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n"); + return; + } + + config = &intel_crtc->config; + + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) { + DRM_DEBUG_KMS("Only Seamless DRRS supported.\n"); + return; + } + + if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate) + index = DRRS_LOW_RR; + + if (index == intel_dp->drrs_state.refresh_rate_type) { + DRM_DEBUG_KMS( + "DRRS requested for previously set RR...ignoring\n"); + return; + } + + if (!intel_crtc->active) { + DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n"); + return; + } + + if (INTEL_INFO(dev)->gen > 6 && INTEL_INFO(dev)->gen < 8) { + reg = PIPECONF(intel_crtc->config.cpu_transcoder); + val = I915_READ(reg); + if (index > DRRS_HIGH_RR) { + val |= PIPECONF_EDP_RR_MODE_SWITCH; + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2); + } else { + val &= ~PIPECONF_EDP_RR_MODE_SWITCH; + } + I915_WRITE(reg, val); + } + + /* + * mutex taken to ensure that there is no race between differnt + * drrs calls trying to update refresh rate. This scenario may occur + * in future when idleness detection based DRRS in kernel and + * possible calls from user space to set differnt RR are made. + */ + + mutex_lock(&intel_dp->drrs_state.mutex); + + intel_dp->drrs_state.refresh_rate_type = index; + + mutex_unlock(&intel_dp->drrs_state.mutex); + + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate); +} + static struct drm_display_mode * intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector, @@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, return NULL; } + dev_priv->drrs.connector = intel_connector; + + mutex_init(&intel_dp->drrs_state.mutex); + intel_dp->drrs_state.type = dev_priv->vbt.drrs_type; intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 286d4fb..37d56e5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -305,6 +305,9 @@ struct intel_crtc_config { int pipe_bpp; struct intel_link_m_n dp_m_n; + /* m2_n2 for eDP downclock */ + struct intel_link_m_n dp_m2_n2; + /* * Frequence the dpll for the port should run at. Differs from the * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also @@ -534,6 +537,7 @@ struct intel_dp { struct { enum drrs_support_type type; enum edp_drrs_refresh_rate_type refresh_rate_type; + struct mutex mutex; } drrs_state; }; @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp); void intel_edp_psr_enable(struct intel_dp *intel_dp); void intel_edp_psr_disable(struct intel_dp *intel_dp); void intel_edp_psr_update(struct drm_device *dev); - +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate); /* intel_dsi.c */ bool intel_dsi_init(struct drm_device *dev);