[Intel-gfx] [RFC 4/7] drm/i915: Program PPS registers
Vandana Kannan
vandana.kannan at intel.com
Mon Oct 20 14:50:06 CEST 2014
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 at intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 80 ++------------------------------------
drivers/gpu/drm/i915/intel_drv.h | 3 ++
drivers/gpu/drm/i915/intel_panel.c | 70 +++++++++++++++++++++++++++++++++
3 files changed, 76 insertions(+), 77 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a433c5f..ca11eb1 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;
@@ -281,11 +281,6 @@ intel_hrawclk(struct drm_device *dev)
}
}
-static void
-intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
- struct intel_dp *intel_dp,
- struct edp_power_seq *out);
-
static void pps_lock(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -4716,76 +4711,6 @@ static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
intel_dp->last_backlight_off = jiffies;
}
-static void
-intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
- struct intel_dp *intel_dp,
- struct edp_power_seq *seq)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_connector *intel_connector = intel_dp->attached_connector;
- struct intel_panel *panel = &intel_connector->panel;
- u32 pp_on, pp_off, pp_div, port_sel = 0;
- int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
- int pp_on_reg, pp_off_reg, pp_div_reg;
- enum port port = dp_to_dig_port(intel_dp)->port;
-
- lockdep_assert_held(&dev_priv->pps_mutex);
-
- if (HAS_PCH_SPLIT(dev)) {
- pp_on_reg = PCH_PP_ON_DELAYS;
- pp_off_reg = PCH_PP_OFF_DELAYS;
- pp_div_reg = PCH_PP_DIVISOR;
- } else {
- enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
-
- 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);
- }
-
- /*
- * 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);
-
- /* Haswell doesn't have any port selection bits for the panel
- * power sequencer any more. */
- if (IS_VALLEYVIEW(dev)) {
- port_sel = PANEL_PORT_SELECT_VLV(port);
- } else 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;
- }
-
- 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));
-}
-
void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4960,6 +4885,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;
@@ -4988,7 +4914,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_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
+ 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 597e09f..4ae913c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1001,6 +1001,7 @@ enum pipe vlv_power_sequencer_pipe(struct intel_dp *intel_dp);
void vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp);
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);
void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
@@ -1102,6 +1103,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_runtime_pm.c */
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 9b124ef..75172ab 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1346,6 +1346,76 @@ void intel_panel_init_backlight_funcs(struct drm_device *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 drm_encoder *encoder = connector->base.encoder;
+ struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+ struct intel_panel *panel = &connector->panel;
+ u32 pp_on, pp_off, pp_div, port_sel = 0;
+ int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
+ int pp_on_reg, pp_off_reg, pp_div_reg;
+
+ lockdep_assert_held(&dev_priv->pps_mutex);
+
+ if (HAS_PCH_SPLIT(dev)) {
+ pp_on_reg = PCH_PP_ON_DELAYS;
+ pp_off_reg = PCH_PP_OFF_DELAYS;
+ pp_div_reg = PCH_PP_DIVISOR;
+ } else {
+ enum pipe pipe = vlv_power_sequencer_pipe(&intel_dig_port->dp);
+
+ 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);
+ }
+
+ /*
+ * 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);
+
+ /* Haswell doesn't have any port selection bits for the panel
+ * power sequencer any more. */
+ if (IS_VALLEYVIEW(dev)) {
+ port_sel = PANEL_PORT_SELECT_VLV(port);
+ } else 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;
+ }
+
+ 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));
+}
+
static struct edp_power_seq pch_get_pps_registers(
struct intel_connector *connector,
u32 pp_ctrl_reg, u32 pp_on_reg,
--
2.0.1
More information about the Intel-gfx
mailing list