[Intel-gfx] [PATCH 6/7] drm/i915: Save latest known sink CRC to compensate delayed counter reset.
Rafael Antognolli
rafael.antognolli at intel.com
Tue Jul 28 13:18:46 PDT 2015
On Thu, Jul 23, 2015 at 04:35:49PM -0700, Rodrigo Vivi wrote:
> By Vesa DP 1.2 Spec TEST_CRC_COUNT should be
> "reset to 0 when TEST_SINK bit 0 = 0."
>
> However for some strange reason when PSR is enabled in
> certain platforms this is not true. At least not immediatelly.
>
> So we face cases like this:
>
> first get_sink_crc operation:
> count: 0, crc: 000000000000
> count: 1, crc: c101c101c101
> returned expected crc: c101c101c101
>
> secont get_sink_crc operation:
> count: 1, crc: c101c101c101
> count: 0, crc: 000000000000
> count: 1, crc: 0000c1010000
> should return expected crc: 0000c1010000
>
> But also the reset to 0 should be faster resulting into:
>
> get_sink_crc operation:
> count: 1, crc: c101c101c101
> count: 1, crc: 0000c1010000
> should return expected crc: 0000c1010000
>
> So in order to know that the second one is valid one
> we need to compare the pair (count, crc) with latest (count, crc).
>
> If the pair changed you have your valid CRC.
>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi at intel.com>
We discussed this before, unfortunately I don't see any other way to do
this, since there is no way to know that the crc count really restarted,
became 0 and then 1 again. So I think this workaround is needed.
Reviewed-by: Rafael Antognolli <rafael.antognolli at intel.com>
> ---
> drivers/gpu/drm/i915/intel_dp.c | 42 +++++++++++++++++++++++++---------------
> drivers/gpu/drm/i915/intel_drv.h | 8 +++++++-
> 2 files changed, 33 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 3ba031d..c7372a1 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3978,7 +3978,7 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
> goto out;
> }
>
> - intel_dp->sink_crc_started = false;
> + intel_dp->sink_crc.started = false;
> out:
> hsw_enable_ips(intel_crtc);
> return ret;
> @@ -3991,7 +3991,7 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
> u8 buf;
> int ret;
>
> - if (intel_dp->sink_crc_started) {
> + if (intel_dp->sink_crc.started) {
> ret = intel_dp_sink_crc_stop(intel_dp);
> if (ret)
> return ret;
> @@ -4003,6 +4003,8 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
> if (!(buf & DP_TEST_CRC_SUPPORTED))
> return -ENOTTY;
>
> + intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK;
> +
> if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0)
> return -EIO;
>
> @@ -4014,7 +4016,7 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
> return -EIO;
> }
>
> - intel_dp->sink_crc_started = true;
> + intel_dp->sink_crc.started = true;
> return 0;
> }
>
> @@ -4024,29 +4026,39 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
> struct drm_device *dev = dig_port->base.base.dev;
> struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
> u8 buf;
> - int test_crc_count;
> + int count, ret;
> int attempts = 6;
> - int ret;
>
> ret = intel_dp_sink_crc_start(intel_dp);
> if (ret)
> return ret;
>
> - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) {
> - ret = -EIO;
> - goto stop;
> - }
> -
> - test_crc_count = buf & DP_TEST_COUNT_MASK;
> -
> do {
> + intel_wait_for_vblank(dev, intel_crtc->pipe);
> +
> if (drm_dp_dpcd_readb(&intel_dp->aux,
> DP_TEST_SINK_MISC, &buf) < 0) {
> ret = -EIO;
> goto stop;
> }
> - intel_wait_for_vblank(dev, intel_crtc->pipe);
> - } while (--attempts && (buf & DP_TEST_COUNT_MASK) == test_crc_count);
> + count = buf & DP_TEST_COUNT_MASK;
> + /*
> + * Count might be reset during the loop. In this case
> + * last known count needs to be reset as well.
> + */
> + if (count == 0)
> + intel_dp->sink_crc.last_count = 0;
> +
> + if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
> + ret = -EIO;
> + goto stop;
> + }
> + } while (--attempts && (count == 0 || (count == intel_dp->sink_crc.last_count &&
> + !memcmp(intel_dp->sink_crc.last_crc, crc,
> + 6 * sizeof(u8)))));
> +
> + intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK;
> + memcpy(intel_dp->sink_crc.last_crc, crc, 6 * sizeof(u8));
>
> if (attempts == 0) {
> DRM_DEBUG_KMS("Panel is unable to calculate CRC after 6 vblanks\n");
> @@ -4054,8 +4066,6 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
> goto stop;
> }
>
> - if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0)
> - ret = -EIO;
> stop:
> intel_dp_sink_crc_stop(intel_dp);
> return ret;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index cc74400..c072820 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -697,6 +697,12 @@ enum link_m_n_set {
> M2_N2
> };
>
> +struct sink_crc {
> + bool started;
> + u8 last_crc[6];
> + int last_count;
> +};
> +
> struct intel_dp {
> uint32_t output_reg;
> uint32_t aux_ch_ctl_reg;
> @@ -714,7 +720,7 @@ struct intel_dp {
> /* sink rates as reported by DP_SUPPORTED_LINK_RATES */
> uint8_t num_sink_rates;
> int sink_rates[DP_MAX_SUPPORTED_RATES];
> - bool sink_crc_started;
> + struct sink_crc sink_crc;
> struct drm_dp_aux aux;
> uint8_t train_set[4];
> int panel_power_up_delay;
> --
> 2.1.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
More information about the Intel-gfx
mailing list