From patchwork Thu Apr 28 21:10:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Souza, Jose" X-Patchwork-Id: 12831178 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 D218DC433FE for ; Thu, 28 Apr 2022 21:10:20 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4AE2410E1A0; Thu, 28 Apr 2022 21:10:20 +0000 (UTC) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5AB3A10E1A0 for ; Thu, 28 Apr 2022 21:10:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1651180219; x=1682716219; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=gZrb0RP6sdwQeRZ0lwRTZHXNBp2qTsZNtmcw08wSXYY=; b=aPFp6gInj3g5+CjP/zIBKa/7LH2GiXeDje07rGOnjJ3gnlHA7wNk7toY ux6DMWPzwhDCBEF53YpIdSPtKmN/BP5c5nSyktAbE9apF1DDVFNFlNoDn MVnn6Nvq6cjKrmNsdOyuDwkg2QIrohcWF6aER8AZs+KtZTNdMDnMqXJNl UeN1uXUQGJwonmvo6u/Erg8SgUlidSEdW2xOQz4pfeQ1BE4vTfLfkMctK uQL5gwVdxji2M13lNYsI47lwVQ61cFURnvATgR9amtxaFgGIGB1BFYjsT dnw98F8tSzGR1g/pjSttlY57LupKdtr+sfKaT7uAU1a2vTje9LB9niYmP Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10331"; a="266581184" X-IronPort-AV: E=Sophos;i="5.91,296,1647327600"; d="scan'208";a="266581184" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Apr 2022 14:10:18 -0700 X-IronPort-AV: E=Sophos;i="5.91,296,1647327600"; d="scan'208";a="581644212" Received: from unknown (HELO josouza-mobl2.fso.intel.com) ([10.230.18.139]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Apr 2022 14:10:17 -0700 From: =?utf-8?q?Jos=C3=A9_Roberto_de_Souza?= To: intel-gfx@lists.freedesktop.org Date: Thu, 28 Apr 2022 14:10:56 -0700 Message-Id: <20220428211058.399630-1-jose.souza@intel.com> X-Mailer: git-send-email 2.36.0 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 1/3] drm/i915/display: Do not schedule DRRS work thread when it is not active 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" Frontbuffer updates were scheduling the execution of DRRS work thread even if DRRS is not active. There was no issues with it because intel_drrs_downclock_work() checks if DRRS is active but there is no reason to keep scheduling this work thread and wasting CPU time. Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_drrs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 166caf293f7bc..04bc296761be0 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -236,6 +236,11 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, else crtc->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits; + if (!intel_drrs_is_active(crtc)) { + mutex_unlock(&crtc->drrs.mutex); + continue; + } + /* flush/invalidate means busy screen hence upclock */ intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); From patchwork Thu Apr 28 21:10:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Souza, Jose" X-Patchwork-Id: 12831179 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 4768AC433EF for ; Thu, 28 Apr 2022 21:10:24 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B098410E478; Thu, 28 Apr 2022 21:10:23 +0000 (UTC) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTPS id D638410E272 for ; Thu, 28 Apr 2022 21:10:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1651180220; x=1682716220; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=lfJ4/R92bgIN+wrn4zUzbPD4HIJbE6l8ZWidB6IYoeY=; b=Gtpccxuf76eyXgNC2kHNeI9XllOqAfQpWz01ucG3gFZieWdEs0YrUM17 wV6E/3au0b2DV0kdMvy+2gubOp2WRxx4ePMPT/bQCuZtp50vsyM5fK9vk RJ0EpKGmlbMOcfF7XAlvLvrT7aibBuN0FcKioBeh/U4FsfX5QhGOFEwb9 UhD1/n3V6MG3FvC1HrVKIhyOpEAbbG63vi+WcYWVwLSgtCIA1r0vdn4oP qwY14WYIiAuEEDKs1Fz4kGSjfRS4MUw57neMnkL2QkbeEJnL6eiQiQ+KZ hsagFRNiR841L4BLJS6I0cTCVpmUbEBNxmeZR9robR25AKiwVBG4hqvQv g==; X-IronPort-AV: E=McAfee;i="6400,9594,10331"; a="266581196" X-IronPort-AV: E=Sophos;i="5.91,296,1647327600"; d="scan'208";a="266581196" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Apr 2022 14:10:20 -0700 X-IronPort-AV: E=Sophos;i="5.91,296,1647327600"; d="scan'208";a="581644236" Received: from unknown (HELO josouza-mobl2.fso.intel.com) ([10.230.18.139]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Apr 2022 14:10:18 -0700 From: =?utf-8?q?Jos=C3=A9_Roberto_de_Souza?= To: intel-gfx@lists.freedesktop.org Date: Thu, 28 Apr 2022 14:10:57 -0700 Message-Id: <20220428211058.399630-2-jose.souza@intel.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220428211058.399630-1-jose.souza@intel.com> References: <20220428211058.399630-1-jose.souza@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 2/3] drm/i915/display: Allow DRRS to be enabled during driver load 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" When driver takes over display from firmware it does some checks and if possible it tries to avoid a modeset to improve user boot experience. But even if DRRS is supported it was being left disabled as intel_crtc_copy_fastset() was overwritten new state with the old one (hardware readout). So here checking if platform has only one set of m_n registers that can change on the fly between high and low clock, if yes we can keep DRRS enabled. Cc: Vidya Srinivas Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 7 ++++-- drivers/gpu/drm/i915/display/intel_drrs.c | 24 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_drrs.h | 2 ++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0decf3d242372..17d0cad9e1686 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7086,8 +7086,11 @@ 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; + + if (!intel_drrs_crtc_copy_fastset(old_crtc_state, new_crtc_state)) { + new_crtc_state->dp_m2_n2 = old_crtc_state->dp_m2_n2; + new_crtc_state->has_drrs = old_crtc_state->has_drrs; + } } static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 04bc296761be0..c6509c29e942b 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -305,3 +305,27 @@ void intel_crtc_drrs_init(struct intel_crtc *crtc) mutex_init(&crtc->drrs.mutex); crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; } + +/** + * intel_drrs_crtc_copy_fastset - Handles crtc state copy during fastsets when + * new state has DRRS. + * @old_crtc_state: old crtc state + * @new_crtc_state: new crtc state + * + * Handle crtc state copy during fastsets trying to keep DRRS enabled. + * That can be done in platforms that supports change the dp_m_n register on + * the fly between high and low clocks. + * + * Returns true if crtc copy was already handled otherwise returns false. + */ +bool intel_drrs_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state) +{ + struct drm_i915_private *i915 = to_i915(old_crtc_state->uapi.crtc->dev); + + /* m2_n2 register needs to already be set */ + if (intel_cpu_transcoder_has_m2_n2(i915, new_crtc_state->cpu_transcoder)) + return false; + + return true; +} diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index 3ad1be1ad9c13..749ac717db063 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -24,5 +24,7 @@ void intel_drrs_invalidate(struct drm_i915_private *dev_priv, void intel_drrs_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_crtc_drrs_init(struct intel_crtc *crtc); +bool intel_drrs_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state); #endif /* __INTEL_DRRS_H__ */ From patchwork Thu Apr 28 21:10:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Souza, Jose" X-Patchwork-Id: 12831180 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 DB219C433F5 for ; Thu, 28 Apr 2022 21:10:23 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4313710E272; Thu, 28 Apr 2022 21:10:23 +0000 (UTC) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7FD5A10E272 for ; Thu, 28 Apr 2022 21:10:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1651180222; x=1682716222; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uqvvanhBbfQkpXeHolmaELC9IqqBy6eApBcc3XvWVd8=; b=Putc+fFy4qg7dKQ0eP4XWbVS7Onl2QbO2L647bOxWGIEokdzCfOxBPHm 4HgyznBReBYaeQFAktkcm8omCIDm1hPv460x1g05mORKYNPy37Ixv32Cr L8DEcrhjm6ZKh7mAbTpGQwnuaa5yNheE4PZVrCn3RMXNgoUj668Y04vjI tNZi6XZwHKcEDS7rysvHkoTdQfBgcokRQND60UbGo7F9ACjOt2EpTBjYc TcE7Suzw1eLUy4tXAXpr4MYzNpyr+rczKGg1KAsK5eKlhs+SbBsTxS5Bq r7RV3jdzfHVcL/MzqT9opbpclBZ/v5XGJP8mHZf9LFei80QsIv2K/INqr g==; X-IronPort-AV: E=McAfee;i="6400,9594,10331"; a="266581213" X-IronPort-AV: E=Sophos;i="5.91,296,1647327600"; d="scan'208";a="266581213" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Apr 2022 14:10:22 -0700 X-IronPort-AV: E=Sophos;i="5.91,296,1647327600"; d="scan'208";a="581644261" Received: from unknown (HELO josouza-mobl2.fso.intel.com) ([10.230.18.139]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Apr 2022 14:10:20 -0700 From: =?utf-8?q?Jos=C3=A9_Roberto_de_Souza?= To: intel-gfx@lists.freedesktop.org Date: Thu, 28 Apr 2022 14:10:58 -0700 Message-Id: <20220428211058.399630-3-jose.souza@intel.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220428211058.399630-1-jose.souza@intel.com> References: <20220428211058.399630-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" So far the i915's DRRS feature was automatically changing between preferred panel mode and downclock mode based on idleness but ChromeOS compositor team is asking to be in control of the mode switch. So for certain types of content it can switch to a mode with a lower refresh rate without the user noticing a thing and saving more power. This seamless mode switch will be triggered when user-space dispatches an atomic commit with the new mode and clears the DRM_MODE_ATOMIC_ALLOW_MODESET flag. The main steps to acomplish that are: - as mode changed in atomic state drm_atomic_helper_check_modeset() will set mode_changed and it will trigger the crtc state computation so intel_dp_compute_config() will be called and dp_m_n will be computed for the new mode - then intel_dp_drrs_compute_config() will check for the necessary conditions to do a seamless mode switch, if possible crtc_state->seamless_mode_switch will be set and has_drrs will not be set, so i915 will not automatically switch between modes - then intel_crtc_compute_config() will call intel_crtc_compute_pixel_rate() that will take the hint that it is trying to do a seamless mode switch and set pixel_rate to the pixel_rate of the old state - then if nothing else changed in the state intel_crtc_check_fastset() will be able to set mode_changed to false and i915 can do fastset otherwise the commit will fail during the check phase - now on the atomic commit phase, intel_ddi_update_pipe_dp() will be called and will program the new dp_m_n - nothing else is different in the commit phase until the step to verify programmed state, the most important change here is that need to save the pixel_rate in DRRS global state as there is no other way to get that from hardware or atomic state Cc: Vidya Srinivas Cc: Sean Paul Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 10 ++++ drivers/gpu/drm/i915/display/intel_display.c | 59 ++++++++++++++++--- .../drm/i915/display/intel_display_debugfs.c | 3 + .../drm/i915/display/intel_display_types.h | 3 + drivers/gpu/drm/i915/display/intel_dp.c | 56 +++++++++++++++--- drivers/gpu/drm/i915/display/intel_drrs.c | 35 ++++++++--- drivers/gpu/drm/i915/display/intel_drrs.h | 3 + 7 files changed, 147 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 9e6fa59eabba7..732e5d425412e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -46,6 +46,7 @@ #include "intel_dp_link_training.h" #include "intel_dp_mst.h" #include "intel_dpio_phy.h" +#include "intel_drrs.h" #include "intel_dsi.h" #include "intel_fdi.h" #include "intel_fifo_underrun.h" @@ -3010,6 +3011,14 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, intel_backlight_update(state, encoder, crtc_state, conn_state); drm_connector_update_privacy_screen(conn_state); + + if (crtc_state->seamless_mode_switch) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); + + intel_cpu_transcoder_set_m1_n1(intel_crtc, + crtc_state->cpu_transcoder, + &crtc_state->dp_m_n); + } } void intel_ddi_update_pipe(struct intel_atomic_state *state, @@ -3484,6 +3493,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC); intel_psr_get_config(encoder, pipe_config); + intel_drrs_get_config(encoder, pipe_config); } void intel_ddi_get_clock(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 17d0cad9e1686..c37501b2ab419 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2629,6 +2629,44 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) else crtc_state->pixel_rate = ilk_pipe_pixel_rate(crtc_state); + + /* + * Do not change pixel_rate when doing seamless mode switch, otherwise + * it will change port_clock and other stuff that will need a modeset + * to be programmed + */ + if (crtc_state->seamless_mode_switch) { + struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct intel_crtc_state *old_crtc_state; + + old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + + /* + * It can only seamless switch if pixel rate of the new mode is + * <= than old one, if not commit will fail with pixel_rate + * mismatch. + */ + if (crtc_state->pixel_rate < old_crtc_state->pixel_rate || + intel_fuzzy_clock_check(crtc_state->pixel_rate, + old_crtc_state->pixel_rate)) + crtc_state->pixel_rate = old_crtc_state->pixel_rate; + } +} + +static void intel_crtc_get_pixel_rate(struct intel_crtc_state *crtc_state) +{ + if (crtc_state->seamless_mode_switch) { + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + mutex_lock(&crtc->drrs.mutex); + crtc_state->pixel_rate = crtc->drrs.seamless_mode_switch_pixel_rate; + mutex_unlock(&crtc->drrs.mutex); + + return; + } + + intel_crtc_compute_pixel_rate(crtc_state); } static void intel_bigjoiner_adjust_timings(const struct intel_crtc_state *crtc_state, @@ -2705,7 +2743,7 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); intel_mode_from_crtc_timings(pipe_mode, pipe_mode); - intel_crtc_compute_pixel_rate(crtc_state); + intel_crtc_get_pixel_rate(crtc_state); } static void intel_encoder_get_config(struct intel_encoder *encoder, @@ -6182,11 +6220,13 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(lane_count); PIPE_CONF_CHECK_X(lane_lat_optim_mask); - if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) { - PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2); - } else { - PIPE_CONF_CHECK_M_N(dp_m_n); - PIPE_CONF_CHECK_M_N(dp_m2_n2); + if (!pipe_config->seamless_mode_switch) { + if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) { + PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2); + } else { + PIPE_CONF_CHECK_M_N(dp_m_n); + PIPE_CONF_CHECK_M_N(dp_m2_n2); + } } PIPE_CONF_CHECK_X(output_types); @@ -6348,8 +6388,10 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) >= 5) PIPE_CONF_CHECK_I(pipe_bpp); - PIPE_CONF_CHECK_CLOCK_FUZZY(hw.pipe_mode.crtc_clock); - PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock); + if (!pipe_config->seamless_mode_switch) { + PIPE_CONF_CHECK_CLOCK_FUZZY(hw.pipe_mode.crtc_clock); + PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock); + } PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); PIPE_CONF_CHECK_I(min_voltage_level); @@ -7090,6 +7132,7 @@ static void intel_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_stat if (!intel_drrs_crtc_copy_fastset(old_crtc_state, new_crtc_state)) { 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->seamless_mode_switch = old_crtc_state->seamless_mode_switch; } } diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 452d773fd4e34..92099e1f0b23e 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_pixel_rate)); + mutex_unlock(&crtc->drrs.mutex); } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 408152f9f46a4..e290366adfc27 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1057,6 +1057,7 @@ struct intel_crtc_state { /* m2_n2 for eDP downclock */ struct intel_link_m_n dp_m2_n2; bool has_drrs; + bool seamless_mode_switch; /* PSR is supported but might not be enabled due the lack of enabled planes */ bool has_psr; @@ -1314,6 +1315,8 @@ struct intel_crtc { unsigned int busy_frontbuffer_bits; enum transcoder cpu_transcoder; struct intel_link_m_n m_n, m2_n2; + /* Only used to verify if programmed state matches */ + unsigned int seamless_mode_switch_pixel_rate; } 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 e4a79c11fd255..d7d045bdf77af 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1835,8 +1835,7 @@ static bool cpu_transcoder_has_drrs(struct drm_i915_private *i915, } static bool can_enable_drrs(struct intel_connector *connector, - const struct intel_crtc_state *pipe_config, - const struct drm_display_mode *downclock_mode) + const struct intel_crtc_state *pipe_config) { struct drm_i915_private *i915 = to_i915(connector->base.dev); @@ -1859,8 +1858,40 @@ static bool can_enable_drrs(struct intel_connector *connector, if (!cpu_transcoder_has_drrs(i915, pipe_config->cpu_transcoder)) return false; - return downclock_mode && - intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; + return intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; +} + +static bool can_seamless_switch_mode(struct intel_crtc_state *pipe_config) +{ + struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev); + const struct intel_crtc_state *old_pipe_config; + struct intel_atomic_state *state; + struct intel_crtc *intel_crtc; + + /* Only supported in platforms that can switch m_n on the fly */ + if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder)) + return false; + + state = to_intel_atomic_state(pipe_config->uapi.state); + if (state->base.allow_modeset) + return false; + + intel_crtc = to_intel_crtc(pipe_config->uapi.crtc); + old_pipe_config = intel_atomic_get_old_crtc_state(state, intel_crtc); + if (drm_mode_equal(&old_pipe_config->hw.adjusted_mode, + &pipe_config->hw.adjusted_mode)) + return false; + + /* Only clock can change */ + if (!drm_mode_match(&old_pipe_config->hw.adjusted_mode, + &pipe_config->hw.adjusted_mode, + DRM_MODE_MATCH_TIMINGS | + DRM_MODE_MATCH_FLAGS | + DRM_MODE_MATCH_3D_FLAGS | + DRM_MODE_MATCH_ASPECT_RATIO)) + return false; + + return true; } static void @@ -1873,12 +1904,17 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); int pixel_clock; - if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { - if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder)) - intel_zero_m_n(&pipe_config->dp_m2_n2); + if (!can_enable_drrs(connector, pipe_config)) + goto not_supported; + + if (can_seamless_switch_mode(pipe_config)) { + pipe_config->seamless_mode_switch = true; return; } + if (!downclock_mode) + goto not_supported; + if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay; @@ -1895,6 +1931,12 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, /* FIXME: abstract this better */ if (pipe_config->splitter.enable) pipe_config->dp_m2_n2.data_m *= pipe_config->splitter.link_count; + + return; + +not_supported: + if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder)) + intel_zero_m_n(&pipe_config->dp_m2_n2); } static bool intel_dp_has_audio(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index c6509c29e942b..179a124177d15 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -144,16 +144,19 @@ void intel_drrs_activate(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + mutex_lock(&crtc->drrs.mutex); + + crtc->drrs.seamless_mode_switch_pixel_rate = crtc_state->seamless_mode_switch ? + crtc_state->pixel_rate : 0; + if (!crtc_state->has_drrs) - return; + goto unlock; if (!crtc_state->hw.active) - return; + goto unlock; if (intel_crtc_is_bigjoiner_slave(crtc_state)) - return; - - mutex_lock(&crtc->drrs.mutex); + goto unlock; crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder; crtc->drrs.m_n = crtc_state->dp_m_n; @@ -163,6 +166,7 @@ void intel_drrs_activate(const struct intel_crtc_state *crtc_state) intel_drrs_schedule_work(crtc); +unlock: mutex_unlock(&crtc->drrs.mutex); } @@ -176,7 +180,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 (!old_crtc_state->has_drrs && !old_crtc_state->seamless_mode_switch) return; if (!old_crtc_state->hw.active) @@ -187,12 +191,14 @@ void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state) mutex_lock(&crtc->drrs.mutex); - if (intel_drrs_is_active(crtc)) + if (intel_drrs_is_active(crtc) && + old_crtc_state->seamless_mode_switch == 0) 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_pixel_rate = 0; mutex_unlock(&crtc->drrs.mutex); @@ -329,3 +335,18 @@ bool intel_drrs_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_state, return true; } + +void intel_drrs_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) +{ + struct intel_crtc *crtc; + + crtc = to_intel_crtc(pipe_config->uapi.crtc); + + mutex_lock(&crtc->drrs.mutex); + + pipe_config->seamless_mode_switch = crtc->drrs.seamless_mode_switch_pixel_rate; + pipe_config->has_drrs = intel_drrs_is_active(crtc); + + mutex_unlock(&crtc->drrs.mutex); +} diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index 749ac717db063..a100023658a5a 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -14,6 +14,7 @@ struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; struct intel_connector; +struct intel_encoder; const char *intel_drrs_type_str(enum drrs_type drrs_type); bool intel_drrs_is_active(struct intel_crtc *crtc); @@ -26,5 +27,7 @@ void intel_drrs_flush(struct drm_i915_private *dev_priv, void intel_crtc_drrs_init(struct intel_crtc *crtc); bool intel_drrs_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state); +void intel_drrs_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config); #endif /* __INTEL_DRRS_H__ */