summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_dp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dp.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c165
1 files changed, 98 insertions, 67 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 36ab58c25b64..146b83916005 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -46,6 +46,7 @@
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_backlight.h"
+#include "intel_combo_phy_regs.h"
#include "intel_connector.h"
#include "intel_crtc.h"
#include "intel_ddi.h"
@@ -72,8 +73,6 @@
#include "intel_vdsc.h"
#include "intel_vrr.h"
-#define DP_DPRX_ESI_LEN 14
-
/* DP DSC throughput values used for slice count calculations KPixels/s */
#define DP_DSC_PEAK_PIXEL_RATE 2720000
#define DP_DSC_MAX_ENC_THROUGHPUT_0 340000
@@ -705,7 +704,7 @@ 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_DEBUG_KMS("Max big joiner bpp: %u\n", max_bpp_bigjoiner);
+ drm_dbg_kms(&i915->drm, "Max big joiner bpp: %u\n", max_bpp_bigjoiner);
bits_per_pixel = min(bits_per_pixel, max_bpp_bigjoiner);
}
@@ -1167,14 +1166,13 @@ static bool intel_dp_hdmi_tmds_clock_valid(struct intel_dp *intel_dp,
return true;
}
-static bool intel_dp_hdmi_deep_color_possible(struct intel_dp *intel_dp,
- const struct intel_crtc_state *crtc_state,
- int bpc)
+static bool intel_dp_hdmi_bpc_possible(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state,
+ int bpc)
{
- return intel_hdmi_deep_color_possible(crtc_state, bpc,
- intel_dp->has_hdmi_sink,
- intel_dp_hdmi_ycbcr420(intel_dp, crtc_state)) &&
+ return intel_hdmi_bpc_possible(crtc_state, bpc, intel_dp->has_hdmi_sink,
+ intel_dp_hdmi_ycbcr420(intel_dp, crtc_state)) &&
intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc);
}
@@ -1192,7 +1190,7 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp,
if (intel_dp->dfp.min_tmds_clock) {
for (; bpc >= 10; bpc -= 2) {
- if (intel_dp_hdmi_deep_color_possible(intel_dp, crtc_state, bpc))
+ if (intel_dp_hdmi_bpc_possible(intel_dp, crtc_state, bpc))
break;
}
}
@@ -1897,7 +1895,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
/* FIXME: abstract this better */
if (pipe_config->splitter.enable)
- pipe_config->dp_m_n.gmch_m *= pipe_config->splitter.link_count;
+ pipe_config->dp_m_n.data_m *= pipe_config->splitter.link_count;
if (!HAS_DDI(dev_priv))
g4x_dp_set_clock(encoder, pipe_config);
@@ -2813,11 +2811,22 @@ intel_dp_configure_mst(struct intel_dp *intel_dp)
}
static bool
-intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)
+intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *esi)
{
- return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI,
- sink_irq_vector, DP_DPRX_ESI_LEN) ==
- DP_DPRX_ESI_LEN;
+ return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 4) == 4;
+}
+
+static bool intel_dp_ack_sink_irq_esi(struct intel_dp *intel_dp, u8 esi[4])
+{
+ int retry;
+
+ for (retry = 0; retry < 3; retry++) {
+ if (drm_dp_dpcd_write(&intel_dp->aux, DP_SINK_COUNT_ESI + 1,
+ &esi[1], 3) == 3)
+ return true;
+ }
+
+ return false;
}
bool
@@ -2909,7 +2918,8 @@ out:
}
static ssize_t
-intel_dp_hdr_metadata_infoframe_sdp_pack(const struct hdmi_drm_infoframe *drm_infoframe,
+intel_dp_hdr_metadata_infoframe_sdp_pack(struct drm_i915_private *i915,
+ const struct hdmi_drm_infoframe *drm_infoframe,
struct dp_sdp *sdp,
size_t size)
{
@@ -2925,12 +2935,12 @@ intel_dp_hdr_metadata_infoframe_sdp_pack(const struct hdmi_drm_infoframe *drm_in
len = hdmi_drm_infoframe_pack_only(drm_infoframe, buf, sizeof(buf));
if (len < 0) {
- DRM_DEBUG_KMS("buffer size is smaller than hdr metadata infoframe\n");
+ drm_dbg_kms(&i915->drm, "buffer size is smaller than hdr metadata infoframe\n");
return -ENOSPC;
}
if (len != infoframe_size) {
- DRM_DEBUG_KMS("wrong static hdr metadata size\n");
+ drm_dbg_kms(&i915->drm, "wrong static hdr metadata size\n");
return -ENOSPC;
}
@@ -3003,7 +3013,8 @@ static void intel_write_dp_sdp(struct intel_encoder *encoder,
sizeof(sdp));
break;
case HDMI_PACKET_TYPE_GAMUT_METADATA:
- len = intel_dp_hdr_metadata_infoframe_sdp_pack(&crtc_state->infoframes.drm.drm,
+ len = intel_dp_hdr_metadata_infoframe_sdp_pack(dev_priv,
+ &crtc_state->infoframes.drm.drm,
&sdp, sizeof(sdp));
break;
default:
@@ -3411,22 +3422,22 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp,
switch (data->phy_pattern) {
case DP_PHY_TEST_PATTERN_NONE:
- DRM_DEBUG_KMS("Disable Phy Test Pattern\n");
+ drm_dbg_kms(&dev_priv->drm, "Disable Phy Test Pattern\n");
intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe), 0x0);
break;
case DP_PHY_TEST_PATTERN_D10_2:
- DRM_DEBUG_KMS("Set D10.2 Phy Test Pattern\n");
+ drm_dbg_kms(&dev_priv->drm, "Set D10.2 Phy Test Pattern\n");
intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_D10_2);
break;
case DP_PHY_TEST_PATTERN_ERROR_COUNT:
- DRM_DEBUG_KMS("Set Error Count Phy Test Pattern\n");
+ drm_dbg_kms(&dev_priv->drm, "Set Error Count Phy Test Pattern\n");
intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE |
DDI_DP_COMP_CTL_SCRAMBLED_0);
break;
case DP_PHY_TEST_PATTERN_PRBS7:
- DRM_DEBUG_KMS("Set PRBS7 Phy Test Pattern\n");
+ drm_dbg_kms(&dev_priv->drm, "Set PRBS7 Phy Test Pattern\n");
intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_PRBS7);
break;
@@ -3436,7 +3447,8 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp,
* current firmware of DPR-100 could not set it, so hardcoding
* now for complaince test.
*/
- DRM_DEBUG_KMS("Set 80Bit Custom Phy Test Pattern 0x3e0f83e0 0x0f83e0f8 0x0000f83e\n");
+ drm_dbg_kms(&dev_priv->drm,
+ "Set 80Bit Custom Phy Test Pattern 0x3e0f83e0 0x0f83e0f8 0x0000f83e\n");
pattern_val = 0x3e0f83e0;
intel_de_write(dev_priv, DDI_DP_COMP_PAT(pipe, 0), pattern_val);
pattern_val = 0x0f83e0f8;
@@ -3453,7 +3465,7 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp,
* current firmware of DPR-100 could not set it, so hardcoding
* now for complaince test.
*/
- DRM_DEBUG_KMS("Set HBR2 compliance Phy Test Pattern\n");
+ drm_dbg_kms(&dev_priv->drm, "Set HBR2 compliance Phy Test Pattern\n");
pattern_val = 0xFB;
intel_de_write(dev_priv, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_HBR2 |
@@ -3522,13 +3534,14 @@ intel_dp_autotest_phy_ddi_enable(struct intel_dp *intel_dp,
static void intel_dp_process_phy_request(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct drm_dp_phy_test_params *data =
&intel_dp->compliance.test_data.phytest;
u8 link_status[DP_LINK_STATUS_SIZE];
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX,
link_status) < 0) {
- DRM_DEBUG_KMS("failed to get link status\n");
+ drm_dbg_kms(&i915->drm, "failed to get link status\n");
return;
}
@@ -3553,11 +3566,12 @@ static void intel_dp_process_phy_request(struct intel_dp *intel_dp,
static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct drm_dp_phy_test_params *data =
&intel_dp->compliance.test_data.phytest;
if (drm_dp_get_phy_test_pattern(&intel_dp->aux, data)) {
- DRM_DEBUG_KMS("DP Phy Test pattern AUX read failure\n");
+ drm_dbg_kms(&i915->drm, "DP Phy Test pattern AUX read failure\n");
return DP_TEST_NAK;
}
@@ -3615,14 +3629,43 @@ update_status:
}
static void
-intel_dp_mst_hpd_irq(struct intel_dp *intel_dp, u8 *esi, bool *handled)
+intel_dp_mst_hpd_irq(struct intel_dp *intel_dp, u8 *esi, u8 *ack)
{
- drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, handled);
+ bool handled = false;
- if (esi[1] & DP_CP_IRQ) {
- intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
- *handled = true;
- }
+ drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
+ if (handled)
+ ack[1] |= esi[1] & (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY);
+
+ if (esi[1] & DP_CP_IRQ) {
+ intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
+ ack[1] |= DP_CP_IRQ;
+ }
+}
+
+static bool intel_dp_mst_link_status(struct intel_dp *intel_dp)
+{
+ struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ u8 link_status[DP_LINK_STATUS_SIZE] = {};
+ const size_t esi_link_status_size = DP_LINK_STATUS_SIZE - 2;
+
+ if (drm_dp_dpcd_read(&intel_dp->aux, DP_LANE0_1_STATUS_ESI, link_status,
+ esi_link_status_size) != esi_link_status_size) {
+ drm_err(&i915->drm,
+ "[ENCODER:%d:%s] Failed to read link status\n",
+ encoder->base.base.id, encoder->base.name);
+ return false;
+ }
+
+ if (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) {
+ drm_dbg_kms(&i915->drm,
+ "[ENCODER:%d:%s] channel EQ not ok, retraining\n",
+ encoder->base.base.id, encoder->base.name);
+ return false;
+ }
+
+ return true;
}
/**
@@ -3647,20 +3690,8 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
drm_WARN_ON_ONCE(&i915->drm, intel_dp->active_mst_links < 0);
for (;;) {
- /*
- * The +2 is because DP_DPRX_ESI_LEN is 14, but we then
- * pass in "esi+10" to drm_dp_channel_eq_ok(), which
- * takes a 6-byte array. So we actually need 16 bytes
- * here.
- *
- * Somebody who knows what the limits actually are
- * should check this, but for now this is at least
- * harmless and avoids a valid compiler warning about
- * using more of the array than we have allocated.
- */
- u8 esi[DP_DPRX_ESI_LEN+2] = {};
- bool handled;
- int retry;
+ u8 esi[4] = {};
+ u8 ack[4] = {};
if (!intel_dp_get_sink_irq_esi(intel_dp, esi)) {
drm_dbg_kms(&i915->drm,
@@ -3670,30 +3701,22 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
break;
}
- /* check link status - esi[10] = 0x200c */
+ drm_dbg_kms(&i915->drm, "DPRX ESI: %4ph\n", esi);
+
if (intel_dp->active_mst_links > 0 && link_ok &&
- !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
- drm_dbg_kms(&i915->drm,
- "channel EQ not ok, retraining\n");
- link_ok = false;
+ esi[3] & LINK_STATUS_CHANGED) {
+ if (!intel_dp_mst_link_status(intel_dp))
+ link_ok = false;
+ ack[3] |= LINK_STATUS_CHANGED;
}
- drm_dbg_kms(&i915->drm, "got esi %3ph\n", esi);
+ intel_dp_mst_hpd_irq(intel_dp, esi, ack);
- intel_dp_mst_hpd_irq(intel_dp, esi, &handled);
-
- if (!handled)
+ if (!memchr_inv(ack, 0, sizeof(ack)))
break;
- for (retry = 0; retry < 3; retry++) {
- int wret;
-
- wret = drm_dp_dpcd_write(&intel_dp->aux,
- DP_SINK_COUNT_ESI+1,
- &esi[1], 3);
- if (wret == 3)
- break;
- }
+ if (!intel_dp_ack_sink_irq_esi(intel_dp, ack))
+ drm_dbg_kms(&i915->drm, "Failed to ack ESI\n");
}
return link_ok;
@@ -4974,6 +4997,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
mutex_lock(&dev->mode_config.mutex);
edid = drm_get_edid(connector, &intel_dp->aux.ddc);
+ if (!edid) {
+ /* Fallback to EDID from ACPI OpRegion, if any */
+ edid = intel_opregion_get_edid(intel_connector);
+ if (edid)
+ drm_dbg_kms(&dev_priv->drm,
+ "[CONNECTOR:%d:%s] Using OpRegion EDID\n",
+ connector->base.id, connector->name);
+ }
if (edid) {
if (drm_add_edid_modes(connector, edid)) {
drm_connector_update_edid_property(connector, edid);
@@ -5048,8 +5079,8 @@ static void intel_dp_modeset_retry_work_fn(struct work_struct *work)
intel_connector = container_of(work, typeof(*intel_connector),
modeset_retry_work);
connector = &intel_connector->base;
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
- connector->name);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s]\n", connector->base.id,
+ connector->name);
/* Grab the locks before changing connector property*/
mutex_lock(&connector->dev->mode_config.mutex);