Actually set values into PPS related registers. This implementation is equivalent to intel_dp_panel_power_sequencer_registers where the values saved intially are written into registers. Signed-off-by: Vandana Kannan <vandana.kannan@xxxxxxxxx> --- drivers/gpu/drm/i915/intel_dp.c | 4 +- drivers/gpu/drm/i915/intel_drv.h | 3 ++ drivers/gpu/drm/i915/intel_panel.c | 102 ++++++++++++++++++++++++++++++++++++- 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 861b634..a40d494 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -248,7 +248,7 @@ unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) } /* hrawclock is 1/4 the FSB frequency */ -static int +int intel_hrawclk(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5005,6 +5005,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, bool has_dpcd; struct drm_display_mode *scan; struct edid *edid; + enum port port = intel_dig_port->port; intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED; @@ -5032,6 +5033,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, pps_lock(intel_dp); intel_dp_init_panel_power_timestamps(intel_dp); intel_panel_setup_panel_power_sequencer(intel_connector); + intel_panel_set_pps_registers(intel_connector, port); pps_unlock(intel_dp); mutex_lock(&dev->mode_config.mutex); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8f4332e..687d581 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -994,6 +994,7 @@ void vlv_initial_power_sequencer_setup( struct intel_digital_port *intel_dig_port); void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv); u32 ironlake_get_pp_control(struct intel_dp *intel_dp); +int intel_hrawclk(struct drm_device *dev); /* intel_dp_mst.c */ int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); @@ -1096,6 +1097,8 @@ extern struct drm_display_mode *intel_find_panel_downclock( struct drm_connector *connector); void intel_panel_setup_panel_power_sequencer( struct intel_connector *connector); +void intel_panel_set_pps_registers(struct intel_connector *connector, + enum port port); void intel_panel_init_pps_funcs(struct drm_device *dev); /* intel_pm.c */ diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index cfb6e9d..9f7cb7a 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1486,15 +1486,113 @@ void intel_panel_setup_panel_power_sequencer(struct intel_connector *connector) } +static void vlv_set_pps_registers(struct intel_connector *connector, + enum port port, int *pp_ctrl_reg, + int *pp_on_reg, int *pp_off_reg, + int *pp_div_reg, int *port_sel, int *div) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_encoder *encoder = connector->base.encoder; + struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + enum pipe pipe = PIPE_A; + + pipe = vlv_power_sequencer_pipe(&intel_dig_port->dp); + + lockdep_assert_held(&dev_priv->pps_mutex); + + *pp_ctrl_reg = 0; + *pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); + *pp_off_reg = VLV_PIPE_PP_OFF_DELAYS(pipe); + *pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe); + + *port_sel = PANEL_PORT_SELECT_VLV(port); + *div = intel_hrawclk(dev); +} + +static void pch_set_pps_registers(struct intel_connector *connector, + enum port port, int *pp_ctrl_reg, + int *pp_on_reg, int *pp_off_reg, + int *pp_div_reg, int *port_sel, int *div) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + lockdep_assert_held(&dev_priv->pps_mutex); + + *pp_ctrl_reg = 0; + *pp_on_reg = PCH_PP_ON_DELAYS; + *pp_off_reg = PCH_PP_OFF_DELAYS; + *pp_div_reg = PCH_PP_DIVISOR; + + if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { + if (port == PORT_A) + *port_sel = PANEL_PORT_SELECT_DPA; + else + *port_sel = PANEL_PORT_SELECT_DPD; + } + *div = intel_pch_rawclk(dev); +} + +void intel_panel_set_pps_registers(struct intel_connector *connector, + enum port port) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; + u32 pp_on, pp_off, pp_div; + u32 port_sel = 0, div; + + dev_priv->display.set_pps_registers(connector, port, &pp_ctrl_reg, + &pp_on_reg, &pp_off_reg, &pp_div_reg, + &port_sel, &div); + + /* + * And finally store the new values in the power sequencer. The + * backlight delays are set to 1 because we do manual waits on them. For + * T8, even BSpec recommends doing it. For T9, if we don't do this, + * we'll end up waiting for the backlight off delay twice: once when we + * do the manual sleep, and once when we disable the panel and wait for + * the PP_STATUS bit to become zero. + */ + pp_on = (panel->pps.panel_power_up_delay << + PANEL_POWER_UP_DELAY_SHIFT) | + (1 << PANEL_LIGHT_ON_DELAY_SHIFT); + pp_off = (1 << PANEL_LIGHT_OFF_DELAY_SHIFT) | + (panel->pps.panel_power_down_delay << + PANEL_POWER_DOWN_DELAY_SHIFT); + /* Compute the divisor for the pp clock, simply match the Bspec + * formula. */ + pp_div = ((100 * div)/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT; + pp_div |= (DIV_ROUND_UP(panel->pps.panel_power_cycle_delay, 1000) + << PANEL_POWER_CYCLE_DELAY_SHIFT); + + pp_on |= port_sel; + + I915_WRITE(pp_on_reg, pp_on); + I915_WRITE(pp_off_reg, pp_off); + I915_WRITE(pp_div_reg, pp_div); + + DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", + I915_READ(pp_on_reg), + I915_READ(pp_off_reg), + I915_READ(pp_div_reg)); + +} + /* Setup chip specific PPS functions */ void intel_panel_init_pps_funcs(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev)) { dev_priv->display.setup_panel_power_seq = vlv_setup_pps; - else + dev_priv->display.set_pps_registers = vlv_set_pps_registers; + } else { dev_priv->display.setup_panel_power_seq = pch_setup_pps; + dev_priv->display.set_pps_registers = pch_set_pps_registers; + } } int intel_panel_init(struct intel_panel *panel, -- 2.0.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx