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@xxxxxxxxx> >> >> >> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@xxxxxxxxx> wrote: >>> From: Pradeep Bhat <pradeep.bhat@xxxxxxxxx> >>> >>> 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@xxxxxxxxx> >>> Signed-off-by: Vandana Kannan <vandana.kannan@xxxxxxxxx> >>> Cc: Jani Nikula <jani.nikula@xxxxxxxxxxxxxxx> > > 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@xxxxxxxxxxxxxxxxxxxxx >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx > _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx