From patchwork Thu Apr 21 19:22:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Souza, Jose" X-Patchwork-Id: 12822298 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 3A0FEC433EF for ; Thu, 21 Apr 2022 19:20:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 409E910E9F7; Thu, 21 Apr 2022 19:20:39 +0000 (UTC) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTPS id E6FB510E04A; Thu, 21 Apr 2022 19:20:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650568837; x=1682104837; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=CGdOFRfAMc0SJu4v7yKKNts+r8x0fRsVEnF2W8MnEGg=; b=LDMw2t9+2i5oysiJMUCS8iKzFeTEILSXatbUvRAhkNtvZXdvM4cURMxo 31qaebpkAyBVPh6SDm/RV35TZaySVVuXftkJtG1vMnekGPjAnGOtEnd/H hl8H1/EHf2eXAR/KMTHr5AboGOiWs4W5YTpcmtqYAEjE4/4zdCBW8Xrse K+ipUUxk41SkeUVxyyKtF4zI421WybREcnFISGR/7vZ+hrDsoMiyaAE+K GiW/ixlLZbClER1AjOpHr2wFh89mu02gcDKOAwBISOhnTfUAd01PJfJ+4 Fqzr3tjWoz4wGjehKJf0ZQeAYrvkz8iXI0PgK0X/ktRHICIB/vQJS+cHS A==; X-IronPort-AV: E=McAfee;i="6400,9594,10324"; a="251776734" X-IronPort-AV: E=Sophos;i="5.90,279,1643702400"; d="scan'208";a="251776734" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Apr 2022 12:20:37 -0700 X-IronPort-AV: E=Sophos;i="5.90,279,1643702400"; d="scan'208";a="533556663" Received: from josouza-mobl2.fso.intel.com ([10.230.18.139]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Apr 2022 12:20:34 -0700 From: =?utf-8?q?Jos=C3=A9_Roberto_de_Souza?= To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Date: Thu, 21 Apr 2022 12:22:03 -0700 Message-Id: <20220421192205.32649-1-jose.souza@intel.com> X-Mailer: git-send-email 2.36.0 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 1/3] drm: Add infrastructure to allow seamless mode switches 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: , Cc: Sean Paul Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Intel hardware supports change between modes with different refresh rates without any glitches or visual artifacts, that feature is called seamless DRRS. So far i915 driver was automatically changing between preferred panel mode and lower refresh rate mode based on idleness but ChromeOS compositor team is requesting to be in control of the mode switch. So for a certain types of content it can switch to mode with a lower refresh rate without user noticing a thing and saving power. This seamless mode switch will be triggered when user-space dispatch a atomic commit with the new mode and clears the DRM_MODE_ATOMIC_ALLOW_MODESET flag. A driver that don't implement atomic_seamless_mode_switch_check function will continue to fail in the atomic check phase with "[CRTC:%d:%s] requires full modeset" debug message. While a driver that implements it and support the seamless change between old and new mode will return 0 otherwise it should return the appropried errno. So here adding basic drm infrastructure to that be supported by i915 and other drivers. Cc: Vidya Srinivas Cc: Sean Paul Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza Tested-by: Vidya Srinivas --- drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_helper.c | 16 +++++++++++++++ drivers/gpu/drm/drm_atomic_state_helper.c | 1 + include/drm/drm_crtc.h | 25 +++++++++++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 58c0283fb6b0c..21525f9f4b4c1 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -437,6 +437,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p, drm_printf(p, "\tself_refresh_active=%d\n", state->self_refresh_active); drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed); drm_printf(p, "\tmode_changed=%d\n", state->mode_changed); + drm_printf(p, "\tseamless_mode_changed=%d\n", state->seamless_mode_changed); drm_printf(p, "\tactive_changed=%d\n", state->active_changed); drm_printf(p, "\tconnectors_changed=%d\n", state->connectors_changed); drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9603193d2fa13..e6f3a966f7b86 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -631,6 +631,22 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, drm_dbg_atomic(dev, "[CRTC:%d:%s] mode changed\n", crtc->base.id, crtc->name); new_crtc_state->mode_changed = true; + + if (!state->allow_modeset && + crtc->funcs->atomic_seamless_mode_switch_check) { + ret = crtc->funcs->atomic_seamless_mode_switch_check(state, crtc); + if (ret == -EOPNOTSUPP) { + drm_dbg_atomic(dev, "[CRTC:%d:%s] Seamless mode switch not supported\n", + crtc->base.id, crtc->name); + return ret; + } + + if (ret < 0) + return ret; + + new_crtc_state->seamless_mode_changed = true; + new_crtc_state->mode_changed = false; + } } if (old_crtc_state->enable != new_crtc_state->enable) { diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 3b6d3bdbd0996..c093073ea6e11 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -142,6 +142,7 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, if (state->gamma_lut) drm_property_blob_get(state->gamma_lut); state->mode_changed = false; + state->seamless_mode_changed = false; state->active_changed = false; state->planes_changed = false; state->connectors_changed = false; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index a70baea0636ca..b7ce378d679d3 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -140,6 +140,16 @@ struct drm_crtc_state { */ bool mode_changed : 1; + /** + * @seamless_mode_changed: @mode has been changed but user-space + * is requesting to change to the new mode with a fastset and driver + * supports this request. + * To be used by drivers to steer the atomic commit control flow to + * appropriate paths to change mode without any visual corruption. + * Never set together with @mode_changed. + */ + bool seamless_mode_changed : 1; + /** * @active_changed: @active has been toggled. Used by the atomic * helpers and drivers to steer the atomic commit control flow. See also @@ -939,6 +949,21 @@ struct drm_crtc_funcs { int *max_error, ktime_t *vblank_time, bool in_vblank_irq); + + /** + * @atomic_seamless_mode_switch_check + * + * Called when user-space wants to change mode without do a modeset. + * Drivers can optionally support do a mode switch without any visual + * corruption when changing between certain modes. + * + * Returns: + * Zero if possible to seamless switch mode, -EOPNOTSUPP if not + * supported seamless mode change or appropriate errno if an error + * happened. + */ + int (*atomic_seamless_mode_switch_check)(struct drm_atomic_state *state, + struct drm_crtc *crtc); }; /** From patchwork Thu Apr 21 19:22:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Souza, Jose" X-Patchwork-Id: 12822297 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id C0540C433FE for ; Thu, 21 Apr 2022 19:20:39 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 201B210E04A; Thu, 21 Apr 2022 19:20:39 +0000 (UTC) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTPS id 434EA10E04A; Thu, 21 Apr 2022 19:20:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650568838; x=1682104838; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vAnyxfLIOUPHnmSNusUOK5vUe3M9S9hQsZxoFQCK9J0=; b=F/LDu9ZCarmqUkWIamESZ9TpLiwTOTnx8wi1Sq8/jgFRKtryQ+hfQHTn 2pDnGxGvUPXrzthacqIo/HSB5Dq8G+FMVlA3eqCF8Zoe/tKvjjeF7mNl2 WtWVfpFDD5Hdw9J9Nec7VCrUBwVQ3RbPp5ntKnuxC8EhaoZV+YoH3G1Mz pA3tqAfdEiYUtPd6QQgaiT9DTOVhiJ4ECWL6t8cGNaEsIOSsJiKSwXnyf h+h5cqCkl8gHujTCP7+dHsWK1gM629hcLCa6BMgGelVkyGyIrjk8Q2Iuf /rwap6awKgVfBlJr7wG8DW2O+sEzKuj59BDGOjQxZMSnWMc8m4U75zr2w Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10324"; a="251776737" X-IronPort-AV: E=Sophos;i="5.90,279,1643702400"; d="scan'208";a="251776737" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Apr 2022 12:20:38 -0700 X-IronPort-AV: E=Sophos;i="5.90,279,1643702400"; d="scan'208";a="533556669" Received: from josouza-mobl2.fso.intel.com ([10.230.18.139]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Apr 2022 12:20:36 -0700 From: =?utf-8?q?Jos=C3=A9_Roberto_de_Souza?= To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Date: Thu, 21 Apr 2022 12:22:04 -0700 Message-Id: <20220421192205.32649-2-jose.souza@intel.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220421192205.32649-1-jose.souza@intel.com> References: <20220421192205.32649-1-jose.souza@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 2/3] drm/i915/display: Replace crtc_state's has_drrs by drrs_downclock_mode 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: , Cc: Sean Paul Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Will be adding some additional control options to DRRS that will require to have the DRRS downclock mode stored in the crtc_state. So to optimize memory usage a bit here using it to replace has_drrs as we can check if the drrs_downclock_mode pointer is different than null to have the same behavior has has_drrs. Cc: Vidya Srinivas Cc: Sean Paul Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display_types.h | 4 +++- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_drrs.c | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0ddfce21a828d..a5f5caeced9a0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5360,7 +5360,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i, drrs: %i\n", pipe_config->ips_enabled, pipe_config->double_wide, - pipe_config->has_drrs); + CRTC_STATE_HAS_DRRS(pipe_config)); intel_dpll_dump_hw_state(dev_priv, &pipe_config->dpll_hw_state); @@ -7088,7 +7088,7 @@ static void intel_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_stat new_crtc_state->fdi_m_n = old_crtc_state->fdi_m_n; new_crtc_state->dp_m_n = old_crtc_state->dp_m_n; new_crtc_state->dp_m2_n2 = old_crtc_state->dp_m2_n2; - new_crtc_state->has_drrs = old_crtc_state->has_drrs; + new_crtc_state->drrs_downclock_mode = old_crtc_state->drrs_downclock_mode; } static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 452d773fd4e34..f9720562336da 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1096,7 +1096,7 @@ static int i915_drrs_status(struct seq_file *m, void *unused) /* DRRS Supported */ seq_printf(m, "\tDRRS Enabled: %s\n", - str_yes_no(crtc_state->has_drrs)); + str_yes_no(CRTC_STATE_HAS_DRRS(crtc_state))); seq_printf(m, "\tDRRS Active: %s\n", str_yes_no(intel_drrs_is_active(crtc))); @@ -1786,7 +1786,7 @@ static int i915_drrs_ctl_set(void *data, u64 val) crtc_state = to_intel_crtc_state(crtc->base.state); if (!crtc_state->hw.active || - !crtc_state->has_drrs) + !CRTC_STATE_HAS_DRRS(crtc_state)) goto out; commit = crtc_state->uapi.commit; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index cfd042117b109..f0b3cfd3138ce 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1056,7 +1056,7 @@ struct intel_crtc_state { /* m2_n2 for eDP downclock */ struct intel_link_m_n dp_m2_n2; - bool has_drrs; + const struct drm_display_mode *drrs_downclock_mode; /* PSR is supported but might not be enabled due the lack of enabled planes */ bool has_psr; @@ -1264,6 +1264,8 @@ enum drrs_refresh_rate { DRRS_REFRESH_RATE_LOW, }; +#define CRTC_STATE_HAS_DRRS(crtc_state) (!!((crtc_state)->drrs_downclock_mode)) + #define INTEL_PIPE_CRC_ENTRIES_NR 128 struct intel_pipe_crc { spinlock_t lock; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index d55acc4a028a8..feea172dd2753 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1881,7 +1881,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay; - pipe_config->has_drrs = true; + pipe_config->drrs_downclock_mode = downclock_mode; pixel_clock = downclock_mode->clock; if (pipe_config->splitter.enable) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 166caf293f7bc..dd527dfc2d1d5 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -144,7 +144,7 @@ void intel_drrs_activate(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if (!crtc_state->has_drrs) + if (!CRTC_STATE_HAS_DRRS(crtc_state)) return; if (!crtc_state->hw.active) @@ -176,7 +176,7 @@ void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - if (!old_crtc_state->has_drrs) + if (!CRTC_STATE_HAS_DRRS(old_crtc_state)) return; if (!old_crtc_state->hw.active) From patchwork Thu Apr 21 19:22:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Souza, Jose" X-Patchwork-Id: 12822299 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 9E6BEC433FE for ; Thu, 21 Apr 2022 19:20:46 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C949610E9FE; Thu, 21 Apr 2022 19:20:42 +0000 (UTC) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4670010E9FE; Thu, 21 Apr 2022 19:20:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650568840; x=1682104840; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4zJD5o0xz54+cLZ7r+RO+pHT6q8ZtCPoTP/HP9FXUU8=; b=Us4u//ECin3UrXCQtC7i/W5ajqn3oRwlh8TWclAV7tUfnny2REcC5Q6L 9UtJyb6zUxtU02gWO1uA+MDmXMRX9gI7DRQHu7nDff89ZvHoq2uyj6jX5 kBoJkYRYlB952nWuohVnI+0W13c6rlzdP9xlki7rXoxpDeuvJbh2y8yVo cBHx/TZ01K4tCFsloaCvX8vaXoVCpRxIC1bjMKzuGbd2Gv8FNFHbp1spv 8ioFZVeH3WquvzncwRf3dLcKhjov7lB2PgzE/dWo5EiwJNC45v02UT8Nj SAdOhmZDGaBKZQM9O0LXN7ExGN+XRbmqfhvq54ySrO2IYZbgqNsOByR4S A==; X-IronPort-AV: E=McAfee;i="6400,9594,10324"; a="251776742" X-IronPort-AV: E=Sophos;i="5.90,279,1643702400"; d="scan'208";a="251776742" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Apr 2022 12:20:40 -0700 X-IronPort-AV: E=Sophos;i="5.90,279,1643702400"; d="scan'208";a="533556682" Received: from josouza-mobl2.fso.intel.com ([10.230.18.139]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Apr 2022 12:20:38 -0700 From: =?utf-8?q?Jos=C3=A9_Roberto_de_Souza?= To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Date: Thu, 21 Apr 2022 12:22:05 -0700 Message-Id: <20220421192205.32649-3-jose.souza@intel.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220421192205.32649-1-jose.souza@intel.com> References: <20220421192205.32649-1-jose.souza@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 3/3] drm/i915/display: Implement seamless mode switch 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: , Cc: Sean Paul Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" As described in previous commit "drm: Add infrastructure to allow seamless mode switches" here doing the i915 implementation. The main steps are: - drm_atomic_helper_check_modeset() will call atomic_seamless_mode_switch_check()/intel_drrs_seamless_mode_switch_check() if conditions match - intel_drrs_seamless_mode_switch_check() will check if seamless DRRS is enabled and if the requested mode matches with fixed or downclock mode - now at the atomic commit phase during the execution of intel_pre_plane_update(), intel_drrs_deactivate() will return without change the DRRS state if seamless_mode_switch_enabled or seamless_mode_changed is set and there is no modeset happening in this pipe(something after drm_atomic_helper_check_modeset() could still require a modeset and set mode_changed) - then in intel_post_plane_update(), intel_drrs_activate() is called and DRRS mode is switched if seamless_mode_changed is set or the function is skipped if seamless_mode_switch_enabled is set and pipe don't need a modeset After a modeset, seamless_mode_switch_enabled is set to 0 and DRRS is back to automatic mode until the next commit that intel_drrs_seamless_mode_switch_check() is executed and it supports the mode. Cc: Vidya Srinivas Cc: Sean Paul Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_crtc.c | 10 +++ drivers/gpu/drm/i915/display/intel_display.c | 5 +- .../drm/i915/display/intel_display_debugfs.c | 5 +- .../drm/i915/display/intel_display_types.h | 3 +- drivers/gpu/drm/i915/display/intel_dp.c | 2 + drivers/gpu/drm/i915/display/intel_drrs.c | 73 ++++++++++++++++++- drivers/gpu/drm/i915/display/intel_drrs.h | 5 +- 7 files changed, 96 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 4442aa355f868..d411daa0b2bab 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -215,6 +215,15 @@ static int intel_crtc_late_register(struct drm_crtc *crtc) return 0; } +static int intel_crtc_seamless_mode_switch_check(struct drm_atomic_state *_state, + struct drm_crtc *_crtc) +{ + struct intel_atomic_state *state = to_intel_atomic_state(_state); + struct intel_crtc *crtc = to_intel_crtc(_crtc); + + return intel_drrs_seamless_mode_switch_check(state, crtc); +} + #define INTEL_CRTC_FUNCS \ .set_config = drm_atomic_helper_set_config, \ .destroy = intel_crtc_destroy, \ @@ -233,6 +242,7 @@ static const struct drm_crtc_funcs bdw_crtc_funcs = { .enable_vblank = bdw_enable_vblank, .disable_vblank = bdw_disable_vblank, .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, + .atomic_seamless_mode_switch_check = intel_crtc_seamless_mode_switch_check, }; static const struct drm_crtc_funcs ilk_crtc_funcs = { diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a5f5caeced9a0..ebfa7d68e35fe 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1329,7 +1329,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); enum pipe pipe = crtc->pipe; - intel_drrs_deactivate(old_crtc_state); + intel_drrs_deactivate(old_crtc_state, new_crtc_state); intel_psr_pre_plane_update(state, crtc); @@ -7089,6 +7089,7 @@ static void intel_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_stat new_crtc_state->dp_m_n = old_crtc_state->dp_m_n; new_crtc_state->dp_m2_n2 = old_crtc_state->dp_m2_n2; new_crtc_state->drrs_downclock_mode = old_crtc_state->drrs_downclock_mode; + new_crtc_state->drrs_fixed_mode = old_crtc_state->drrs_fixed_mode; } static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state, @@ -7716,6 +7717,8 @@ static int intel_atomic_check(struct drm_device *dev, if (!intel_crtc_needs_modeset(new_crtc_state)) { if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) copy_bigjoiner_crtc_state_nomodeset(state, crtc); + else if (new_crtc_state->uapi.seamless_mode_changed) + intel_crtc_copy_uapi_to_hw_state_modeset(state, crtc); else intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); continue; diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index f9720562336da..1d27ed2b68210 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1108,6 +1108,9 @@ static int i915_drrs_status(struct seq_file *m, void *unused) crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ? "low" : "high"); + seq_printf(m, "Seamless mode switch enabled: %s\n", + str_yes_no(crtc->drrs.seamless_mode_switch_enabled)); + mutex_unlock(&crtc->drrs.mutex); } @@ -1802,7 +1805,7 @@ static int i915_drrs_ctl_set(void *data, u64 val) if (val) intel_drrs_activate(crtc_state); else - intel_drrs_deactivate(crtc_state); + intel_drrs_deactivate(crtc_state, crtc_state); out: drm_modeset_unlock(&crtc->base.mutex); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f0b3cfd3138ce..b04922fd45e45 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1056,7 +1056,7 @@ struct intel_crtc_state { /* m2_n2 for eDP downclock */ struct intel_link_m_n dp_m2_n2; - const struct drm_display_mode *drrs_downclock_mode; + const struct drm_display_mode *drrs_fixed_mode, *drrs_downclock_mode; /* PSR is supported but might not be enabled due the lack of enabled planes */ bool has_psr; @@ -1316,6 +1316,7 @@ struct intel_crtc { unsigned int busy_frontbuffer_bits; enum transcoder cpu_transcoder; struct intel_link_m_n m_n, m2_n2; + bool seamless_mode_switch_enabled; } drrs; int scanline_offset; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index feea172dd2753..82f13c3b0f2b3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1881,6 +1881,8 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay; + pipe_config->drrs_fixed_mode = intel_panel_fixed_mode(connector, + &pipe_config->hw.adjusted_mode); pipe_config->drrs_downclock_mode = downclock_mode; pixel_clock = downclock_mode->clock; diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index dd527dfc2d1d5..3a801f7e79187 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -155,6 +155,23 @@ void intel_drrs_activate(const struct intel_crtc_state *crtc_state) mutex_lock(&crtc->drrs.mutex); + /* Until the next modeset user-space will control the refresh rate */ + if (crtc_state->uapi.seamless_mode_changed && + !intel_crtc_needs_modeset(crtc_state)) { + enum drrs_refresh_rate rate = DRRS_REFRESH_RATE_HIGH; + + if (drm_mode_match(&crtc_state->hw.adjusted_mode, + crtc_state->drrs_downclock_mode, + DRM_MODE_MATCH_CLOCK)) + rate = DRRS_REFRESH_RATE_LOW; + + crtc->drrs.seamless_mode_switch_enabled = true; + intel_drrs_set_state(crtc, rate); + } + + if (crtc->drrs.seamless_mode_switch_enabled) + goto unlock; + crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder; crtc->drrs.m_n = crtc_state->dp_m_n; crtc->drrs.m2_n2 = crtc_state->dp_m2_n2; @@ -162,7 +179,7 @@ void intel_drrs_activate(const struct intel_crtc_state *crtc_state) crtc->drrs.busy_frontbuffer_bits = 0; intel_drrs_schedule_work(crtc); - +unlock: mutex_unlock(&crtc->drrs.mutex); } @@ -172,7 +189,8 @@ void intel_drrs_activate(const struct intel_crtc_state *crtc_state) * * Deactivates DRRS on the crtc. */ -void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state) +void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); @@ -187,13 +205,25 @@ void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state) mutex_lock(&crtc->drrs.mutex); + /* + * When seamless_mode_switch_enabled is enabled, user-space is in + * control of DRRS and it will only go to the automatic mode on the + * next modeset + */ + if ((crtc->drrs.seamless_mode_switch_enabled || + new_crtc_state->uapi.seamless_mode_changed) && + !intel_crtc_needs_modeset(new_crtc_state)) + goto unlock; + if (intel_drrs_is_active(crtc)) intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; crtc->drrs.frontbuffer_bits = 0; crtc->drrs.busy_frontbuffer_bits = 0; + crtc->drrs.seamless_mode_switch_enabled = false; +unlock: mutex_unlock(&crtc->drrs.mutex); cancel_delayed_work_sync(&crtc->drrs.work); @@ -205,7 +235,8 @@ static void intel_drrs_downclock_work(struct work_struct *work) mutex_lock(&crtc->drrs.mutex); - if (intel_drrs_is_active(crtc) && !crtc->drrs.busy_frontbuffer_bits) + if (intel_drrs_is_active(crtc) && !crtc->drrs.busy_frontbuffer_bits && + !crtc->drrs.seamless_mode_switch_enabled) intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_LOW); mutex_unlock(&crtc->drrs.mutex); @@ -236,6 +267,11 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, else crtc->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits; + if (crtc->drrs.seamless_mode_switch_enabled) { + mutex_unlock(&crtc->drrs.mutex); + continue; + } + /* flush/invalidate means busy screen hence upclock */ intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); @@ -300,3 +336,34 @@ void intel_crtc_drrs_init(struct intel_crtc *crtc) mutex_init(&crtc->drrs.mutex); crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; } + +int intel_drrs_seamless_mode_switch_check(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + const unsigned int match_mode_flags = DRM_MODE_MATCH_TIMINGS | + DRM_MODE_MATCH_FLAGS | + DRM_MODE_MATCH_3D_FLAGS | + DRM_MODE_MATCH_ASPECT_RATIO; + struct intel_crtc_state *new_crtc_state; + + new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + if (IS_ERR(new_crtc_state)) + return PTR_ERR(new_crtc_state); + + if (!CRTC_STATE_HAS_DRRS(new_crtc_state)) + return -EOPNOTSUPP; + + /* Requested mode matches with fixed or downclock mode? */ + if (!drm_mode_match(&new_crtc_state->uapi.mode, + new_crtc_state->drrs_fixed_mode, + match_mode_flags) && + !drm_mode_match(&new_crtc_state->uapi.mode, + new_crtc_state->drrs_downclock_mode, + match_mode_flags)) + return -EOPNOTSUPP; + + drm_mode_copy(&new_crtc_state->uapi.adjusted_mode, + &new_crtc_state->uapi.mode); + + return 0; +} diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index 3ad1be1ad9c13..85ad987c45945 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -18,11 +18,14 @@ struct intel_connector; const char *intel_drrs_type_str(enum drrs_type drrs_type); bool intel_drrs_is_active(struct intel_crtc *crtc); void intel_drrs_activate(const struct intel_crtc_state *crtc_state); -void intel_drrs_deactivate(const struct intel_crtc_state *crtc_state); +void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state); void intel_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_drrs_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_crtc_drrs_init(struct intel_crtc *crtc); +int intel_drrs_seamless_mode_switch_check(struct intel_atomic_state *state, + struct intel_crtc *crtc); #endif /* __INTEL_DRRS_H__ */