@@ -508,6 +508,9 @@ struct drm_i915_display_funcs {
uint32_t level);
void (*disable_backlight)(struct intel_connector *connector);
void (*enable_backlight)(struct intel_connector *connector);
+
+ struct edp_power_seq (*setup_panel_power_seq)
+ (struct intel_connector *connector);
};
struct intel_uncore_funcs {
@@ -12677,6 +12677,7 @@ static void intel_init_display(struct drm_device *dev)
}
intel_panel_init_backlight_funcs(dev);
+ intel_panel_init_pps_funcs(dev);
mutex_init(&dev_priv->pps_mutex);
}
@@ -409,14 +409,12 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
return INVALID_PIPE;
}
-static void
+void
vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_connector *intel_connector = intel_dp->attached_connector;
- struct edp_power_seq power_seq;
enum port port = intel_dig_port->port;
lockdep_assert_held(&dev_priv->pps_mutex);
@@ -444,9 +442,6 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n",
port_name(port), pipe_name(intel_dp->pps_pipe));
- intel_panel_setup_panel_power_sequencer(intel_connector);
- intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
- &power_seq);
}
void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
@@ -4991,8 +4986,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
/* We now know it's not a ghost, init power sequence regs. */
pps_lock(intel_dp);
- if (IS_VALLEYVIEW(dev))
- vlv_initial_power_sequencer_setup(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);
@@ -998,6 +998,7 @@ void intel_dp_mst_resume(struct drm_device *dev);
int intel_dp_max_link_bw(struct intel_dp *intel_dp);
void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
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);
/* intel_dp_mst.c */
@@ -1101,6 +1102,7 @@ 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_init_pps_funcs(struct drm_device *dev);
/* intel_runtime_pm.c */
int intel_power_domains_init(struct drm_i915_private *);
@@ -1346,43 +1346,27 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev)
}
}
-void
-intel_panel_setup_panel_power_sequencer(struct intel_connector *connector)
+static struct edp_power_seq pch_get_pps_registers(
+ struct intel_connector *connector,
+ u32 pp_ctrl_reg, u32 pp_on_reg,
+ u32 pp_off_reg, u32 pp_div_reg)
{
- struct intel_panel *panel = &connector->panel;
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 edp_power_seq cur, vbt, spec, final;
+ struct edp_power_seq cur;
u32 pp_on, pp_off, pp_div, pp;
- int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
-
- lockdep_assert_held(&dev_priv->pps_mutex);
- if (HAS_PCH_SPLIT(dev)) {
- pp_ctrl_reg = PCH_PP_CONTROL;
- 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_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
- 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);
- }
+ pp_on = I915_READ(pp_on_reg);
+ pp_off = I915_READ(pp_off_reg);
+ pp_div = I915_READ(pp_div_reg);
/* Workaround: Need to write PP_CONTROL with the unlock key as
* the very first thing. */
pp = ironlake_get_pp_control(&intel_dig_port->dp);
I915_WRITE(pp_ctrl_reg, pp);
- pp_on = I915_READ(pp_on_reg);
- pp_off = I915_READ(pp_off_reg);
- pp_div = I915_READ(pp_div_reg);
-
/* Pull timing values out of registers */
cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
PANEL_POWER_UP_DELAY_SHIFT;
@@ -1397,10 +1381,63 @@ intel_panel_setup_panel_power_sequencer(struct intel_connector *connector)
PANEL_POWER_DOWN_DELAY_SHIFT;
cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
- PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
+ PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
- cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
+ cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
+
+ return cur;
+}
+
+static struct edp_power_seq pch_setup_pps(struct intel_connector *connector)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
+
+ lockdep_assert_held(&dev_priv->pps_mutex);
+
+ pp_ctrl_reg = PCH_PP_CONTROL;
+ pp_on_reg = PCH_PP_ON_DELAYS;
+ pp_off_reg = PCH_PP_OFF_DELAYS;
+ pp_div_reg = PCH_PP_DIVISOR;
+
+ return pch_get_pps_registers(connector, pp_ctrl_reg, pp_on_reg,
+ pp_off_reg, pp_div_reg);
+}
+
+static struct edp_power_seq vlv_setup_pps(struct intel_connector *connector)
+{
+ 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 = vlv_power_sequencer_pipe(&intel_dig_port->dp);
+ int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
+
+ vlv_initial_power_sequencer_setup(&intel_dig_port->dp);
+
+ lockdep_assert_held(&dev_priv->pps_mutex);
+
+ pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
+ 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);
+
+ return pch_get_pps_registers(connector, pp_ctrl_reg, pp_on_reg,
+ pp_off_reg, pp_div_reg);
+}
+
+void
+intel_panel_setup_panel_power_sequencer(struct intel_connector *connector)
+{
+ struct intel_panel *panel = &connector->panel;
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct edp_power_seq cur, vbt, spec, final;
+
+ /* Get chip specific register values */
+ cur = dev_priv->display.setup_panel_power_seq(connector);
vbt = dev_priv->vbt.edp_pps;
@@ -1449,6 +1486,18 @@ intel_panel_setup_panel_power_sequencer(struct intel_connector *connector)
panel->pps.backlight_off_delay);
}
+/* 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))
+ dev_priv->display.setup_panel_power_seq = vlv_setup_pps;
+ else
+ dev_priv->display.setup_panel_power_seq = pch_setup_pps;
+}
+
+
int intel_panel_init(struct intel_panel *panel,
struct drm_display_mode *fixed_mode,
struct drm_display_mode *downclock_mode)
In the setup part, the differnce between vlv and other platforms is only w.r.t registers. Other parts like reading VBT are common. Removing calls to setup PPS and registers again through vlv_setup_panel_power sequencer (this would be redundant). Signed-off-by: Vandana Kannan <vandana.kannan@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 3 ++ drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/i915/intel_dp.c | 9 +--- drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_panel.c | 101 ++++++++++++++++++++++++++--------- 5 files changed, 82 insertions(+), 34 deletions(-)