diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_dp.c | 1660 |
1 files changed, 154 insertions, 1506 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 775d89b6c3fc..a560468765c0 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -39,6 +39,7 @@ #include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> +#include "g4x_dp.h" #include "i915_debugfs.h" #include "i915_drv.h" #include "intel_atomic.h" @@ -50,6 +51,7 @@ #include "intel_dp_aux.h" #include "intel_dp_link_training.h" #include "intel_dp_mst.h" +#include "intel_dpll.h" #include "intel_dpio_phy.h" #include "intel_fifo_underrun.h" #include "intel_hdcp.h" @@ -81,52 +83,6 @@ #define INTEL_DP_RESOLUTION_STANDARD (2 << INTEL_DP_RESOLUTION_SHIFT_MASK) #define INTEL_DP_RESOLUTION_FAILSAFE (3 << INTEL_DP_RESOLUTION_SHIFT_MASK) -struct dp_link_dpll { - int clock; - struct dpll dpll; -}; - -static const struct dp_link_dpll g4x_dpll[] = { - { 162000, - { .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } }, - { 270000, - { .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } } -}; - -static const struct dp_link_dpll pch_dpll[] = { - { 162000, - { .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } }, - { 270000, - { .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } } -}; - -static const struct dp_link_dpll vlv_dpll[] = { - { 162000, - { .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } }, - { 270000, - { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } } -}; - -/* - * CHV supports eDP 1.4 that have more link rates. - * Below only provides the fixed rate but exclude variable rate. - */ -static const struct dp_link_dpll chv_dpll[] = { - /* - * CHV requires to program fractional division for m2. - * m2 is stored in fixed point format using formula below - * (m2_int << 22) | m2_fraction - */ - { 162000, /* m2_int = 32, m2_fraction = 1677722 */ - { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } }, - { 270000, /* m2_int = 27, m2_fraction = 0 */ - { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }, -}; - -const struct dpll *vlv_get_dpll(struct drm_i915_private *i915) -{ - return IS_CHERRYVIEW(i915) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll; -} /* Constants for DP DSC configurations */ static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15}; @@ -150,8 +106,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp) return dig_port->base.type == INTEL_OUTPUT_EDP; } -static void intel_dp_link_down(struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state); static void intel_dp_unset_edid(struct intel_dp *intel_dp); /* update sink rates from dpcd */ @@ -260,8 +214,8 @@ bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp) struct intel_encoder *encoder = &intel_dig_port->base; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - return INTEL_GEN(dev_priv) >= 12 || - (INTEL_GEN(dev_priv) == 11 && + return DISPLAY_VER(dev_priv) >= 12 || + (IS_DISPLAY_VER(dev_priv, 11) && encoder->port != PORT_A); } @@ -338,10 +292,10 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) drm_WARN_ON(&dev_priv->drm, intel_dp->source_rates || intel_dp->num_source_rates); - if (INTEL_GEN(dev_priv) >= 10) { + if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) { source_rates = cnl_rates; size = ARRAY_SIZE(cnl_rates); - if (IS_GEN(dev_priv, 10)) + if (IS_DISPLAY_VER(dev_priv, 10)) max_rate = cnl_max_source_rate(intel_dp); else if (IS_JSL_EHL(dev_priv)) max_rate = ehl_max_source_rate(intel_dp); @@ -529,7 +483,7 @@ u32 intel_dp_mode_to_fec_clock(u32 mode_clock) static int small_joiner_ram_size_bits(struct drm_i915_private *i915) { - if (INTEL_GEN(i915) >= 11) + if (DISPLAY_VER(i915) >= 11) return 7680 * 8; else return 6144 * 8; @@ -788,10 +742,10 @@ intel_dp_mode_valid(struct drm_connector *connector, return MODE_H_ILLEGAL; if (intel_dp_is_edp(intel_dp) && fixed_mode) { - if (mode->hdisplay > fixed_mode->hdisplay) + if (mode->hdisplay != fixed_mode->hdisplay) return MODE_PANEL; - if (mode->vdisplay > fixed_mode->vdisplay) + if (mode->vdisplay != fixed_mode->vdisplay) return MODE_PANEL; target_clock = fixed_mode->clock; @@ -822,7 +776,7 @@ intel_dp_mode_valid(struct drm_connector *connector, * Output bpp is stored in 6.4 format so right shift by 4 to get the * integer value since we support only integer values of bpp. */ - if ((INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) && + if (DISPLAY_VER(dev_priv) >= 10 && drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) { if (intel_dp_is_edp(intel_dp)) { dsc_max_output_bpp = @@ -877,39 +831,6 @@ bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp) return max_rate >= 810000; } -static void -intel_dp_set_clock(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - const struct dp_link_dpll *divisor = NULL; - int i, count = 0; - - if (IS_G4X(dev_priv)) { - divisor = g4x_dpll; - count = ARRAY_SIZE(g4x_dpll); - } else if (HAS_PCH_SPLIT(dev_priv)) { - divisor = pch_dpll; - count = ARRAY_SIZE(pch_dpll); - } else if (IS_CHERRYVIEW(dev_priv)) { - divisor = chv_dpll; - count = ARRAY_SIZE(chv_dpll); - } else if (IS_VALLEYVIEW(dev_priv)) { - divisor = vlv_dpll; - count = ARRAY_SIZE(vlv_dpll); - } - - if (divisor && count) { - for (i = 0; i < count; i++) { - if (pipe_config->port_clock == divisor[i].clock) { - pipe_config->dpll = divisor[i].dpll; - pipe_config->clock_set = true; - break; - } - } - } -} - static void snprintf_int_array(char *str, size_t len, const int *array, int nelem) { @@ -992,10 +913,10 @@ static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); /* On TGL, FEC is supported on all Pipes */ - if (INTEL_GEN(dev_priv) >= 12) + if (DISPLAY_VER(dev_priv) >= 12) return true; - if (IS_GEN(dev_priv, 11) && pipe_config->cpu_transcoder != TRANSCODER_A) + if (IS_DISPLAY_VER(dev_priv, 11) && pipe_config->cpu_transcoder != TRANSCODER_A) return true; return false; @@ -1314,7 +1235,7 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, return -EINVAL; /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */ - if (INTEL_GEN(dev_priv) >= 12) + if (DISPLAY_VER(dev_priv) >= 12) dsc_max_bpc = min_t(u8, 12, conn_state->max_requested_bpc); else dsc_max_bpc = min_t(u8, 10, @@ -1553,7 +1474,7 @@ static bool intel_dp_port_has_audio(struct drm_i915_private *dev_priv, { if (IS_G4X(dev_priv)) return false; - if (INTEL_GEN(dev_priv) < 12 && port == PORT_A) + if (DISPLAY_VER(dev_priv) < 12 && port == PORT_A) return false; return true; @@ -1663,12 +1584,10 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp, const struct drm_connector_state *conn_state, struct drm_dp_vsc_sdp *vsc) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - vsc->sdp_type = DP_SDP_VSC; - if (dev_priv->psr.psr2_enabled) { - if (dev_priv->psr.colorimetry_support && + if (intel_dp->psr.psr2_enabled) { + if (intel_dp->psr.colorimetry_support && intel_dp_needs_vsc_sdp(crtc_state, conn_state)) { /* [PSR2, +Colorimetry] */ intel_dp_compute_vsc_colorimetry(crtc_state, conn_state, @@ -1724,6 +1643,7 @@ intel_dp_drrs_compute_config(struct intel_dp *intel_dp, { struct intel_connector *intel_connector = intel_dp->attached_connector; struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + int pixel_clock; if (pipe_config->vrr.enable) return; @@ -1742,10 +1662,18 @@ intel_dp_drrs_compute_config(struct intel_dp *intel_dp, return; pipe_config->has_drrs = true; - intel_link_compute_m_n(output_bpp, pipe_config->lane_count, - intel_connector->panel.downclock_mode->clock, + + pixel_clock = intel_connector->panel.downclock_mode->clock; + if (pipe_config->splitter.enable) + pixel_clock /= pipe_config->splitter.link_count; + + intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock, pipe_config->port_clock, &pipe_config->dp_m2_n2, constant_n, pipe_config->fec_enable); + + /* FIXME: abstract this better */ + if (pipe_config->splitter.enable) + pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count; } int @@ -1820,6 +1748,26 @@ intel_dp_compute_config(struct intel_encoder *encoder, output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_config->pipe_bpp); + if (intel_dp->mso_link_count) { + int n = intel_dp->mso_link_count; + int overlap = intel_dp->mso_pixel_overlap; + + pipe_config->splitter.enable = true; + pipe_config->splitter.link_count = n; + pipe_config->splitter.pixel_overlap = overlap; + + drm_dbg_kms(&dev_priv->drm, "MSO link count %d, pixel overlap %d\n", + n, overlap); + + adjusted_mode->crtc_hdisplay = adjusted_mode->crtc_hdisplay / n + overlap; + adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hblank_start / n + overlap; + adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_end / n + overlap; + adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hsync_start / n + overlap; + adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_end / n + overlap; + adjusted_mode->crtc_htotal = adjusted_mode->crtc_htotal / n + overlap; + adjusted_mode->crtc_clock /= n; + } + intel_link_compute_m_n(output_bpp, pipe_config->lane_count, adjusted_mode->crtc_clock, @@ -1827,8 +1775,12 @@ intel_dp_compute_config(struct intel_encoder *encoder, &pipe_config->dp_m_n, constant_n, pipe_config->fec_enable); + /* FIXME: abstract this better */ + if (pipe_config->splitter.enable) + pipe_config->dp_m_n.gmch_m *= pipe_config->splitter.link_count; + if (!HAS_DDI(dev_priv)) - intel_dp_set_clock(encoder, pipe_config); + g4x_dp_set_clock(encoder, pipe_config); intel_vrr_compute_config(pipe_config, conn_state); intel_psr_compute_config(intel_dp, pipe_config); @@ -1848,90 +1800,6 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, intel_dp->lane_count = lane_count; } -static void intel_dp_prepare(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - enum port port = encoder->port; - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); - const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; - - intel_dp_set_link_params(intel_dp, - pipe_config->port_clock, - pipe_config->lane_count); - - /* - * There are four kinds of DP registers: - * - * IBX PCH - * SNB CPU - * IVB CPU - * CPT PCH - * - * IBX PCH and CPU are the same for almost everything, - * except that the CPU DP PLL is configured in this - * register - * - * CPT PCH is quite different, having many bits moved - * to the TRANS_DP_CTL register instead. That - * configuration happens (oddly) in ilk_pch_enable - */ - - /* Preserve the BIOS-computed detected bit. This is - * supposed to be read-only. - */ - intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED; - - /* Handle DP bits in common between all three register formats */ - intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; - intel_dp->DP |= DP_PORT_WIDTH(pipe_config->lane_count); - - /* Split out the IBX/CPU vs CPT settings */ - - if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) { - if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) - intel_dp->DP |= DP_SYNC_HS_HIGH; - if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) - intel_dp->DP |= DP_SYNC_VS_HIGH; - intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; - - if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) - intel_dp->DP |= DP_ENHANCED_FRAMING; - - intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe); - } else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) { - u32 trans_dp; - - intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; - - trans_dp = intel_de_read(dev_priv, TRANS_DP_CTL(crtc->pipe)); - if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) - trans_dp |= TRANS_DP_ENH_FRAMING; - else - trans_dp &= ~TRANS_DP_ENH_FRAMING; - intel_de_write(dev_priv, TRANS_DP_CTL(crtc->pipe), trans_dp); - } else { - if (IS_G4X(dev_priv) && pipe_config->limited_color_range) - intel_dp->DP |= DP_COLOR_RANGE_16_235; - - if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) - intel_dp->DP |= DP_SYNC_HS_HIGH; - if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) - intel_dp->DP |= DP_SYNC_VS_HIGH; - intel_dp->DP |= DP_LINK_TRAIN_OFF; - - if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) - intel_dp->DP |= DP_ENHANCED_FRAMING; - - if (IS_CHERRYVIEW(dev_priv)) - intel_dp->DP |= DP_PIPE_SEL_CHV(crtc->pipe); - else - intel_dp->DP |= DP_PIPE_SEL(crtc->pipe); - } -} - - /* Enable backlight PWM and backlight PP control. */ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) @@ -1963,89 +1831,6 @@ void intel_edp_backlight_off(const struct drm_connector_state *old_conn_state) intel_panel_disable_backlight(old_conn_state); } -static void assert_dp_port(struct intel_dp *intel_dp, bool state) -{ - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); - bool cur_state = intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN; - - I915_STATE_WARN(cur_state != state, - "[ENCODER:%d:%s] state assertion failure (expected %s, current %s)\n", - dig_port->base.base.base.id, dig_port->base.base.name, - onoff(state), onoff(cur_state)); -} -#define assert_dp_port_disabled(d) assert_dp_port((d), false) - -static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state) -{ - bool cur_state = intel_de_read(dev_priv, DP_A) & DP_PLL_ENABLE; - - I915_STATE_WARN(cur_state != state, - "eDP PLL state assertion failure (expected %s, current %s)\n", - onoff(state), onoff(cur_state)); -} -#define assert_edp_pll_enabled(d) assert_edp_pll((d), true) -#define assert_edp_pll_disabled(d) assert_edp_pll((d), false) - -static void ilk_edp_pll_on(struct intel_dp *intel_dp, - const struct intel_crtc_state *pipe_config) -{ - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - - assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder); - assert_dp_port_disabled(intel_dp); - assert_edp_pll_disabled(dev_priv); - - drm_dbg_kms(&dev_priv->drm, "enabling eDP PLL for clock %d\n", - pipe_config->port_clock); - - intel_dp->DP &= ~DP_PLL_FREQ_MASK; - - if (pipe_config->port_clock == 162000) - intel_dp->DP |= DP_PLL_FREQ_162MHZ; - else - intel_dp->DP |= DP_PLL_FREQ_270MHZ; - - intel_de_write(dev_priv, DP_A, intel_dp->DP); - intel_de_posting_read(dev_priv, DP_A); - udelay(500); - - /* - * [DevILK] Work around required when enabling DP PLL - * while a pipe is enabled going to FDI: - * 1. Wait for the start of vertical blank on the enabled pipe going to FDI - * 2. Program DP PLL enable - */ - if (IS_GEN(dev_priv, 5)) - intel_wait_for_vblank_if_active(dev_priv, !crtc->pipe); - - intel_dp->DP |= DP_PLL_ENABLE; - - intel_de_write(dev_priv, DP_A, intel_dp->DP); - intel_de_posting_read(dev_priv, DP_A); - udelay(200); -} - -static void ilk_edp_pll_off(struct intel_dp *intel_dp, - const struct intel_crtc_state *old_crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - - assert_pipe_disabled(dev_priv, old_crtc_state->cpu_transcoder); - assert_dp_port_disabled(intel_dp); - assert_edp_pll_enabled(dev_priv); - - drm_dbg_kms(&dev_priv->drm, "disabling eDP PLL\n"); - - intel_dp->DP &= ~DP_PLL_ENABLE; - - intel_de_write(dev_priv, DP_A, intel_dp->DP); - intel_de_posting_read(dev_priv, DP_A); - udelay(200); -} - static bool downstream_hpd_needs_d0(struct intel_dp *intel_dp) { /* @@ -2148,160 +1933,6 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) mode == DP_SET_POWER_D0 ? "D0" : "D3"); } -static bool cpt_dp_port_selected(struct drm_i915_private *dev_priv, - enum port port, enum pipe *pipe) -{ - enum pipe p; - - for_each_pipe(dev_priv, p) { - u32 val = intel_de_read(dev_priv, TRANS_DP_CTL(p)); - - if ((val & TRANS_DP_PORT_SEL_MASK) == TRANS_DP_PORT_SEL(port)) { - *pipe = p; - return true; - } - } - - drm_dbg_kms(&dev_priv->drm, "No pipe for DP port %c found\n", - port_name(port)); - - /* must initialize pipe to something for the asserts */ - *pipe = PIPE_A; - - return false; -} - -bool intel_dp_port_enabled(struct drm_i915_private *dev_priv, - i915_reg_t dp_reg, enum port port, - enum pipe *pipe) -{ - bool ret; - u32 val; - - val = intel_de_read(dev_priv, dp_reg); - - ret = val & DP_PORT_EN; - - /* asserts want to know the pipe even if the port is disabled */ - if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) - *pipe = (val & DP_PIPE_SEL_MASK_IVB) >> DP_PIPE_SEL_SHIFT_IVB; - else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) - ret &= cpt_dp_port_selected(dev_priv, port, pipe); - else if (IS_CHERRYVIEW(dev_priv)) - *pipe = (val & DP_PIPE_SEL_MASK_CHV) >> DP_PIPE_SEL_SHIFT_CHV; - else - *pipe = (val & DP_PIPE_SEL_MASK) >> DP_PIPE_SEL_SHIFT; - - return ret; -} - -static bool intel_dp_get_hw_state(struct intel_encoder *encoder, - enum pipe *pipe) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - intel_wakeref_t wakeref; - bool ret; - - wakeref = intel_display_power_get_if_enabled(dev_priv, - encoder->power_domain); - if (!wakeref) - return false; - - ret = intel_dp_port_enabled(dev_priv, intel_dp->output_reg, - encoder->port, pipe); - - intel_display_power_put(dev_priv, encoder->power_domain, wakeref); - - return ret; -} - -static void intel_dp_get_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - u32 tmp, flags = 0; - enum port port = encoder->port; - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); - - if (encoder->type == INTEL_OUTPUT_EDP) - pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP); - else - pipe_config->output_types |= BIT(INTEL_OUTPUT_DP); - - tmp = intel_de_read(dev_priv, intel_dp->output_reg); - - pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A; - - if (HAS_PCH_CPT(dev_priv) && port != PORT_A) { - u32 trans_dp = intel_de_read(dev_priv, - TRANS_DP_CTL(crtc->pipe)); - - if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH) - flags |= DRM_MODE_FLAG_PHSYNC; - else - flags |= DRM_MODE_FLAG_NHSYNC; - - if (trans_dp & TRANS_DP_VSYNC_ACTIVE_HIGH) - flags |= DRM_MODE_FLAG_PVSYNC; - else - flags |= DRM_MODE_FLAG_NVSYNC; - } else { - 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->hw.adjusted_mode.flags |= flags; - - if (IS_G4X(dev_priv) && tmp & DP_COLOR_RANGE_16_235) - pipe_config->limited_color_range = true; - - pipe_config->lane_count = - ((tmp & DP_PORT_WIDTH_MASK) >> DP_PORT_WIDTH_SHIFT) + 1; - - intel_dp_get_m_n(crtc, pipe_config); - - if (port == PORT_A) { - if ((intel_de_read(dev_priv, DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_162MHZ) - pipe_config->port_clock = 162000; - else - pipe_config->port_clock = 270000; - } - - pipe_config->hw.adjusted_mode.crtc_clock = - intel_dotclock_calculate(pipe_config->port_clock, - &pipe_config->dp_m_n); - - if (intel_dp_is_edp(intel_dp) && dev_priv->vbt.edp.bpp && - pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) { - /* - * This is a big fat ugly hack. - * - * Some machines in UEFI boot mode provide us a VBT that has 18 - * bpp and 1.62 GHz link bandwidth for eDP, which for reasons - * unknown we fail to light up. Yet the same BIOS boots up with - * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as - * max, not what it tells us to use. - * - * Note: This will still be broken if the eDP panel is not lit - * up by the BIOS, and thus we can't get the mode at module - * load. - */ - drm_dbg_kms(&dev_priv->drm, - "pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", - pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp); - dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp; - } -} - static bool intel_dp_get_dpcd(struct intel_dp *intel_dp); @@ -2359,7 +1990,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, return false; } - if (CAN_PSR(i915) && intel_dp_is_edp(intel_dp)) { + if (CAN_PSR(intel_dp)) { drm_dbg_kms(&i915->drm, "Forcing full modeset to compute PSR state\n"); crtc_state->uapi.mode_changed = true; return false; @@ -2368,122 +1999,6 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, return true; } -static void intel_disable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - - intel_dp->link_trained = false; - - if (old_crtc_state->has_audio) - intel_audio_codec_disable(encoder, - old_crtc_state, old_conn_state); - - /* 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. */ - intel_pps_vdd_on(intel_dp); - intel_edp_backlight_off(old_conn_state); - intel_dp_set_power(intel_dp, DP_SET_POWER_D3); - intel_pps_off(intel_dp); - intel_dp->frl.is_trained = false; - intel_dp->frl.trained_rate_gbps = 0; -} - -static void g4x_disable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - intel_disable_dp(state, encoder, old_crtc_state, old_conn_state); -} - -static void vlv_disable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - intel_disable_dp(state, encoder, old_crtc_state, old_conn_state); -} - -static void g4x_post_disable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - enum port port = encoder->port; - - /* - * Bspec does not list a specific disable sequence for g4x DP. - * Follow the ilk+ sequence (disable pipe before the port) for - * g4x DP as it does not suffer from underruns like the normal - * g4x modeset sequence (disable pipe after the port). - */ - intel_dp_link_down(encoder, old_crtc_state); - - /* Only ilk+ has port A */ - if (port == PORT_A) - ilk_edp_pll_off(intel_dp, old_crtc_state); -} - -static void vlv_post_disable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - intel_dp_link_down(encoder, old_crtc_state); -} - -static void chv_post_disable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - - intel_dp_link_down(encoder, old_crtc_state); - - vlv_dpio_get(dev_priv); - - /* Assert data lane reset */ - chv_data_lane_soft_reset(encoder, old_crtc_state, true); - - vlv_dpio_put(dev_priv); -} - -static void -cpt_set_link_train(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state, - u8 dp_train_pat) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - u32 *DP = &intel_dp->DP; - - *DP &= ~DP_LINK_TRAIN_MASK_CPT; - - switch (intel_dp_training_pattern_symbol(dp_train_pat)) { - case DP_TRAINING_PATTERN_DISABLE: - *DP |= DP_LINK_TRAIN_OFF_CPT; - break; - case DP_TRAINING_PATTERN_1: - *DP |= DP_LINK_TRAIN_PAT_1_CPT; - break; - case DP_TRAINING_PATTERN_2: - *DP |= DP_LINK_TRAIN_PAT_2_CPT; - break; - case DP_TRAINING_PATTERN_3: - drm_dbg_kms(&dev_priv->drm, - "TPS3 not supported, using TPS2 instead\n"); - *DP |= DP_LINK_TRAIN_PAT_2_CPT; - break; - } - - intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); -} - static void intel_dp_get_pcon_dsc_cap(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -2558,10 +2073,6 @@ static int intel_dp_hdmi_sink_max_frl(struct intel_dp *intel_dp) static int intel_dp_pcon_start_frl_training(struct intel_dp *intel_dp) { -#define PCON_EXTENDED_TRAIN_MODE (1 > 0) -#define PCON_CONCURRENT_MODE (1 > 0) -#define PCON_SEQUENTIAL_MODE !PCON_CONCURRENT_MODE -#define PCON_NORMAL_TRAIN_MODE !PCON_EXTENDED_TRAIN_MODE #define TIMEOUT_FRL_READY_MS 500 #define TIMEOUT_HDMI_LINK_ACTIVE_MS 1000 @@ -2595,10 +2106,12 @@ static int intel_dp_pcon_start_frl_training(struct intel_dp *intel_dp) return -ETIMEDOUT; max_frl_bw_mask = intel_dp_pcon_set_frl_mask(max_frl_bw); - ret = drm_dp_pcon_frl_configure_1(&intel_dp->aux, max_frl_bw, PCON_SEQUENTIAL_MODE); + ret = drm_dp_pcon_frl_configure_1(&intel_dp->aux, max_frl_bw, + DP_PCON_ENABLE_SEQUENTIAL_LINK); if (ret < 0) return ret; - ret = drm_dp_pcon_frl_configure_2(&intel_dp->aux, max_frl_bw_mask, PCON_NORMAL_TRAIN_MODE); + ret = drm_dp_pcon_frl_configure_2(&intel_dp->aux, max_frl_bw_mask, + DP_PCON_FRL_LINK_TRAIN_NORMAL); if (ret < 0) return ret; ret = drm_dp_pcon_frl_enable(&intel_dp->aux); @@ -2642,15 +2155,20 @@ void intel_dp_check_frl_training(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - /* Always go for FRL training if supported */ - if (!intel_dp_is_hdmi_2_1_sink(intel_dp) || + /* + * Always go for FRL training if: + * -PCON supports SRC_CTL_MODE (VESA DP2.0-HDMI2.1 PCON Spec Draft-1 Sec-7) + * -sink is HDMI2.1 + */ + if (!(intel_dp->dpcd[2] & DP_PCON_SOURCE_CTL_MODE) || + !intel_dp_is_hdmi_2_1_sink(intel_dp) || intel_dp->frl.is_trained) return; if (intel_dp_pcon_start_frl_training(intel_dp) < 0) { int ret, mode; - drm_dbg(&dev_priv->drm, "Couldnt set FRL mode, continuing with TMDS mode\n"); + drm_dbg(&dev_priv->drm, "Couldn't set FRL mode, continuing with TMDS mode\n"); ret = drm_dp_pcon_reset_frl_config(&intel_dp->aux); mode = drm_dp_pcon_hdmi_link_mode(&intel_dp->aux, NULL); @@ -2758,61 +2276,6 @@ intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp, drm_dbg_kms(&i915->drm, "Failed to set pcon DSC\n"); } -static void -g4x_set_link_train(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state, - u8 dp_train_pat) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - u32 *DP = &intel_dp->DP; - - *DP &= ~DP_LINK_TRAIN_MASK; - - switch (intel_dp_training_pattern_symbol(dp_train_pat)) { - case DP_TRAINING_PATTERN_DISABLE: - *DP |= DP_LINK_TRAIN_OFF; - break; - case DP_TRAINING_PATTERN_1: - *DP |= DP_LINK_TRAIN_PAT_1; - break; - case DP_TRAINING_PATTERN_2: - *DP |= DP_LINK_TRAIN_PAT_2; - break; - case DP_TRAINING_PATTERN_3: - drm_dbg_kms(&dev_priv->drm, - "TPS3 not supported, using TPS2 instead\n"); - *DP |= DP_LINK_TRAIN_PAT_2; - break; - } - - intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); -} - -static void intel_dp_enable_port(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - - /* enable with pattern 1 (as per spec) */ - - intel_dp_program_link_training_pattern(intel_dp, crtc_state, - DP_TRAINING_PATTERN_1); - - /* - * Magic for VLV/CHV. We _must_ first set up the register - * without actually enabling the port, and then do another - * write to enable the port. Otherwise link training will - * fail when the power sequencer is freshly used for this port. - */ - intel_dp->DP |= DP_PORT_EN; - if (crtc_state->has_audio) - intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; - - intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); -} - void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -2881,592 +2344,6 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, enableddisabled(tmp ? true : false)); } -static void intel_enable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); - u32 dp_reg = intel_de_read(dev_priv, intel_dp->output_reg); - enum pipe pipe = crtc->pipe; - intel_wakeref_t wakeref; - - if (drm_WARN_ON(&dev_priv->drm, dp_reg & DP_PORT_EN)) - return; - - with_intel_pps_lock(intel_dp, wakeref) { - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - vlv_pps_init(encoder, pipe_config); - - intel_dp_enable_port(intel_dp, pipe_config); - - intel_pps_vdd_on_unlocked(intel_dp); - intel_pps_on_unlocked(intel_dp); - intel_pps_vdd_off_unlocked(intel_dp, true); - } - - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - unsigned int lane_mask = 0x0; - - if (IS_CHERRYVIEW(dev_priv)) - lane_mask = intel_dp_unused_lane_mask(pipe_config->lane_count); - - vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp), - lane_mask); - } - - intel_dp_set_power(intel_dp, DP_SET_POWER_D0); - intel_dp_configure_protocol_converter(intel_dp, pipe_config); - intel_dp_check_frl_training(intel_dp); - intel_dp_pcon_dsc_configure(intel_dp, pipe_config); - intel_dp_start_link_train(intel_dp, pipe_config); - intel_dp_stop_link_train(intel_dp, pipe_config); - - if (pipe_config->has_audio) { - drm_dbg(&dev_priv->drm, "Enabling DP audio on pipe %c\n", - pipe_name(pipe)); - intel_audio_codec_enable(encoder, pipe_config, conn_state); - } -} - -static void g4x_enable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) -{ - intel_enable_dp(state, encoder, pipe_config, conn_state); - intel_edp_backlight_on(pipe_config, conn_state); -} - -static void vlv_enable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) -{ - intel_edp_backlight_on(pipe_config, conn_state); -} - -static void g4x_pre_enable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) -{ - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - enum port port = encoder->port; - - intel_dp_prepare(encoder, pipe_config); - - /* Only ilk+ has port A */ - if (port == PORT_A) - ilk_edp_pll_on(intel_dp, pipe_config); -} - -static void vlv_pre_enable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) -{ - vlv_phy_pre_encoder_enable(encoder, pipe_config); - - intel_enable_dp(state, encoder, pipe_config, conn_state); -} - -static void vlv_dp_pre_pll_enable(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) -{ - intel_dp_prepare(encoder, pipe_config); - - vlv_phy_pre_pll_enable(encoder, pipe_config); -} - -static void chv_pre_enable_dp(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) -{ - chv_phy_pre_encoder_enable(encoder, pipe_config); - - intel_enable_dp(state, encoder, pipe_config, conn_state); - - /* Second common lane will stay alive on its own now */ - chv_phy_release_cl2_override(encoder); -} - -static void chv_dp_pre_pll_enable(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) -{ - intel_dp_prepare(encoder, pipe_config); - - chv_phy_pre_pll_enable(encoder, pipe_config); -} - -static void chv_dp_post_pll_disable(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - chv_phy_post_pll_disable(encoder, old_crtc_state); -} - -static u8 intel_dp_voltage_max_2(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; -} - -static u8 intel_dp_voltage_max_3(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; -} - -static u8 intel_dp_preemph_max_2(struct intel_dp *intel_dp) -{ - return DP_TRAIN_PRE_EMPH_LEVEL_2; -} - -static u8 intel_dp_preemph_max_3(struct intel_dp *intel_dp) -{ - return DP_TRAIN_PRE_EMPH_LEVEL_3; -} - -static void vlv_set_signal_levels(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - unsigned long demph_reg_value, preemph_reg_value, - uniqtranscale_reg_value; - u8 train_set = intel_dp->train_set[0]; - - switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { - case DP_TRAIN_PRE_EMPH_LEVEL_0: - preemph_reg_value = 0x0004000; - switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - demph_reg_value = 0x2B405555; - uniqtranscale_reg_value = 0x552AB83A; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - demph_reg_value = 0x2B404040; - uniqtranscale_reg_value = 0x5548B83A; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: - demph_reg_value = 0x2B245555; - uniqtranscale_reg_value = 0x5560B83A; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: - demph_reg_value = 0x2B405555; - uniqtranscale_reg_value = 0x5598DA3A; - break; - default: - return; - } - break; - case DP_TRAIN_PRE_EMPH_LEVEL_1: - preemph_reg_value = 0x0002000; - switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - demph_reg_value = 0x2B404040; - uniqtranscale_reg_value = 0x5552B83A; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - demph_reg_value = 0x2B404848; - uniqtranscale_reg_value = 0x5580B83A; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: - demph_reg_value = 0x2B404040; - uniqtranscale_reg_value = 0x55ADDA3A; - break; - default: - return; - } - break; - case DP_TRAIN_PRE_EMPH_LEVEL_2: - preemph_reg_value = 0x0000000; - switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - demph_reg_value = 0x2B305555; - uniqtranscale_reg_value = 0x5570B83A; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - demph_reg_value = 0x2B2B4040; - uniqtranscale_reg_value = 0x55ADDA3A; - break; - default: - return; - } - break; - case DP_TRAIN_PRE_EMPH_LEVEL_3: - preemph_reg_value = 0x0006000; - switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - demph_reg_value = 0x1B405555; - uniqtranscale_reg_value = 0x55ADDA3A; - break; - default: - return; - } - break; - default: - return; - } - - vlv_set_phy_signal_level(encoder, crtc_state, - demph_reg_value, preemph_reg_value, - uniqtranscale_reg_value, 0); -} - -static void chv_set_signal_levels(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - u32 deemph_reg_value, margin_reg_value; - bool uniq_trans_scale = false; - u8 train_set = intel_dp->train_set[0]; - - switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { - case DP_TRAIN_PRE_EMPH_LEVEL_0: - switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - deemph_reg_value = 128; - margin_reg_value = 52; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - deemph_reg_value = 128; - margin_reg_value = 77; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: - deemph_reg_value = 128; - margin_reg_value = 102; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: - deemph_reg_value = 128; - margin_reg_value = 154; - uniq_trans_scale = true; - break; - default: - return; - } - break; - case DP_TRAIN_PRE_EMPH_LEVEL_1: - switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - deemph_reg_value = 85; - margin_reg_value = 78; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - deemph_reg_value = 85; - margin_reg_value = 116; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: - deemph_reg_value = 85; - margin_reg_value = 154; - break; - default: - return; - } - break; - case DP_TRAIN_PRE_EMPH_LEVEL_2: - switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - deemph_reg_value = 64; - margin_reg_value = 104; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - deemph_reg_value = 64; - margin_reg_value = 154; - break; - default: - return; - } - break; - case DP_TRAIN_PRE_EMPH_LEVEL_3: - switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - deemph_reg_value = 43; - margin_reg_value = 154; - break; - default: - return; - } - break; - default: - return; - } - - chv_set_phy_signal_level(encoder, crtc_state, - deemph_reg_value, margin_reg_value, - uniq_trans_scale); -} - -static u32 g4x_signal_levels(u8 train_set) -{ - u32 signal_levels = 0; - - switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: - default: - signal_levels |= DP_VOLTAGE_0_4; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: - signal_levels |= DP_VOLTAGE_0_6; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: - signal_levels |= DP_VOLTAGE_0_8; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: - signal_levels |= DP_VOLTAGE_1_2; - break; - } - switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { - case DP_TRAIN_PRE_EMPH_LEVEL_0: - default: - signal_levels |= DP_PRE_EMPHASIS_0; - break; - case DP_TRAIN_PRE_EMPH_LEVEL_1: - signal_levels |= DP_PRE_EMPHASIS_3_5; - break; - case DP_TRAIN_PRE_EMPH_LEVEL_2: - signal_levels |= DP_PRE_EMPHASIS_6; - break; - case DP_TRAIN_PRE_EMPH_LEVEL_3: - signal_levels |= DP_PRE_EMPHASIS_9_5; - break; - } - return signal_levels; -} - -static void -g4x_set_signal_levels(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - u8 train_set = intel_dp->train_set[0]; - u32 signal_levels; - - signal_levels = g4x_signal_levels(train_set); - - drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n", - signal_levels); - - intel_dp->DP &= ~(DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK); - intel_dp->DP |= signal_levels; - - intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); -} - -/* SNB CPU eDP voltage swing and pre-emphasis control */ -static u32 snb_cpu_edp_signal_levels(u8 train_set) -{ - u8 signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | - DP_TRAIN_PRE_EMPHASIS_MASK); - - switch (signal_levels) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return EDP_LINK_TRAIN_400MV_3_5DB_SNB_B; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: - return EDP_LINK_TRAIN_400_600MV_6DB_SNB_B; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B; - default: - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" - "0x%x\n", signal_levels); - return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B; - } -} - -static void -snb_cpu_edp_set_signal_levels(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - u8 train_set = intel_dp->train_set[0]; - u32 signal_levels; - - signal_levels = snb_cpu_edp_signal_levels(train_set); - - drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n", - signal_levels); - - intel_dp->DP &= ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB; - intel_dp->DP |= signal_levels; - - intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); -} - -/* IVB CPU eDP voltage swing and pre-emphasis control */ -static u32 ivb_cpu_edp_signal_levels(u8 train_set) -{ - u8 signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | - DP_TRAIN_PRE_EMPHASIS_MASK); - - switch (signal_levels) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return EDP_LINK_TRAIN_400MV_0DB_IVB; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return EDP_LINK_TRAIN_400MV_3_5DB_IVB; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: - return EDP_LINK_TRAIN_400MV_6DB_IVB; - - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return EDP_LINK_TRAIN_600MV_0DB_IVB; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return EDP_LINK_TRAIN_600MV_3_5DB_IVB; - - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return EDP_LINK_TRAIN_800MV_0DB_IVB; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return EDP_LINK_TRAIN_800MV_3_5DB_IVB; - - default: - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" - "0x%x\n", signal_levels); - return EDP_LINK_TRAIN_500MV_0DB_IVB; - } -} - -static void -ivb_cpu_edp_set_signal_levels(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - u8 train_set = intel_dp->train_set[0]; - u32 signal_levels; - - signal_levels = ivb_cpu_edp_signal_levels(train_set); - - drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n", - signal_levels); - - intel_dp->DP &= ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; - intel_dp->DP |= signal_levels; - - intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); -} - -static char dp_training_pattern_name(u8 train_pat) -{ - switch (train_pat) { - case DP_TRAINING_PATTERN_1: - case DP_TRAINING_PATTERN_2: - case DP_TRAINING_PATTERN_3: - return '0' + train_pat; - case DP_TRAINING_PATTERN_4: - return '4'; - default: - MISSING_CASE(train_pat); - return '?'; - } -} - -void -intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state, - u8 dp_train_pat) -{ - struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u8 train_pat = intel_dp_training_pattern_symbol(dp_train_pat); - - if (train_pat != DP_TRAINING_PATTERN_DISABLE) - drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] Using DP training pattern TPS%c\n", - encoder->base.base.id, encoder->base.name, - dp_training_pattern_name(train_pat)); - - intel_dp->set_link_train(intel_dp, crtc_state, dp_train_pat); -} - -static void -intel_dp_link_down(struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - enum port port = encoder->port; - u32 DP = intel_dp->DP; - - if (drm_WARN_ON(&dev_priv->drm, - (intel_de_read(dev_priv, intel_dp->output_reg) & - DP_PORT_EN) == 0)) - return; - - drm_dbg_kms(&dev_priv->drm, "\n"); - - if ((IS_IVYBRIDGE(dev_priv) && port == PORT_A) || - (HAS_PCH_CPT(dev_priv) && port != PORT_A)) { - DP &= ~DP_LINK_TRAIN_MASK_CPT; - DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; - } else { - DP &= ~DP_LINK_TRAIN_MASK; - DP |= DP_LINK_TRAIN_PAT_IDLE; - } - intel_de_write(dev_priv, intel_dp->output_reg, DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); - - DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE); - intel_de_write(dev_priv, intel_dp->output_reg, DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); - - /* - * HW workaround for IBX, we need to move the port - * to transcoder A after disabling it to allow the - * matching HDMI port to be enabled on transcoder A. - */ - if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B && port != PORT_A) { - /* - * We get CPU/PCH FIFO underruns on the other pipe when - * doing the workaround. Sweep them under the rug. - */ - intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false); - intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); - - /* always enable with pattern 1 (as per spec) */ - DP &= ~(DP_PIPE_SEL_MASK | DP_LINK_TRAIN_MASK); - DP |= DP_PORT_EN | DP_PIPE_SEL(PIPE_A) | - DP_LINK_TRAIN_PAT_1; - intel_de_write(dev_priv, intel_dp->output_reg, DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); - - DP &= ~DP_PORT_EN; - intel_de_write(dev_priv, intel_dp->output_reg, DP); - intel_de_posting_read(dev_priv, intel_dp->output_reg); - - intel_wait_for_vblank_if_active(dev_priv, PIPE_A); - intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true); - intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); - } - - msleep(intel_dp->pps.panel_power_down_delay); - - intel_dp->DP = DP; - - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - intel_wakeref_t wakeref; - - with_intel_pps_lock(intel_dp, wakeref) - intel_dp->pps.active_pipe = INVALID_PIPE; - } -} bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp) { @@ -3517,6 +2394,64 @@ static void intel_dp_get_dsc_sink_cap(struct intel_dp *intel_dp) } } +static void intel_edp_mso_mode_fixup(struct intel_connector *connector, + struct drm_display_mode *mode) +{ + struct intel_dp *intel_dp = intel_attached_dp(connector); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int n = intel_dp->mso_link_count; + int overlap = intel_dp->mso_pixel_overlap; + + if (!mode || !n) + return; + + mode->hdisplay = (mode->hdisplay - overlap) * n; + mode->hsync_start = (mode->hsync_start - overlap) * n; + mode->hsync_end = (mode->hsync_end - overlap) * n; + mode->htotal = (mode->htotal - overlap) * n; + mode->clock *= n; + + drm_mode_set_name(mode); + + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] using generated MSO mode: ", + connector->base.base.id, connector->base.name); + drm_mode_debug_printmodeline(mode); +} + +static void intel_edp_mso_init(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + u8 mso; + + if (intel_dp->edp_dpcd[0] < DP_EDP_14) + return; + + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_MSO_LINK_CAPABILITIES, &mso) != 1) { + drm_err(&i915->drm, "Failed to read MSO cap\n"); + return; + } + + /* Valid configurations are SST or MSO 2x1, 2x2, 4x1 */ + mso &= DP_EDP_MSO_NUMBER_OF_LINKS_MASK; + if (mso % 2 || mso > drm_dp_max_lane_count(intel_dp->dpcd)) { + drm_err(&i915->drm, "Invalid MSO link count cap %u\n", mso); + mso = 0; + } + + if (mso) { + drm_dbg_kms(&i915->drm, "Sink MSO %ux%u configuration\n", + mso, drm_dp_max_lane_count(intel_dp->dpcd) / mso); + if (!HAS_MSO(i915)) { + drm_err(&i915->drm, "No source MSO support, disabling\n"); + mso = 0; + } + } + + intel_dp->mso_link_count = mso; + intel_dp->mso_pixel_overlap = 0; /* FIXME: read from DisplayID v2.0 */ +} + static bool intel_edp_init_dpcd(struct intel_dp *intel_dp) { @@ -3591,7 +2526,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) intel_dp_set_common_rates(intel_dp); /* Read the eDP DSC DPCD registers */ - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) + if (DISPLAY_VER(dev_priv) >= 10) intel_dp_get_dsc_sink_cap(intel_dp); /* @@ -3600,6 +2535,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) */ intel_edp_init_source_oui(intel_dp, true); + intel_edp_mso_init(intel_dp); + return true; } @@ -4768,7 +3705,7 @@ int intel_dp_retrain_link(struct intel_encoder *encoder, to_intel_crtc_state(crtc->base.state); /* retrain on the MST master transcoder */ - if (INTEL_GEN(dev_priv) >= 12 && + if (DISPLAY_VER(dev_priv) >= 12 && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) && !intel_dp_mst_is_master_trans(crtc_state)) continue; @@ -4872,7 +3809,7 @@ static int intel_dp_do_phy_test(struct intel_encoder *encoder, to_intel_crtc_state(crtc->base.state); /* test on the MST master transcoder */ - if (INTEL_GEN(dev_priv) >= 12 && + if (DISPLAY_VER(dev_priv) >= 12 && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) && !intel_dp_mst_is_master_trans(crtc_state)) continue; @@ -4908,64 +3845,6 @@ void intel_dp_phy_test(struct intel_encoder *encoder) "Acquiring modeset locks failed with %i\n", ret); } -/* - * If display is now connected check links status, - * there has been known issues of link loss triggering - * long pulse. - * - * Some sinks (eg. ASUS PB287Q) seem to perform some - * weird HPD ping pong during modesets. So we can apparently - * end up with HPD going low during a modeset, and then - * going back up soon after. And once that happens we must - * retrain the link to get a picture. That's in case no - * userspace component reacted to intermittent HPD dip. - */ -static enum intel_hotplug_state -intel_dp_hotplug(struct intel_encoder *encoder, - struct intel_connector *connector) -{ - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct drm_modeset_acquire_ctx ctx; - enum intel_hotplug_state state; - int ret; - - if (intel_dp->compliance.test_active && - intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) { - intel_dp_phy_test(encoder); - /* just do the PHY test and nothing else */ - return INTEL_HOTPLUG_UNCHANGED; - } - - state = intel_encoder_hotplug(encoder, connector); - - drm_modeset_acquire_init(&ctx, 0); - - for (;;) { - ret = intel_dp_retrain_link(encoder, &ctx); - - if (ret == -EDEADLK) { - drm_modeset_backoff(&ctx); - continue; - } - - break; - } - - drm_modeset_drop_locks(&ctx); - drm_modeset_acquire_fini(&ctx); - drm_WARN(encoder->base.dev, ret, - "Acquiring modeset locks failed with %i\n", ret); - - /* - * Keeping it consistent with intel_ddi_hotplug() and - * intel_hdmi_hotplug(). - */ - if (state == INTEL_HOTPLUG_UNCHANGED && !connector->hotplug_retries) - state = INTEL_HOTPLUG_RETRY; - - return state; -} - static void intel_dp_check_device_service_irq(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -5147,68 +4026,6 @@ edp_detect(struct intel_dp *intel_dp) return connector_status_connected; } -static bool ibx_digital_port_connected(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 bit = dev_priv->hotplug.pch_hpd[encoder->hpd_pin]; - - return intel_de_read(dev_priv, SDEISR) & bit; -} - -static bool g4x_digital_port_connected(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 bit; - - switch (encoder->hpd_pin) { - case HPD_PORT_B: - bit = PORTB_HOTPLUG_LIVE_STATUS_G4X; - break; - case HPD_PORT_C: - bit = PORTC_HOTPLUG_LIVE_STATUS_G4X; - break; - case HPD_PORT_D: - bit = PORTD_HOTPLUG_LIVE_STATUS_G4X; - break; - default: - MISSING_CASE(encoder->hpd_pin); - return false; - } - - return intel_de_read(dev_priv, PORT_HOTPLUG_STAT) & bit; -} - -static bool gm45_digital_port_connected(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 bit; - - switch (encoder->hpd_pin) { - case HPD_PORT_B: - bit = PORTB_HOTPLUG_LIVE_STATUS_GM45; - break; - case HPD_PORT_C: - bit = PORTC_HOTPLUG_LIVE_STATUS_GM45; - break; - case HPD_PORT_D: - bit = PORTD_HOTPLUG_LIVE_STATUS_GM45; - break; - default: - MISSING_CASE(encoder->hpd_pin); - return false; - } - - return intel_de_read(dev_priv, PORT_HOTPLUG_STAT) & bit; -} - -static bool ilk_digital_port_connected(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 bit = dev_priv->hotplug.hpd[encoder->hpd_pin]; - - return intel_de_read(dev_priv, DEISR) & bit; -} - /* * intel_digital_port_connected - is the specified port connected? * @encoder: intel_encoder @@ -5305,7 +4122,7 @@ intel_dp_update_420(struct intel_dp *intel_dp) * ILK doesn't seem capable of DP YCbCr output. The * displayed image is severly corrupted. SNB+ is fine. */ - if (IS_GEN(i915, 5)) + if (IS_IRONLAKE(i915)) return; is_branch = drm_dp_is_branch(intel_dp->dpcd); @@ -5323,7 +4140,7 @@ intel_dp_update_420(struct intel_dp *intel_dp) DP_DS_HDMI_BT709_RGB_YCBCR_CONV | DP_DS_HDMI_BT2020_RGB_YCBCR_CONV); - if (INTEL_GEN(i915) >= 11) { + if (DISPLAY_VER(i915) >= 11) { /* Let PCON convert from RGB->YCbCr if possible */ if (is_branch && rgb_to_ycbcr && ycbcr_444_to_420) { intel_dp->dfp.rgb_to_ycbcr = true; @@ -5441,7 +4258,7 @@ intel_dp_detect(struct drm_connector *connector, } /* Read DP Sink DSC Cap DPCD regs for DP v1.4 */ - if (INTEL_GEN(dev_priv) >= 11) + if (DISPLAY_VER(dev_priv) >= 11) intel_dp_get_dsc_sink_cap(intel_dp); intel_dp_configure_mst(intel_dp); @@ -5546,19 +4363,18 @@ static int intel_dp_get_modes(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); struct edid *edid; + int num_modes = 0; edid = intel_connector->detect_edid; if (edid) { - int ret = intel_connector_update_modes(connector, edid); + num_modes = intel_connector_update_modes(connector, edid); if (intel_vrr_is_capable(connector)) drm_connector_set_vrr_capable_property(connector, true); - if (ret) - return ret; } - /* if eDP has no EDID, fall back to fixed mode */ + /* Also add fixed mode, which may or may not be present in EDID */ if (intel_dp_is_edp(intel_attached_dp(intel_connector)) && intel_connector->panel.fixed_mode) { struct drm_display_mode *mode; @@ -5567,10 +4383,13 @@ static int intel_dp_get_modes(struct drm_connector *connector) intel_connector->panel.fixed_mode); if (mode) { drm_mode_probed_add(connector, mode); - return 1; + num_modes++; } } + if (num_modes) + return num_modes; + if (!edid) { struct intel_dp *intel_dp = intel_attached_dp(intel_connector); struct drm_display_mode *mode; @@ -5580,11 +4399,11 @@ static int intel_dp_get_modes(struct drm_connector *connector) intel_dp->downstream_ports); if (mode) { drm_mode_probed_add(connector, mode); - return 1; + num_modes++; } } - return 0; + return num_modes; } static int @@ -5648,14 +4467,6 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder) intel_dp_aux_fini(intel_dp); } -static void intel_dp_encoder_destroy(struct drm_encoder *encoder) -{ - intel_dp_encoder_flush_work(encoder); - - drm_encoder_cleanup(encoder); - kfree(enc_to_dig_port(to_intel_encoder(encoder))); -} - void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder); @@ -5670,39 +4481,6 @@ void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder) intel_pps_wait_power_cycle(intel_dp); } -static enum pipe vlv_active_pipe(struct intel_dp *intel_dp) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - enum pipe pipe; - - if (intel_dp_port_enabled(dev_priv, intel_dp->output_reg, - encoder->port, &pipe)) - return pipe; - - return INVALID_PIPE; -} - -void intel_dp_encoder_reset(struct drm_encoder *encoder) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->dev); - struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder)); - - if (!HAS_DDI(dev_priv)) - intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg); - - intel_dp->reset_link_params = true; - - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - intel_wakeref_t wakeref; - - with_intel_pps_lock(intel_dp, wakeref) - intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp); - } - - intel_pps_encoder_reset(intel_dp); -} - static int intel_modeset_tile_group(struct intel_atomic_state *state, int tile_group_id) { @@ -5826,7 +4604,7 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn, * We don't enable port sync on BDW due to missing w/as and * due to not having adjusted the modeset sequence appropriately. */ - if (INTEL_GEN(dev_priv) < 9) + if (DISPLAY_VER(dev_priv) < 9) return 0; if (!intel_connector_needs_modeset(state, conn)) @@ -5860,11 +4638,6 @@ static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = .atomic_check = intel_dp_connector_atomic_check, }; -static const struct drm_encoder_funcs intel_dp_enc_funcs = { - .reset = intel_dp_encoder_reset, - .destroy = intel_dp_encoder_destroy, -}; - enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd) { @@ -5914,10 +4687,10 @@ bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port) * eDP not supported on g4x. so bail out early just * for a bit extra safety in case the VBT is bonkers. */ - if (INTEL_GEN(dev_priv) < 5) + if (DISPLAY_VER(dev_priv) < 5) return false; - if (INTEL_GEN(dev_priv) < 9 && port == PORT_A) + if (DISPLAY_VER(dev_priv) < 9 && port == PORT_A) return true; return intel_bios_is_port_edp(dev_priv, port); @@ -5938,7 +4711,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_broadcast_rgb_property(connector); if (HAS_GMCH(dev_priv)) drm_connector_attach_max_bpc_property(connector, 6, 10); - else if (INTEL_GEN(dev_priv) >= 5) + else if (DISPLAY_VER(dev_priv) >= 5) drm_connector_attach_max_bpc_property(connector, 6, 12); /* Register HDMI colorspace for case of lspcon */ @@ -5949,7 +4722,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_dp_colorspace_property(connector); } - if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 11) + if (IS_GEMINILAKE(dev_priv) || DISPLAY_VER(dev_priv) >= 11) drm_object_attach_property(&connector->base, connector->dev->mode_config.hdr_output_metadata_property, 0); @@ -6030,7 +4803,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, return; } - if (INTEL_GEN(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) { + if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) { switch (index) { case DRRS_HIGH_RR: intel_dp_set_m_n(crtc_state, M1_N1); @@ -6043,7 +4816,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, drm_err(&dev_priv->drm, "Unsupported refreshrate type\n"); } - } else if (INTEL_GEN(dev_priv) > 6) { + } else if (DISPLAY_VER(dev_priv) > 6) { i915_reg_t reg = PIPECONF(crtc_state->cpu_transcoder); u32 val; @@ -6371,7 +5144,7 @@ intel_dp_drrs_init(struct intel_connector *connector, INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work); mutex_init(&dev_priv->drrs.mutex); - if (INTEL_GEN(dev_priv) <= 6) { + if (DISPLAY_VER(dev_priv) <= 6) { drm_dbg_kms(&dev_priv->drm, "DRRS supported for Gen7 and above\n"); return NULL; @@ -6457,6 +5230,10 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, if (fixed_mode) downclock_mode = intel_dp_drrs_init(intel_connector, fixed_mode); + /* multiply the mode clock and horizontal timings for MSO */ + intel_edp_mso_mode_fixup(intel_connector, fixed_mode); + intel_edp_mso_mode_fixup(intel_connector, downclock_mode); + /* fallback to VBT if available for eDP */ if (!fixed_mode) fixed_mode = intel_panel_vbt_fixed_mode(intel_connector); @@ -6639,6 +5416,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, intel_dp->frl.is_trained = false; intel_dp->frl.trained_rate_gbps = 0; + intel_psr_init(intel_dp); + return true; fail: @@ -6647,137 +5426,6 @@ fail: return false; } -bool intel_dp_init(struct drm_i915_private *dev_priv, - i915_reg_t output_reg, - enum port port) -{ - struct intel_digital_port *dig_port; - struct intel_encoder *intel_encoder; - struct drm_encoder *encoder; - struct intel_connector *intel_connector; - - dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL); - if (!dig_port) - return false; - - intel_connector = intel_connector_alloc(); - if (!intel_connector) - goto err_connector_alloc; - - intel_encoder = &dig_port->base; - encoder = &intel_encoder->base; - - mutex_init(&dig_port->hdcp_mutex); - - if (drm_encoder_init(&dev_priv->drm, &intel_encoder->base, - &intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS, - "DP %c", port_name(port))) - goto err_encoder_init; - - intel_encoder->hotplug = intel_dp_hotplug; - intel_encoder->compute_config = intel_dp_compute_config; - intel_encoder->get_hw_state = intel_dp_get_hw_state; - intel_encoder->get_config = intel_dp_get_config; - intel_encoder->sync_state = intel_dp_sync_state; - intel_encoder->initial_fastset_check = intel_dp_initial_fastset_check; - intel_encoder->update_pipe = intel_panel_update_backlight; - intel_encoder->suspend = intel_dp_encoder_suspend; - intel_encoder->shutdown = intel_dp_encoder_shutdown; - if (IS_CHERRYVIEW(dev_priv)) { - intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; - intel_encoder->pre_enable = chv_pre_enable_dp; - intel_encoder->enable = vlv_enable_dp; - intel_encoder->disable = vlv_disable_dp; - intel_encoder->post_disable = chv_post_disable_dp; - intel_encoder->post_pll_disable = chv_dp_post_pll_disable; - } else if (IS_VALLEYVIEW(dev_priv)) { - intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable; - intel_encoder->pre_enable = vlv_pre_enable_dp; - intel_encoder->enable = vlv_enable_dp; - intel_encoder->disable = vlv_disable_dp; - intel_encoder->post_disable = vlv_post_disable_dp; - } else { - intel_encoder->pre_enable = g4x_pre_enable_dp; - intel_encoder->enable = g4x_enable_dp; - intel_encoder->disable = g4x_disable_dp; - intel_encoder->post_disable = g4x_post_disable_dp; - } - - if ((IS_IVYBRIDGE(dev_priv) && port == PORT_A) || - (HAS_PCH_CPT(dev_priv) && port != PORT_A)) - dig_port->dp.set_link_train = cpt_set_link_train; - else - dig_port->dp.set_link_train = g4x_set_link_train; - - if (IS_CHERRYVIEW(dev_priv)) - dig_port->dp.set_signal_levels = chv_set_signal_levels; - else if (IS_VALLEYVIEW(dev_priv)) - dig_port->dp.set_signal_levels = vlv_set_signal_levels; - else if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) - dig_port->dp.set_signal_levels = ivb_cpu_edp_set_signal_levels; - else if (IS_GEN(dev_priv, 6) && port == PORT_A) - dig_port->dp.set_signal_levels = snb_cpu_edp_set_signal_levels; - else - dig_port->dp.set_signal_levels = g4x_set_signal_levels; - - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv) || - (HAS_PCH_SPLIT(dev_priv) && port != PORT_A)) { - dig_port->dp.preemph_max = intel_dp_preemph_max_3; - dig_port->dp.voltage_max = intel_dp_voltage_max_3; - } else { - dig_port->dp.preemph_max = intel_dp_preemph_max_2; - dig_port->dp.voltage_max = intel_dp_voltage_max_2; - } - - dig_port->dp.output_reg = output_reg; - dig_port->max_lanes = 4; - - intel_encoder->type = INTEL_OUTPUT_DP; - intel_encoder->power_domain = intel_port_to_power_domain(port); - if (IS_CHERRYVIEW(dev_priv)) { - if (port == PORT_D) - intel_encoder->pipe_mask = BIT(PIPE_C); - else - intel_encoder->pipe_mask = BIT(PIPE_A) | BIT(PIPE_B); - } else { - intel_encoder->pipe_mask = ~0; - } - intel_encoder->cloneable = 0; - intel_encoder->port = port; - intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); - - dig_port->hpd_pulse = intel_dp_hpd_pulse; - - if (HAS_GMCH(dev_priv)) { - if (IS_GM45(dev_priv)) - dig_port->connected = gm45_digital_port_connected; - else - dig_port->connected = g4x_digital_port_connected; - } else { - if (port == PORT_A) - dig_port->connected = ilk_digital_port_connected; - else - dig_port->connected = ibx_digital_port_connected; - } - - if (port != PORT_A) - intel_infoframe_init(dig_port); - - dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port); - if (!intel_dp_init_connector(dig_port, intel_connector)) - goto err_init_connector; - - return true; - -err_init_connector: - drm_encoder_cleanup(encoder); -err_encoder_init: - kfree(intel_connector); -err_connector_alloc: - kfree(dig_port); - return false; -} - void intel_dp_mst_suspend(struct drm_i915_private *dev_priv) { struct intel_encoder *encoder; |