From patchwork Wed Jan 13 22:09:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Navare, Manasi" X-Patchwork-Id: 12017921 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1EDA3C433E0 for ; Wed, 13 Jan 2021 22:05:46 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C1B8C23382 for ; Wed, 13 Jan 2021 22:05:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C1B8C23382 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2C5F86EC7B; Wed, 13 Jan 2021 22:05:41 +0000 (UTC) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by gabe.freedesktop.org (Postfix) with ESMTPS id A8CAC6EC78 for ; Wed, 13 Jan 2021 22:05:34 +0000 (UTC) IronPort-SDR: +PZ06LL2uNjrtNvCH3s3Gj+zX172w6n/+f/a2UskYveGZ1/hC8jgmdbCOssAyb+Yw7Zabh57JQ L/dY5d6kKBAA== X-IronPort-AV: E=McAfee;i="6000,8403,9863"; a="239817538" X-IronPort-AV: E=Sophos;i="5.79,345,1602572400"; d="scan'208";a="239817538" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Jan 2021 14:05:33 -0800 IronPort-SDR: 0IiFd4Ac4N87xZkiLh6wVSkRrnEcs/yT9ZdHl9tgcJ7L2S9t3BjY8i4O0/9+v/dy0gssQHYMrT gPksHoGNY1jA== X-IronPort-AV: E=Sophos;i="5.79,345,1602572400"; d="scan'208";a="400696586" Received: from labuser-z97x-ud5h.jf.intel.com ([10.165.21.211]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 13 Jan 2021 14:05:33 -0800 From: Manasi Navare To: intel-gfx@lists.freedesktop.org Date: Wed, 13 Jan 2021 14:09:34 -0800 Message-Id: <20210113220935.4151-18-manasi.d.navare@intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20210113220935.4151-1-manasi.d.navare@intel.com> References: <20210113220935.4151-1-manasi.d.navare@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v4 17/18] drm/i915: Fix vblank timestamps with VRR X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä To get sensible vblank timestamping behaviour we need to feed the vmax based timings to the vblank code, otherwise it'll chop off the scanline counter when it exceeds the minumum vtotal. Additionally with VRR we have three cases to consider when we generate the vblank timestamp: 1) we are in vertical active -> nothing special needs to be done, just return the current scanout position and the core will calculate the timestamp corresponding to the past time when the current vertical active started 2) we are in vertical blank and no push has been sent -> the hardware will keep extending the vblank presumably to its maximum length, so we make the timestmap match the expected time when the max length vblank will end. Since the timings used for this are now based on vmax nothing special actually needs to be done 3) we are in vblank and a push has been sent so the vblank is about to terminate -> presumably we want the timestmap to accurately reflect when the vblank will terminate, so we use the sampled frame timestamp vs. current timestamp to guesstimate how far along the vblank exit we are, and then we adjust the reported scanout position accordingly so that the core will see that the vblank is close to ending. Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_display.c | 17 ++++++++++++----- .../gpu/drm/i915/display/intel_display_types.h | 4 ++++ drivers/gpu/drm/i915/display/intel_vrr.c | 4 ++++ drivers/gpu/drm/i915/i915_irq.c | 15 ++++++++++++++- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4ed279f034be..d989baa44c37 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -13835,10 +13835,17 @@ intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + struct drm_display_mode adjusted_mode = + crtc_state->hw.adjusted_mode; + + if (crtc_state->vrr.enable) { + adjusted_mode.crtc_vtotal = crtc_state->vrr.vmax; + adjusted_mode.crtc_vblank_end = crtc_state->vrr.vmax; + adjusted_mode.crtc_vblank_start = intel_vrr_vmin_vblank_start(crtc_state); + crtc->vmax_vblank_start = intel_vrr_vmax_vblank_start(crtc_state); + } - drm_calc_timestamping_constants(&crtc->base, adjusted_mode); + drm_calc_timestamping_constants(&crtc->base, &adjusted_mode); crtc->mode_flags = crtc_state->mode_flags; @@ -13872,8 +13879,8 @@ intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state) if (IS_GEN(dev_priv, 2)) { int vtotal; - vtotal = adjusted_mode->crtc_vtotal; - if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) + vtotal = adjusted_mode.crtc_vtotal; + if (adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) vtotal /= 2; crtc->scanline_offset = vtotal - 1; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index aa0842028414..3fee613617f1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -679,6 +679,8 @@ struct intel_crtc_scaler_state { #define I915_MODE_FLAG_DSI_USE_TE1 (1<<4) /* Flag to indicate mipi dsi periodic command mode where we do not get TE */ #define I915_MODE_FLAG_DSI_PERIODIC_CMD_MODE (1<<5) +/* Do tricks to make vblank timestamps sane with VRR? */ +#define I915_MODE_FLAG_VRR (1<<6) struct intel_wm_level { bool enable; @@ -1186,6 +1188,8 @@ struct intel_crtc { /* I915_MODE_FLAG_* */ u8 mode_flags; + u16 vmax_vblank_start; + struct intel_display_power_domain_set enabled_power_domains; struct intel_overlay *overlay; diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 9a18c36e4a9a..a494d3ecb1b5 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -134,6 +134,8 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, */ crtc_state->vrr.pipeline_full = min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - 4 - 1); + + crtc_state->mode_flags |= I915_MODE_FLAG_VRR; } void intel_vrr_enable(struct intel_encoder *encoder, @@ -202,4 +204,6 @@ void intel_vrr_get_config(struct intel_crtc *crtc, crtc_state->vrr.flipline = intel_de_read(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder)) + 1; crtc_state->vrr.vmax = intel_de_read(dev_priv, TRANS_VRR_VMAX(cpu_transcoder)) + 1; crtc_state->vrr.vmin = intel_de_read(dev_priv, TRANS_VRR_VMIN(cpu_transcoder)) + 1; + + crtc_state->mode_flags |= I915_MODE_FLAG_VRR; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8505ceca87d5..e81afcb2f43e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -893,7 +893,20 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, if (stime) *stime = ktime_get(); - if (use_scanline_counter) { + if (crtc->mode_flags & I915_MODE_FLAG_VRR) { + int scanlines = intel_crtc_scanlines_since_frame_timestamp(crtc); + + position = __intel_get_crtc_scanline(crtc); + + /* + * Already exiting vblank? If so, shift our position + * so it looks like we're already apporaching the full + * vblank end. This should make the generated timestamp + * more or less match when the active portion will start. + */ + if (position >= vbl_start && scanlines < position) + position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); + } if (use_scanline_counter) { /* No obvious pixelcount register. Only query vertical * scanout position from Display scan line register. */