diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 8d8b2f8d37a9..d6600079bcf7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -620,6 +620,12 @@ struct intel_connector { struct intel_dp *mst_port; + struct { + struct drm_dp_aux *dsc_decompression_aux; + u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]; + u8 fec_capability; + } dp; + /* Work struct to schedule a uevent on link train failure */ struct work_struct modeset_retry_work; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index a010e021c48c..857cee5a5be8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3483,7 +3483,8 @@ static void intel_dp_read_dsc_dpcd(struct drm_dp_aux *aux, dsc_dpcd); } -static void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_dp *intel_dp) +static void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_dp *intel_dp, + struct intel_connector *connector) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -3491,32 +3492,46 @@ static void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_dp *intel_dp) * Clear the cached register set to avoid using stale values * for the sinks that do not support DSC. */ - memset(intel_dp->dsc_dpcd, 0, sizeof(intel_dp->dsc_dpcd)); + memset(connector->dp.dsc_dpcd, 0, sizeof(connector->dp.dsc_dpcd)); /* Clear fec_capable to avoid using stale values */ - intel_dp->fec_capable = 0; + connector->dp.fec_capability = 0; if (dpcd_rev < DP_DPCD_REV_14) return; - intel_dp_read_dsc_dpcd(&intel_dp->aux, intel_dp->dsc_dpcd); + intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux, + connector->dp.dsc_dpcd); - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_FEC_CAPABILITY, - &intel_dp->fec_capable) < 0) { + if (drm_dp_dpcd_readb(connector->dp.dsc_decompression_aux, DP_FEC_CAPABILITY, + &connector->dp.fec_capability) < 0) { drm_err(&i915->drm, "Failed to read FEC DPCD register\n"); return; } drm_dbg_kms(&i915->drm, "FEC CAPABILITY: %x\n", - intel_dp->fec_capable); + connector->dp.fec_capability); + + /* + * TODO: remove the following intel_dp copies once all users + * are converted to look up DSC DPCD/FEC capability via the + * connector. + */ + memcpy(intel_dp->dsc_dpcd, connector->dp.dsc_dpcd, + sizeof(intel_dp->dsc_dpcd)); + intel_dp->fec_capable = connector->dp.fec_capability; } -static void intel_edp_get_dsc_sink_cap(u8 edp_dpcd_rev, struct intel_dp *intel_dp) +static void intel_edp_get_dsc_sink_cap(u8 edp_dpcd_rev, struct intel_dp *intel_dp, + struct intel_connector *connector) { if (edp_dpcd_rev < DP_EDP_14) return; - intel_dp_read_dsc_dpcd(&intel_dp->aux, intel_dp->dsc_dpcd); + intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux, connector->dp.dsc_dpcd); + + memcpy(intel_dp->dsc_dpcd, connector->dp.dsc_dpcd, + sizeof(intel_dp->dsc_dpcd)); } static void intel_edp_mso_mode_fixup(struct intel_connector *connector, @@ -3608,7 +3623,7 @@ static void intel_edp_mso_init(struct intel_dp *intel_dp) } static bool -intel_edp_init_dpcd(struct intel_dp *intel_dp) +intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(dp_to_dig_port(intel_dp)->base.base.dev); @@ -3688,7 +3703,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) /* Read the eDP DSC DPCD registers */ if (HAS_DSC(dev_priv)) intel_edp_get_dsc_sink_cap(intel_dp->edp_dpcd[0], - intel_dp); + intel_dp, + connector); /* * If needed, program our source OUI so we can make various Intel-specific AUX services @@ -5357,7 +5373,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) } static void -intel_dp_detect_dsc_caps(struct intel_dp *intel_dp) +intel_dp_detect_dsc_caps(struct intel_dp *intel_dp, struct intel_connector *connector) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -5367,10 +5383,10 @@ intel_dp_detect_dsc_caps(struct intel_dp *intel_dp) if (intel_dp_is_edp(intel_dp)) intel_edp_get_dsc_sink_cap(intel_dp->edp_dpcd[0], - intel_dp); + intel_dp, connector); else intel_dp_get_dsc_sink_cap(intel_dp->dpcd[DP_DPCD_REV], - intel_dp); + intel_dp, connector); } static int @@ -5379,7 +5395,9 @@ intel_dp_detect(struct drm_connector *connector, bool force) { struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector)); + struct intel_connector *intel_connector = + to_intel_connector(connector); + struct intel_dp *intel_dp = intel_attached_dp(intel_connector); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *encoder = &dig_port->base; enum drm_connector_status status; @@ -5402,7 +5420,12 @@ intel_dp_detect(struct drm_connector *connector, if (status == connector_status_disconnected) { memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance)); + /* + * TODO: Remove clearing the DPCD in intel_dp, once all + * user are converted to using the DPCD in connector. + */ memset(intel_dp->dsc_dpcd, 0, sizeof(intel_dp->dsc_dpcd)); + memset(intel_connector->dp.dsc_dpcd, 0, sizeof(intel_connector->dp.dsc_dpcd)); if (intel_dp->is_mst) { drm_dbg_kms(&dev_priv->drm, @@ -5417,7 +5440,7 @@ intel_dp_detect(struct drm_connector *connector, goto out; } - intel_dp_detect_dsc_caps(intel_dp); + intel_dp_detect_dsc_caps(intel_dp, intel_connector); intel_dp_configure_mst(intel_dp); @@ -6002,7 +6025,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_hpd_enable_detection(encoder); /* Cache DPCD and EDID for edp. */ - has_dpcd = intel_edp_init_dpcd(intel_dp); + has_dpcd = intel_edp_init_dpcd(intel_dp, intel_connector); if (!has_dpcd) { /* if this fails, presume the device is a ghost */ @@ -6176,6 +6199,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp); intel_dp_aux_init(intel_dp); + intel_connector->dp.dsc_decompression_aux = &intel_dp->aux; drm_dbg_kms(&dev_priv->drm, "Adding %s connector on [ENCODER:%d:%s]\n",