From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Imre Deak <imre.deak@intel.com>
Cc: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH v2] drm/i915: Add a DP1.2 compatible way to read LTTPR capabilities
Date: Tue, 22 Mar 2022 19:31:17 +0200 [thread overview]
Message-ID: <YjoH5UbXwKmSEeEy@intel.com> (raw)
In-Reply-To: <20220322143844.42616-1-imre.deak@intel.com>
On Tue, Mar 22, 2022 at 04:38:44PM +0200, Imre Deak wrote:
> At least some DELL monitors (P2715Q) with DPCD_REV 1.2 return corrupted
> DPCD register values when reading from the 0xF0000- LTTPR range with an
> AUX transaction block size bigger than 1. The DP standard requires 0 to
> be returned - as for any other reserved/invalid addresses - but these
> monitors return the DPCD_REV register value repeated in each byte of the
> read buffer. This will in turn corrupt the values returned by the LTTPRs
> between the source and the monitor: LTTPRs must adjust the values they
> read from the downstream DPRX, for instance left-shift/init the
> downstream DP_PHY_REPEATER_CNT value. Since the value returned by the
> monitor's DPRX is non-zero the adjusted values will be corrupt.
>
> Reading the LTTPR registers one-by-one instead of reading all of them
> with a single AUX transfer works around the issue.
>
> According to the DP standard's 0xF0000 register description:
> "LTTPR-related registers at DPCD Addresses F0000h through F02FFh are
> valid only for DPCD r1.4 (or higher)." While it's unclear if DPCD r1.4
> refers to the DPCD_REV or to the
> LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV register (tickets filed
> at the VESA site to clarify this haven't been addressed), one
> possibility is that it's a restriction due to non-compliant monitors
> described above. Disabling the non-transparent LTTPR mode for all such
> monitors is not a viable solution: the transparent LTTPR mode has its
> own issue causing link training failures and this would affect a lot of
> monitors in use with DPCD_REV < 1.4. Instead this patch works around
> the problem by reading the LTTPR common and PHY cap registers one-by-one
> for any monitor with a DPCD_REV < 1.4.
>
> The standard requires the DPCD capabilites to be read after the LTTPR
> common capabilities are read, so re-read the DPCD capabilities after
> the LTTPR common and PHY caps were read out.
>
> v2:
> - Use for instead of a while loop. (Ville)
> - Add to code comment the monitor model with the problem.
>
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4531
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
> drivers/gpu/drm/dp/drm_dp.c | 57 ++++++++++++-------
> .../drm/i915/display/intel_dp_link_training.c | 30 +++++++---
> include/drm/dp/drm_dp_helper.h | 2 +
> 3 files changed, 58 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/gpu/drm/dp/drm_dp.c b/drivers/gpu/drm/dp/drm_dp.c
> index 703972ae14c64..58744f83931af 100644
> --- a/drivers/gpu/drm/dp/drm_dp.c
> +++ b/drivers/gpu/drm/dp/drm_dp.c
> @@ -2390,9 +2390,35 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
> }
> EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
>
> +static int drm_dp_read_lttpr_regs(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE], int address,
> + u8 *buf, int buf_size)
> +{
> + /*
> + * At least the DELL P2715Q monitor with a DPCD_REV < 0x14 returns
> + * corrupted values when reading from the 0xF0000- range with a block
> + * size bigger than 1.
> + */
> + int block_size = dpcd[DP_DPCD_REV] < 0x14 ? 1 : buf_size;
> + int offset;
> + int ret;
> +
> + for (offset = 0; offset < buf_size; offset += block_size) {
> + ret = drm_dp_dpcd_read(aux,
> + address + offset,
> + &buf[offset], block_size);
> + if (ret < 0)
> + return ret;
> +
> + WARN_ON(ret != block_size);
> + }
> +
> + return 0;
> +}
> +
> /**
> * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
> * @aux: DisplayPort AUX channel
> + * @dpcd: DisplayPort configuration data
> * @caps: buffer to return the capability info in
> *
> * Read capabilities common to all LTTPRs.
> @@ -2400,25 +2426,19 @@ EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
> * Returns 0 on success or a negative error code on failure.
> */
> int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> {
> - int ret;
> -
> - ret = drm_dp_dpcd_read(aux,
> - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
> - caps, DP_LTTPR_COMMON_CAP_SIZE);
> - if (ret < 0)
> - return ret;
> -
> - WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
> -
> - return 0;
> + return drm_dp_read_lttpr_regs(aux, dpcd,
> + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
> + caps, DP_LTTPR_COMMON_CAP_SIZE);
> }
> EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
>
> /**
> * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
> * @aux: DisplayPort AUX channel
> + * @dpcd: DisplayPort configuration data
> * @dp_phy: LTTPR PHY to read the capabilities for
> * @caps: buffer to return the capability info in
> *
> @@ -2427,20 +2447,13 @@ EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
> * Returns 0 on success or a negative error code on failure.
> */
> int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> enum drm_dp_phy dp_phy,
> u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> {
> - int ret;
> -
> - ret = drm_dp_dpcd_read(aux,
> - DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
> - caps, DP_LTTPR_PHY_CAP_SIZE);
> - if (ret < 0)
> - return ret;
> -
> - WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
> -
> - return 0;
> + return drm_dp_read_lttpr_regs(aux, dpcd,
> + DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
> + caps, DP_LTTPR_PHY_CAP_SIZE);
> }
> EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> index 5d98773efd1b3..fbee20a76cf44 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> @@ -55,6 +55,7 @@ static u8 *intel_dp_lttpr_phy_caps(struct intel_dp *intel_dp,
> }
>
> static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> enum drm_dp_phy dp_phy)
> {
> struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> @@ -63,7 +64,7 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
>
> intel_dp_phy_name(dp_phy, phy_name, sizeof(phy_name));
>
> - if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dp_phy, phy_caps) < 0) {
> + if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dpcd, dp_phy, phy_caps) < 0) {
> drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
> "[ENCODER:%d:%s][%s] failed to read the PHY caps\n",
> encoder->base.base.id, encoder->base.name, phy_name);
> @@ -77,10 +78,11 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
> phy_caps);
> }
>
> -static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
> +static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> {
> struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> + int ret;
>
> if (intel_dp_is_edp(intel_dp))
> return false;
> @@ -92,8 +94,9 @@ static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
> if (DISPLAY_VER(i915) < 10 || IS_GEMINILAKE(i915))
> return false;
>
> - if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
> - intel_dp->lttpr_common_caps) < 0)
> + ret = drm_dp_read_lttpr_common_caps(&intel_dp->aux, dpcd,
> + intel_dp->lttpr_common_caps);
> + if (ret < 0)
> goto reset_caps;
>
> drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
> @@ -122,14 +125,14 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
> return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
> }
>
> -static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
> +static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> {
> struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> int lttpr_count;
> int i;
>
> - if (!intel_dp_read_lttpr_common_caps(intel_dp))
> + if (!intel_dp_read_lttpr_common_caps(intel_dp, dpcd))
> return 0;
>
> lttpr_count = drm_dp_lttpr_count(intel_dp->lttpr_common_caps);
> @@ -168,7 +171,7 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
> }
>
> for (i = 0; i < lttpr_count; i++)
> - intel_dp_read_lttpr_phy_caps(intel_dp, DP_PHY_LTTPR(i));
> + intel_dp_read_lttpr_phy_caps(intel_dp, dpcd, DP_PHY_LTTPR(i));
>
> return lttpr_count;
> }
> @@ -193,9 +196,18 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
> */
> int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
> {
> - int lttpr_count = intel_dp_init_lttpr(intel_dp);
> + u8 dpcd[DP_RECEIVER_CAP_SIZE];
> + int lttpr_count;
>
> - /* The DPTX shall read the DPRX caps after LTTPR detection. */
> + if (drm_dp_read_dpcd_caps(&intel_dp->aux, dpcd))
> + return -EIO;
> +
> + lttpr_count = intel_dp_init_lttpr(intel_dp, dpcd);
> +
> + /*
> + * The DPTX shall read the DPRX caps after LTTPR detection, so re-read
> + * it here.
> + */
> if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) {
> intel_dp_reset_lttpr_common_caps(intel_dp);
> return -EIO;
> diff --git a/include/drm/dp/drm_dp_helper.h b/include/drm/dp/drm_dp_helper.h
> index 51e02cf75277e..1eccd97419436 100644
> --- a/include/drm/dp/drm_dp_helper.h
> +++ b/include/drm/dp/drm_dp_helper.h
> @@ -2148,8 +2148,10 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
> int drm_dp_read_sink_count(struct drm_dp_aux *aux);
>
> int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> enum drm_dp_phy dp_phy,
> u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]);
> --
> 2.30.2
--
Ville Syrjälä
Intel
WARNING: multiple messages have this Message-ID (diff)
From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Imre Deak <imre.deak@intel.com>
Cc: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v2] drm/i915: Add a DP1.2 compatible way to read LTTPR capabilities
Date: Tue, 22 Mar 2022 19:31:17 +0200 [thread overview]
Message-ID: <YjoH5UbXwKmSEeEy@intel.com> (raw)
In-Reply-To: <20220322143844.42616-1-imre.deak@intel.com>
On Tue, Mar 22, 2022 at 04:38:44PM +0200, Imre Deak wrote:
> At least some DELL monitors (P2715Q) with DPCD_REV 1.2 return corrupted
> DPCD register values when reading from the 0xF0000- LTTPR range with an
> AUX transaction block size bigger than 1. The DP standard requires 0 to
> be returned - as for any other reserved/invalid addresses - but these
> monitors return the DPCD_REV register value repeated in each byte of the
> read buffer. This will in turn corrupt the values returned by the LTTPRs
> between the source and the monitor: LTTPRs must adjust the values they
> read from the downstream DPRX, for instance left-shift/init the
> downstream DP_PHY_REPEATER_CNT value. Since the value returned by the
> monitor's DPRX is non-zero the adjusted values will be corrupt.
>
> Reading the LTTPR registers one-by-one instead of reading all of them
> with a single AUX transfer works around the issue.
>
> According to the DP standard's 0xF0000 register description:
> "LTTPR-related registers at DPCD Addresses F0000h through F02FFh are
> valid only for DPCD r1.4 (or higher)." While it's unclear if DPCD r1.4
> refers to the DPCD_REV or to the
> LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV register (tickets filed
> at the VESA site to clarify this haven't been addressed), one
> possibility is that it's a restriction due to non-compliant monitors
> described above. Disabling the non-transparent LTTPR mode for all such
> monitors is not a viable solution: the transparent LTTPR mode has its
> own issue causing link training failures and this would affect a lot of
> monitors in use with DPCD_REV < 1.4. Instead this patch works around
> the problem by reading the LTTPR common and PHY cap registers one-by-one
> for any monitor with a DPCD_REV < 1.4.
>
> The standard requires the DPCD capabilites to be read after the LTTPR
> common capabilities are read, so re-read the DPCD capabilities after
> the LTTPR common and PHY caps were read out.
>
> v2:
> - Use for instead of a while loop. (Ville)
> - Add to code comment the monitor model with the problem.
>
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4531
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
> drivers/gpu/drm/dp/drm_dp.c | 57 ++++++++++++-------
> .../drm/i915/display/intel_dp_link_training.c | 30 +++++++---
> include/drm/dp/drm_dp_helper.h | 2 +
> 3 files changed, 58 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/gpu/drm/dp/drm_dp.c b/drivers/gpu/drm/dp/drm_dp.c
> index 703972ae14c64..58744f83931af 100644
> --- a/drivers/gpu/drm/dp/drm_dp.c
> +++ b/drivers/gpu/drm/dp/drm_dp.c
> @@ -2390,9 +2390,35 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
> }
> EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
>
> +static int drm_dp_read_lttpr_regs(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE], int address,
> + u8 *buf, int buf_size)
> +{
> + /*
> + * At least the DELL P2715Q monitor with a DPCD_REV < 0x14 returns
> + * corrupted values when reading from the 0xF0000- range with a block
> + * size bigger than 1.
> + */
> + int block_size = dpcd[DP_DPCD_REV] < 0x14 ? 1 : buf_size;
> + int offset;
> + int ret;
> +
> + for (offset = 0; offset < buf_size; offset += block_size) {
> + ret = drm_dp_dpcd_read(aux,
> + address + offset,
> + &buf[offset], block_size);
> + if (ret < 0)
> + return ret;
> +
> + WARN_ON(ret != block_size);
> + }
> +
> + return 0;
> +}
> +
> /**
> * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
> * @aux: DisplayPort AUX channel
> + * @dpcd: DisplayPort configuration data
> * @caps: buffer to return the capability info in
> *
> * Read capabilities common to all LTTPRs.
> @@ -2400,25 +2426,19 @@ EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
> * Returns 0 on success or a negative error code on failure.
> */
> int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> {
> - int ret;
> -
> - ret = drm_dp_dpcd_read(aux,
> - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
> - caps, DP_LTTPR_COMMON_CAP_SIZE);
> - if (ret < 0)
> - return ret;
> -
> - WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
> -
> - return 0;
> + return drm_dp_read_lttpr_regs(aux, dpcd,
> + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
> + caps, DP_LTTPR_COMMON_CAP_SIZE);
> }
> EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
>
> /**
> * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
> * @aux: DisplayPort AUX channel
> + * @dpcd: DisplayPort configuration data
> * @dp_phy: LTTPR PHY to read the capabilities for
> * @caps: buffer to return the capability info in
> *
> @@ -2427,20 +2447,13 @@ EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
> * Returns 0 on success or a negative error code on failure.
> */
> int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> enum drm_dp_phy dp_phy,
> u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> {
> - int ret;
> -
> - ret = drm_dp_dpcd_read(aux,
> - DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
> - caps, DP_LTTPR_PHY_CAP_SIZE);
> - if (ret < 0)
> - return ret;
> -
> - WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
> -
> - return 0;
> + return drm_dp_read_lttpr_regs(aux, dpcd,
> + DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
> + caps, DP_LTTPR_PHY_CAP_SIZE);
> }
> EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> index 5d98773efd1b3..fbee20a76cf44 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> @@ -55,6 +55,7 @@ static u8 *intel_dp_lttpr_phy_caps(struct intel_dp *intel_dp,
> }
>
> static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> enum drm_dp_phy dp_phy)
> {
> struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> @@ -63,7 +64,7 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
>
> intel_dp_phy_name(dp_phy, phy_name, sizeof(phy_name));
>
> - if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dp_phy, phy_caps) < 0) {
> + if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dpcd, dp_phy, phy_caps) < 0) {
> drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
> "[ENCODER:%d:%s][%s] failed to read the PHY caps\n",
> encoder->base.base.id, encoder->base.name, phy_name);
> @@ -77,10 +78,11 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
> phy_caps);
> }
>
> -static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
> +static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> {
> struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> + int ret;
>
> if (intel_dp_is_edp(intel_dp))
> return false;
> @@ -92,8 +94,9 @@ static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
> if (DISPLAY_VER(i915) < 10 || IS_GEMINILAKE(i915))
> return false;
>
> - if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
> - intel_dp->lttpr_common_caps) < 0)
> + ret = drm_dp_read_lttpr_common_caps(&intel_dp->aux, dpcd,
> + intel_dp->lttpr_common_caps);
> + if (ret < 0)
> goto reset_caps;
>
> drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
> @@ -122,14 +125,14 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
> return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
> }
>
> -static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
> +static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> {
> struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> int lttpr_count;
> int i;
>
> - if (!intel_dp_read_lttpr_common_caps(intel_dp))
> + if (!intel_dp_read_lttpr_common_caps(intel_dp, dpcd))
> return 0;
>
> lttpr_count = drm_dp_lttpr_count(intel_dp->lttpr_common_caps);
> @@ -168,7 +171,7 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
> }
>
> for (i = 0; i < lttpr_count; i++)
> - intel_dp_read_lttpr_phy_caps(intel_dp, DP_PHY_LTTPR(i));
> + intel_dp_read_lttpr_phy_caps(intel_dp, dpcd, DP_PHY_LTTPR(i));
>
> return lttpr_count;
> }
> @@ -193,9 +196,18 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
> */
> int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
> {
> - int lttpr_count = intel_dp_init_lttpr(intel_dp);
> + u8 dpcd[DP_RECEIVER_CAP_SIZE];
> + int lttpr_count;
>
> - /* The DPTX shall read the DPRX caps after LTTPR detection. */
> + if (drm_dp_read_dpcd_caps(&intel_dp->aux, dpcd))
> + return -EIO;
> +
> + lttpr_count = intel_dp_init_lttpr(intel_dp, dpcd);
> +
> + /*
> + * The DPTX shall read the DPRX caps after LTTPR detection, so re-read
> + * it here.
> + */
> if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) {
> intel_dp_reset_lttpr_common_caps(intel_dp);
> return -EIO;
> diff --git a/include/drm/dp/drm_dp_helper.h b/include/drm/dp/drm_dp_helper.h
> index 51e02cf75277e..1eccd97419436 100644
> --- a/include/drm/dp/drm_dp_helper.h
> +++ b/include/drm/dp/drm_dp_helper.h
> @@ -2148,8 +2148,10 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
> int drm_dp_read_sink_count(struct drm_dp_aux *aux);
>
> int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> + const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> enum drm_dp_phy dp_phy,
> u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]);
> --
> 2.30.2
--
Ville Syrjälä
Intel
next prev parent reply other threads:[~2022-03-22 17:36 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-02-28 20:12 [Intel-gfx] [PATCH] drm/i915: Add a DP1.2 compatible way to read LTTPR capabilities Imre Deak
2022-02-28 20:12 ` Imre Deak
2022-03-01 0:35 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for " Patchwork
2022-03-01 1:08 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-03-01 14:14 ` [Intel-gfx] [PATCH] " Ville Syrjälä
2022-03-01 14:14 ` Ville Syrjälä
2022-03-01 18:14 ` [Intel-gfx] " Imre Deak
2022-03-01 18:14 ` Imre Deak
2022-03-01 18:24 ` [Intel-gfx] " Ville Syrjälä
2022-03-01 18:24 ` Ville Syrjälä
2022-03-22 14:38 ` [Intel-gfx] [PATCH v2] " Imre Deak
2022-03-22 14:38 ` Imre Deak
2022-03-22 17:31 ` Ville Syrjälä [this message]
2022-03-22 17:31 ` Ville Syrjälä
2022-03-22 14:48 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Add a DP1.2 compatible way to read LTTPR capabilities (rev2) Patchwork
2022-03-22 14:55 ` [Intel-gfx] ✗ Fi.CI.DOCS: " Patchwork
2022-03-22 15:20 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-03-22 21:50 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YjoH5UbXwKmSEeEy@intel.com \
--to=ville.syrjala@linux.intel.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=imre.deak@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.