Modifying PPS functions in intel_dp.c to avoid using too many conditional statements based on platform. Calling vlv_initial_power_sequencer_setup() from vlv specific pps functions to just initialize vlv specific data and continue with the rest of the generic code.
Signed-off-by: Vandana Kannan <vandana.kan...@intel.com> --- drivers/gpu/drm/i915/intel_dp.c | 215 ++++++++++++++++++++++++++------------- drivers/gpu/drm/i915/intel_drv.h | 3 + 2 files changed, 146 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1d4bf78..1c6b4b3 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -520,8 +520,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_dp_init_panel_power_sequencer(dev, intel_dp); - intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); } void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv) @@ -4714,6 +4712,7 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp) static void intel_dp_encoder_reset(struct drm_encoder *encoder) { + struct drm_device *dev = encoder->dev; struct intel_dp *intel_dp; if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP) @@ -4727,8 +4726,10 @@ static void intel_dp_encoder_reset(struct drm_encoder *encoder) * Read out the current power sequencer assignment, * in case the BIOS did something with it. */ - if (IS_VALLEYVIEW(encoder->dev)) - vlv_initial_power_sequencer_setup(intel_dp); + if (IS_VALLEYVIEW(dev)) { + intel_dp_init_panel_power_sequencer(dev, intel_dp); + intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); + } intel_edp_panel_vdd_sanitize(intel_dp); @@ -4917,45 +4918,26 @@ 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(struct drm_device *dev, - struct intel_dp *intel_dp) +static struct edp_power_seq pch_get_pps_registers( + struct intel_dp *intel_dp, + u32 pp_ctrl_reg, u32 pp_on_reg, + u32 pp_off_reg, u32 pp_div_reg) { + 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 edp_power_seq cur, vbt, spec, - *final = &intel_dp->pps_delays; 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); + struct edp_power_seq cur; - /* already initialized? */ - if (final->t11_t12 != 0) - return; - - 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_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_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; @@ -4970,10 +4952,61 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, 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_dp *intel_dp) +{ + int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; + + 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(intel_dp, pp_ctrl_reg, pp_on_reg, + pp_off_reg, pp_div_reg); +} + +static struct edp_power_seq vlv_setup_pps(struct intel_dp *intel_dp) +{ + enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); + int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; + + vlv_initial_power_sequencer_setup(intel_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); + + return pch_get_pps_registers(intel_dp, pp_ctrl_reg, pp_on_reg, + pp_off_reg, pp_div_reg); +} + +static void +intel_dp_init_panel_power_sequencer(struct drm_device *dev, + struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct edp_power_seq cur = { 0, 0, 0, 0, 0 }, vbt, spec, + *final = &intel_dp->pps_delays; + + lockdep_assert_held(&dev_priv->pps_mutex); + + /* already initialized? */ + if (final->t11_t12 != 0) + return; + + /* Get chip specific register values */ + if (intel_dp->setup_panel_power_seq) + cur = intel_dp->setup_panel_power_seq(intel_dp); vbt = dev_priv->vbt.edp_pps; @@ -5020,30 +5053,16 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); } -static void -intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, - struct intel_dp *intel_dp) +static void pch_actually_set_pps_registers( + struct intel_dp *intel_dp, + int pp_on_reg, int pp_off_reg, int pp_div_reg, + int port_sel, int div) { + 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; - 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; const struct edp_power_seq *seq = &intel_dp->pps_delays; - - 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); - } + u32 pp_on, pp_off, pp_div; /* * And finally store the new values in the power sequencer. The @@ -5056,24 +5075,13 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | (1 << PANEL_LIGHT_ON_DELAY_SHIFT); pp_off = (1 << PANEL_LIGHT_OFF_DELAY_SHIFT) | - (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); + (seq->t10 << 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(seq->t11_t12, 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); @@ -5084,6 +5092,64 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, I915_READ(pp_on_reg), I915_READ(pp_off_reg), I915_READ(pp_div_reg)); + +} + +static void vlv_set_pps_registers(struct intel_dp *intel_dp, + enum port port) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + int pp_on_reg, pp_off_reg, pp_div_reg, port_sel = 0, div; + enum pipe pipe = PIPE_A; + + 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); + + port_sel = PANEL_PORT_SELECT_VLV(port); + div = intel_hrawclk(dev); + + pch_actually_set_pps_registers(intel_dp, pp_on_reg, pp_off_reg, + pp_div_reg, port_sel, div); +} + +static void pch_set_pps_registers(struct intel_dp *intel_dp, + enum port port) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + int pp_on_reg, pp_off_reg, pp_div_reg, port_sel = 0, div; + + 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); + + pch_actually_set_pps_registers(intel_dp, pp_on_reg, pp_off_reg, + pp_div_reg, port_sel, div); +} + +static void +intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, + struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + enum port port = dp_to_dig_port(intel_dp)->port; + + lockdep_assert_held(&dev_priv->pps_mutex); + + if (intel_dp->set_pps_registers) + intel_dp->set_pps_registers(intel_dp, port); } void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) @@ -5234,6 +5300,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, if (!is_edp(intel_dp)) return true; + if (IS_VALLEYVIEW(dev)) { + intel_dp->setup_panel_power_seq = vlv_setup_pps; + intel_dp->set_pps_registers = vlv_set_pps_registers; + } else { + intel_dp->setup_panel_power_seq = pch_setup_pps; + intel_dp->set_pps_registers = pch_set_pps_registers; + } + pps_lock(intel_dp); intel_edp_panel_vdd_sanitize(intel_dp); pps_unlock(intel_dp); @@ -5255,10 +5329,7 @@ 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); intel_dp_init_panel_power_timestamps(intel_dp); - if (IS_VALLEYVIEW(dev)) - vlv_initial_power_sequencer_setup(intel_dp); - else - intel_dp_init_panel_power_sequencer(dev, intel_dp); + intel_dp_init_panel_power_sequencer(dev, intel_dp); intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); pps_unlock(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5c622ad..345bcbc 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -629,6 +629,9 @@ struct intel_dp { struct mutex mutex; } drrs_state; + struct edp_power_seq (*setup_panel_power_seq) + (struct intel_dp *intel_dp); + void (*set_pps_registers)(struct intel_dp *intel_dp, enum port port); }; struct intel_digital_port { -- 2.0.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx