diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_dp.c | 126 |
1 files changed, 99 insertions, 27 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 7c96088d80c7..32292c0be2bd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -389,13 +389,23 @@ static int dg2_max_source_rate(struct intel_dp *intel_dp) return intel_dp_is_edp(intel_dp) ? 810000 : 1350000; } +static bool is_low_voltage_sku(struct drm_i915_private *i915, enum phy phy) +{ + u32 voltage; + + voltage = intel_de_read(i915, ICL_PORT_COMP_DW3(phy)) & VOLTAGE_INFO_MASK; + + return voltage == VOLTAGE_INFO_0_85V; +} + static int icl_max_source_rate(struct intel_dp *intel_dp) { 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); enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port); - if (intel_phy_is_combo(dev_priv, phy) && !intel_dp_is_edp(intel_dp)) + if (intel_phy_is_combo(dev_priv, phy) && + (is_low_voltage_sku(dev_priv, phy) || !intel_dp_is_edp(intel_dp))) return 540000; return 810000; @@ -403,12 +413,48 @@ static int icl_max_source_rate(struct intel_dp *intel_dp) static int ehl_max_source_rate(struct intel_dp *intel_dp) { - if (intel_dp_is_edp(intel_dp)) + 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); + enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port); + + if (intel_dp_is_edp(intel_dp) || is_low_voltage_sku(dev_priv, phy)) return 540000; return 810000; } +static int dg1_max_source_rate(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); + + if (intel_phy_is_combo(i915, phy) && is_low_voltage_sku(i915, phy)) + return 540000; + + return 810000; +} + +static int vbt_max_link_rate(struct intel_dp *intel_dp) +{ + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + int max_rate; + + max_rate = intel_bios_dp_max_link_rate(encoder); + + if (intel_dp_is_edp(intel_dp)) { + struct intel_connector *connector = intel_dp->attached_connector; + int edp_max_rate = connector->panel.vbt.edp.max_link_rate; + + if (max_rate && edp_max_rate) + max_rate = min(max_rate, edp_max_rate); + else if (edp_max_rate) + max_rate = edp_max_rate; + } + + return max_rate; +} + static void intel_dp_set_source_rates(struct intel_dp *intel_dp) { @@ -430,7 +476,6 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) 162000, 270000 }; struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct intel_encoder *encoder = &dig_port->base; struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); const int *source_rates; int size, max_rate = 0, vbt_max_rate; @@ -446,7 +491,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) max_rate = dg2_max_source_rate(intel_dp); else if (IS_ALDERLAKE_P(dev_priv) || IS_ALDERLAKE_S(dev_priv) || IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) - max_rate = 810000; + max_rate = dg1_max_source_rate(intel_dp); else if (IS_JSL_EHL(dev_priv)) max_rate = ehl_max_source_rate(intel_dp); else @@ -466,7 +511,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) size = ARRAY_SIZE(g4x_rates); } - vbt_max_rate = intel_bios_dp_max_link_rate(encoder); + vbt_max_rate = vbt_max_link_rate(intel_dp); if (max_rate && vbt_max_rate) max_rate = min(max_rate, vbt_max_rate); else if (vbt_max_rate) @@ -659,7 +704,6 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, */ bits_per_pixel = (link_clock * lane_count * 8) / intel_dp_mode_to_fec_clock(mode_clock); - drm_dbg_kms(&i915->drm, "Max link bpp: %u\n", bits_per_pixel); /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / @@ -668,9 +712,6 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, if (bigjoiner) max_bpp_small_joiner_ram *= 2; - drm_dbg_kms(&i915->drm, "Max small joiner bpp: %u\n", - max_bpp_small_joiner_ram); - /* * Greatest allowed DSC BPP = MIN (output BPP from available Link BW * check, output bpp from small joiner RAM check) @@ -682,7 +723,6 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, i915->max_cdclk_freq * 48 / intel_dp_mode_to_fec_clock(mode_clock); - drm_dbg_kms(&i915->drm, "Max big joiner bpp: %u\n", max_bpp_bigjoiner); bits_per_pixel = min(bits_per_pixel, max_bpp_bigjoiner); } @@ -1221,11 +1261,12 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp, if (intel_dp_is_edp(intel_dp)) { /* Get bpp from vbt only for panels that dont have bpp in edid */ if (intel_connector->base.display_info.bpc == 0 && - dev_priv->vbt.edp.bpp && dev_priv->vbt.edp.bpp < bpp) { + intel_connector->panel.vbt.edp.bpp && + intel_connector->panel.vbt.edp.bpp < bpp) { drm_dbg_kms(&dev_priv->drm, "clamping bpp for eDP panel to BIOS-provided %i\n", - dev_priv->vbt.edp.bpp); - bpp = dev_priv->vbt.edp.bpp; + intel_connector->panel.vbt.edp.bpp); + bpp = intel_connector->panel.vbt.edp.bpp; } } @@ -1881,7 +1922,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, } if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) - pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay; + pipe_config->msa_timing_delay = connector->panel.vbt.edp.drrs_msa_timing_delay; pipe_config->has_drrs = true; @@ -2711,6 +2752,33 @@ static void intel_edp_mso_mode_fixup(struct intel_connector *connector, DRM_MODE_ARG(mode)); } +void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct intel_connector *connector = intel_dp->attached_connector; + + if (connector->panel.vbt.edp.bpp && pipe_bpp > connector->panel.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_bpp, connector->panel.vbt.edp.bpp); + connector->panel.vbt.edp.bpp = pipe_bpp; + } +} + static void intel_edp_mso_init(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -2825,9 +2893,6 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) intel_dp_set_sink_rates(intel_dp); intel_dp_set_max_sink_lane_count(intel_dp); - intel_dp_set_common_rates(intel_dp); - intel_dp_reset_max_link_params(intel_dp); - /* Read the eDP DSC DPCD registers */ if (DISPLAY_VER(dev_priv) >= 10) intel_dp_get_dsc_sink_cap(intel_dp); @@ -4525,7 +4590,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp) edid = intel_dp_get_edid(intel_dp); connector->detect_edid = edid; - vrr_capable = intel_vrr_is_capable(&connector->base); + vrr_capable = intel_vrr_is_capable(connector); drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] VRR capable: %s\n", connector->base.base.id, connector->base.name, str_yes_no(vrr_capable)); drm_connector_set_vrr_capable_property(&connector->base, vrr_capable); @@ -5130,6 +5195,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector = &intel_connector->base; struct drm_display_mode *fixed_mode; + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; bool has_dpcd; enum pipe pipe = INVALID_PIPE; struct edid *edid; @@ -5186,8 +5252,12 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } intel_connector->edid = edid; + intel_bios_init_panel(dev_priv, &intel_connector->panel, + encoder->devdata, IS_ERR(edid) ? NULL : edid); + intel_panel_add_edid_fixed_modes(intel_connector, - dev_priv->vbt.drrs_type != DRRS_TYPE_NONE); + intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE, + intel_vrr_is_capable(intel_connector)); /* MSO requires information from the EDID */ intel_edp_mso_init(intel_dp); @@ -5229,6 +5299,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_edp_add_properties(intel_dp); + intel_pps_init_late(intel_dp); + return true; out_vdd_off: @@ -5309,11 +5381,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, type = DRM_MODE_CONNECTOR_DisplayPort; } - intel_dp_set_source_rates(intel_dp); intel_dp_set_default_sink_rates(intel_dp); intel_dp_set_default_max_sink_lane_count(intel_dp); - intel_dp_set_common_rates(intel_dp); - intel_dp_reset_max_link_params(intel_dp); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp); @@ -5341,16 +5410,19 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, else intel_connector->get_hw_state = intel_connector_get_hw_state; - /* init MST on ports that can support it */ - intel_dp_mst_encoder_init(dig_port, - intel_connector->base.base.id); - if (!intel_edp_init_connector(intel_dp, intel_connector)) { intel_dp_aux_fini(intel_dp); - intel_dp_mst_encoder_cleanup(dig_port); goto fail; } + intel_dp_set_source_rates(intel_dp); + intel_dp_set_common_rates(intel_dp); + intel_dp_reset_max_link_params(intel_dp); + + /* init MST on ports that can support it */ + intel_dp_mst_encoder_init(dig_port, + intel_connector->base.base.id); + intel_dp_add_properties(intel_dp, connector); if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) { |