diff options
author | Dave Airlie <airlied@redhat.com> | 2013-06-11 08:38:56 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-06-11 08:38:56 +1000 |
commit | e6dfcc5303d5d31cb36e36405acd766c8ed2c923 (patch) | |
tree | 986beb9aba4a62ea1449dde210005e82084e8c5e /drivers/gpu/drm/i915/intel_dp.c | |
parent | 9bc3cd5673d84d29272fa7181a4dfca83cbb48c1 (diff) | |
parent | 92d44621ad2d083bc03920c904ca0a5eb10d9ded (diff) |
Merge tag 'drm-intel-next-2013-06-01' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
Daniel writes:
Another round of drm-intel-next for 3.11. Highlights:
- Haswell IPS support (Paulo Zanoni)
- VECS support on Haswell (Ben Widawsky, Xiang Haihao, ...)
- Haswell watermark fixes (Paulo Zanoni)
- "Make the gun bigger again" multithread fence fix from Chris.
- i915_error_state finnally no longer fails with -ENOMEM! Big thanks to
Mika for tackling this.
- vlv sideband locking fixes from Jani
- Hangcheck prep work for arb_robustness support (Mika&Chris)
- edp vs cpu port confusion clean-up from Imre
- pile of smaller fixes and cleanups all over.
* tag 'drm-intel-next-2013-06-01' of git://people.freedesktop.org/~danvet/drm-intel: (70 commits)
drm/i915: add i915_ips_status debugfs entry
drm/i915: add enable_ips module option
drm/i915: implement IPS feature
drm/i915: fix up the edp power well check
drm/i915: add I915_PARAM_HAS_VEBOX to i915_getparam
drm/i915: add I915_EXEC_VEBOX to i915_gem_do_execbuffer()
drm/i915: add VEBOX into debugfs
drm/i915: Enable vebox interrupts
drm/i915: vebox interrupt get/put
drm/i915: consolidate interrupt naming scheme
drm/i915: Convert irq_refounct to struct
drm/i915: make PM interrupt writes non-destructive
drm/i915: Add PM regs to pre/post install
drm/i915: Create an ivybridge_irq_preinstall
drm/i915: Create a more generic pm handler for hsw+
drm/i915: add support for 5/6 data buffer partitioning on Haswell
drm/i915: properly set HSW WM_LP watermarks
drm/i915: properly set HSW WM_PIPE registers
drm/i915: fix pch_nop support
drm/i915: Vebox ringbuffer init
...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 145 |
1 files changed, 77 insertions, 68 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bfc8664be8d..91a31b3b982 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -59,22 +59,6 @@ static struct drm_device *intel_dp_to_dev(struct intel_dp *intel_dp) return intel_dig_port->base.base.dev; } -/** - * is_cpu_edp - is the port on the CPU and attached to an eDP panel? - * @intel_dp: DP struct - * - * Returns true if the given DP struct corresponds to a CPU eDP port. - */ -static bool is_cpu_edp(struct intel_dp *intel_dp) -{ - struct drm_device *dev = intel_dp_to_dev(intel_dp); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - enum port port = intel_dig_port->port; - - return is_edp(intel_dp) && - (port == PORT_A || (port == PORT_C && IS_VALLEYVIEW(dev))); -} - static struct intel_dp *intel_attached_dp(struct drm_connector *connector) { return enc_to_intel_dp(&intel_attached_encoder(connector)->base); @@ -317,11 +301,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, * Note that PCH attached eDP panels should use a 125MHz input * clock divider. */ - if (is_cpu_edp(intel_dp)) { + if (IS_VALLEYVIEW(dev)) { + aux_clock_divider = 100; + } else if (intel_dig_port->port == PORT_A) { if (HAS_DDI(dev)) - aux_clock_divider = intel_ddi_get_cdclk_freq(dev_priv) >> 1; - else if (IS_VALLEYVIEW(dev)) - aux_clock_divider = 100; + aux_clock_divider = DIV_ROUND_CLOSEST( + intel_ddi_get_cdclk_freq(dev_priv), 2000); else if (IS_GEN6(dev) || IS_GEN7(dev)) aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */ else @@ -684,6 +669,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + enum port port = dp_to_dig_port(intel_dp)->port; struct intel_crtc *intel_crtc = encoder->new_crtc; struct intel_connector *intel_connector = intel_dp->attached_connector; int lane_count, clock; @@ -693,7 +679,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; int target_clock, link_avail, link_clock; - if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && !is_cpu_edp(intel_dp)) + if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A) pipe_config->has_pch_encoder = true; pipe_config->has_dp_encoder = true; @@ -827,6 +813,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + enum port port = dp_to_dig_port(intel_dp)->port; struct drm_crtc *crtc = encoder->crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -867,7 +854,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, /* Split out the IBX/CPU vs CPT settings */ - if (is_cpu_edp(intel_dp) && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) { + if (port == PORT_A && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) { if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) intel_dp->DP |= DP_SYNC_HS_HIGH; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) @@ -884,7 +871,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, intel_dp->DP |= DP_PLL_FREQ_160MHZ; else intel_dp->DP |= DP_PLL_FREQ_270MHZ; - } else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) { + } else if (!HAS_PCH_CPT(dev) || port == PORT_A) { if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev)) intel_dp->DP |= intel_dp->color_range; @@ -900,7 +887,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, if (intel_crtc->pipe == 1) intel_dp->DP |= DP_PIPEB_SELECT; - if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { + if (port == PORT_A && !IS_VALLEYVIEW(dev)) { /* don't miss out required setting for eDP */ if (adjusted_mode->clock < 200000) intel_dp->DP |= DP_PLL_FREQ_160MHZ; @@ -911,7 +898,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; } - if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) + if (port == PORT_A && !IS_VALLEYVIEW(dev)) ironlake_set_pll_edp(crtc, adjusted_mode->clock); } @@ -1301,6 +1288,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + enum port port = dp_to_dig_port(intel_dp)->port; struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 tmp = I915_READ(intel_dp->output_reg); @@ -1308,9 +1296,9 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, if (!(tmp & DP_PORT_EN)) return false; - if (is_cpu_edp(intel_dp) && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) { + if (port == PORT_A && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) { *pipe = PORT_TO_PIPE_CPT(tmp); - } else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) { + } else if (!HAS_PCH_CPT(dev) || port == PORT_A) { *pipe = PORT_TO_PIPE(tmp); } else { u32 trans_sel; @@ -1346,9 +1334,33 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, return true; } +static void intel_dp_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + u32 tmp, flags = 0; + + tmp = I915_READ(intel_dp->output_reg); + + if (tmp & DP_SYNC_HS_HIGH) + flags |= DRM_MODE_FLAG_PHSYNC; + else + flags |= DRM_MODE_FLAG_NHSYNC; + + if (tmp & DP_SYNC_VS_HIGH) + flags |= DRM_MODE_FLAG_PVSYNC; + else + flags |= DRM_MODE_FLAG_NVSYNC; + + pipe_config->adjusted_mode.flags |= flags; +} + static void intel_disable_dp(struct intel_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + enum port port = dp_to_dig_port(intel_dp)->port; + struct drm_device *dev = encoder->base.dev; /* Make sure the panel is off before trying to change the mode. But also * ensure that we have vdd while we switch off the panel. */ @@ -1358,16 +1370,17 @@ static void intel_disable_dp(struct intel_encoder *encoder) ironlake_edp_panel_off(intel_dp); /* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */ - if (!is_cpu_edp(intel_dp)) + if (!(port == PORT_A || IS_VALLEYVIEW(dev))) intel_dp_link_down(intel_dp); } static void intel_post_disable_dp(struct intel_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + enum port port = dp_to_dig_port(intel_dp)->port; struct drm_device *dev = encoder->base.dev; - if (is_cpu_edp(intel_dp)) { + if (port == PORT_A || IS_VALLEYVIEW(dev)) { intel_dp_link_down(intel_dp); if (!IS_VALLEYVIEW(dev)) ironlake_edp_pll_off(intel_dp); @@ -1405,34 +1418,32 @@ static void intel_enable_dp(struct intel_encoder *encoder) static void intel_pre_enable_dp(struct intel_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + struct intel_digital_port *dport = dp_to_dig_port(intel_dp); struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) + if (dport->port == PORT_A && !IS_VALLEYVIEW(dev)) ironlake_edp_pll_on(intel_dp); if (IS_VALLEYVIEW(dev)) { - struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); int port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; u32 val; - WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); - - val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(port)); + val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port)); val = 0; if (pipe) val |= (1<<21); else val &= ~(1<<21); val |= 0x001000c4; - intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val); + vlv_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val); - intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port), + vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port), 0x00760018); - intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port), + vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port), 0x00400888); } } @@ -1447,22 +1458,20 @@ static void intel_dp_pre_pll_enable(struct intel_encoder *encoder) if (!IS_VALLEYVIEW(dev)) return; - WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); - /* Program Tx lane resets to default */ - intel_dpio_write(dev_priv, DPIO_PCS_TX(port), + vlv_dpio_write(dev_priv, DPIO_PCS_TX(port), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - intel_dpio_write(dev_priv, DPIO_PCS_CLK(port), + vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ - intel_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00); - intel_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500); - intel_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000); + vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00); + vlv_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500); + vlv_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000); } /* @@ -1524,12 +1533,13 @@ static uint8_t intel_dp_voltage_max(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); + enum port port = dp_to_dig_port(intel_dp)->port; if (IS_VALLEYVIEW(dev)) return DP_TRAIN_VOLTAGE_SWING_1200; - else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) + else if (IS_GEN7(dev) && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_800; - else if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + else if (HAS_PCH_CPT(dev) && port != PORT_A) return DP_TRAIN_VOLTAGE_SWING_1200; else return DP_TRAIN_VOLTAGE_SWING_800; @@ -1539,6 +1549,7 @@ static uint8_t intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) { struct drm_device *dev = intel_dp_to_dev(intel_dp); + enum port port = dp_to_dig_port(intel_dp)->port; if (HAS_DDI(dev)) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { @@ -1564,7 +1575,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) default: return DP_TRAIN_PRE_EMPHASIS_0; } - } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { + } else if (IS_GEN7(dev) && port == PORT_A) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { case DP_TRAIN_VOLTAGE_SWING_400: return DP_TRAIN_PRE_EMPHASIS_6; @@ -1599,8 +1610,6 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) uint8_t train_set = intel_dp->train_set[0]; int port = vlv_dport_to_channel(dport); - WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); - switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { case DP_TRAIN_PRE_EMPHASIS_0: preemph_reg_value = 0x0004000; @@ -1674,14 +1683,14 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) return 0; } - intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x00000000); - intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port), demph_reg_value); - intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port), + vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x00000000); + vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port), demph_reg_value); + vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port), uniqtranscale_reg_value); - intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port), 0x0C782040); - intel_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000); - intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), preemph_reg_value); - intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x80000000); + vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port), 0x0C782040); + vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000); + vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), preemph_reg_value); + vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x80000000); return 0; } @@ -1853,6 +1862,7 @@ static void intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + enum port port = intel_dig_port->port; struct drm_device *dev = intel_dig_port->base.base.dev; uint32_t signal_levels, mask; uint8_t train_set = intel_dp->train_set[0]; @@ -1863,10 +1873,10 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) } else if (IS_VALLEYVIEW(dev)) { signal_levels = intel_vlv_signal_levels(intel_dp); mask = 0; - } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { + } else if (IS_GEN7(dev) && port == PORT_A) { signal_levels = intel_gen7_edp_signal_levels(train_set); mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; - } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { + } else if (IS_GEN6(dev) && port == PORT_A) { signal_levels = intel_gen6_edp_signal_levels(train_set); mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB; } else { @@ -1916,8 +1926,7 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, } I915_WRITE(DP_TP_CTL(port), temp); - } else if (HAS_PCH_CPT(dev) && - (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) { + } else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) { dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT; switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { @@ -2168,6 +2177,7 @@ static void intel_dp_link_down(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + enum port port = intel_dig_port->port; struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = @@ -2197,7 +2207,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) DRM_DEBUG_KMS("\n"); - if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) { + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) { DP &= ~DP_LINK_TRAIN_MASK_CPT; I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); } else { @@ -2488,11 +2498,10 @@ intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) return NULL; size = (intel_connector->edid->extensions + 1) * EDID_LENGTH; - edid = kmalloc(size, GFP_KERNEL); + edid = kmemdup(intel_connector->edid, size, GFP_KERNEL); if (!edid) return NULL; - memcpy(edid, intel_connector->edid, size); return edid; } @@ -2925,9 +2934,6 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, pp_div_reg = PIPEA_PP_DIVISOR; } - if (IS_VALLEYVIEW(dev)) - port_sel = I915_READ(pp_on_reg) & 0xc0000000; - /* And finally store the new values in the power sequencer. */ pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT); @@ -2941,8 +2947,10 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, /* Haswell doesn't have any port selection bits for the panel * power sequencer any more. */ - if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { - if (is_cpu_edp(intel_dp)) + if (IS_VALLEYVIEW(dev)) { + port_sel = I915_READ(pp_on_reg) & 0xc0000000; + } else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { + if (dp_to_dig_port(intel_dp)->port == PORT_A) port_sel = PANEL_POWER_PORT_DP_A; else port_sel = PANEL_POWER_PORT_DP_D; @@ -3184,6 +3192,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) intel_encoder->disable = intel_disable_dp; intel_encoder->post_disable = intel_post_disable_dp; intel_encoder->get_hw_state = intel_dp_get_hw_state; + intel_encoder->get_config = intel_dp_get_config; if (IS_VALLEYVIEW(dev)) intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable; |