From patchwork Wed Apr 22 14:12:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: You-Sheng Yang X-Patchwork-Id: 1275123 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 496jC13XY9z9sSm; Thu, 23 Apr 2020 00:15:41 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1jRGA4-00046u-6g; Wed, 22 Apr 2020 14:15:36 +0000 Received: from mail-pg1-f194.google.com ([209.85.215.194]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1jRG8u-0003Ml-Qh for kernel-team@lists.ubuntu.com; Wed, 22 Apr 2020 14:14:24 +0000 Received: by mail-pg1-f194.google.com with SMTP id o185so1151994pgo.3 for ; Wed, 22 Apr 2020 07:14:24 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9Qvcq8Uofq3FmD2XdAcwI3/UbhtHnjTDEcP2EmdwHC0=; b=Ma6y17SaODuukDHiMSMoPTmMbDQzrZKvJWe8/ZmFMm0VLS2qODIY3+Rr+6S4TuKWFE 81u54HPLZZ5UmZNHkRGkolJeT4DuV1QONmNeGk448jnLhOp6ezWoZpdCBJlgdEU2U8uX gTeJ0ecdK5gC3P6VXpy3wemhIS4B+r3jPio03tTYvx77+bku2GfxA/9VlMNH7w2oP5TJ euAVonBAqpHNREaorgYHHZ8t8GTr1dfDOSh/KPqZ6p4gck0/PDwvP827nI+ODpFZod8w 5qkgQYEveb1uaD4Mvhf1GeNnc6v1JDReg7/TsW9wmlqVjj5iZtaKQLtbDKtgl2eXNM51 aLeA== X-Gm-Message-State: AGi0PuZfkCQ7MiqIT9JlhacQ8zaFbArhWfV0DIPb3nKgzFgt4Ut6PNoI 5ouerOx/YsK26zrbZInMQXBWOrbhgwA= X-Google-Smtp-Source: APiQypIvYjyHu6CLQTf80zvQ0bFCnZPgZ71RiRWRg7wWcj3YKsn9MJgDttiO31WfVDrE7x5cMqjfaQ== X-Received: by 2002:a63:1c6:: with SMTP id 189mr26129073pgb.254.1587564862091; Wed, 22 Apr 2020 07:14:22 -0700 (PDT) Received: from localhost (61-220-137-37.HINET-IP.hinet.net. [61.220.137.37]) by smtp.gmail.com with ESMTPSA id x66sm5664842pfb.173.2020.04.22.07.14.20 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Apr 2020 07:14:21 -0700 (PDT) From: You-Sheng Yang To: kernel-team@lists.ubuntu.com Subject: [SRU][E][PATCH 48/52] drm/i915/tc/icl: Implement TC cold sequences Date: Wed, 22 Apr 2020 22:12:11 +0800 Message-Id: <20200422141215.1548544-49-vicamo.yang@canonical.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200422141215.1548544-1-vicamo.yang@canonical.com> References: <20200422141215.1548544-1-vicamo.yang@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: José Roberto de Souza BugLink: https://bugs.launchpad.net/bugs/1868936 This is required for legacy/static TC ports as IOM is not aware of the connection and will not trigger the TC cold exit. Just request PCODE to exit TCCOLD is not enough as it could enter again before driver makes use of the port, to prevent it BSpec states that aux powerwell should be held. So here embedding the TC cold exit sequence into ICL aux enable, it will enable aux and then request TC cold to exit. The TC cold block(exit and aux hold) and unblock was added to some exported TC functions for the others and to access PHY registers, callers should enable and keep aux powerwell enabled during access. Also adding TC cold check and warnig in tc_port_load_fia_params() as at this point of the driver initialization we can't request power wells, if we get this warning we will need to figure out how to handle it. v2: - moved ICL TC cold exit function to intel_display_power - using dig_port->tc_legacy_port to only execute sequences for legacy ports, hopefully VBTs will have this right - fixed check to call _hsw_power_well_continue_enable() - calling _hsw_power_well_continue_enable() unconditionally in icl_tc_phy_aux_power_well_enable(), if needed we will surpress timeout warnings of TC legacy ports - only blocking TC cold around fia access v3: - added timeout of 5msec to not loop forever if sandybridge_pcode_write_timeout() keeps returning -EAGAIN returning -EAGAIN in in icl_tc_cold_exit() - removed leftover tc_cold_wakeref - added one msec sleep when PCODE returns -EAGAIN v4: - removed 5msec timeout, instead giving 1msec to whoever is using PCODE to finish it up to 3 times - added a comment about turn TC cold exit failure as a error in future BSpec: 21750 Closes: https://gitlab.freedesktop.org/drm/intel/issues/1296 Cc: Imre Deak Cc: Cooper Chiou Cc: Kai-Heng Feng Reviewed-by: Imre Deak Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200414194956.164323-4-jose.souza@intel.com (backported from drm-tip commit feb7e0ef5ff820ee7242bb46cfe3d0dd3e234c38) Signed-off-by: You-Sheng Yang --- .../drm/i915/display/intel_display_power.c | 24 ++++++- drivers/gpu/drm/i915/display/intel_tc.c | 62 +++++++++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 1 + 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 6aad2dc5b57b..a8ada51c37c8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -545,6 +545,27 @@ static void icl_tc_port_assert_ref_held(struct drm_i915_private *dev_priv, #endif +static void icl_tc_cold_exit(struct drm_i915_private *i915) +{ + int ret, tries = 0; + + while (1) { + ret = sandybridge_pcode_write_timeout(i915, + ICL_PCODE_EXIT_TCCOLD, + 0, 250, 1); + if (ret != -EAGAIN || ++tries == 3) + break; + msleep(1); + } + + /* Spec states that TC cold exit can take up to 1ms to complete */ + if (!ret) + msleep(1); + + /* TODO: turn failure into a error as soon i915 CI updates ICL IFWI */ + DRM_DEBUG_KMS("TC cold block %s\n", ret ? "failed" : "succeeded"); +} + static void icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) @@ -563,7 +584,8 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, hsw_power_well_enable_prepare(dev_priv, power_well); - /* TODO ICL TC cold handling */ + if (INTEL_GEN(dev_priv) == 11 && dig_port->tc_legacy_port) + icl_tc_cold_exit(dev_priv); hsw_power_well_enable_complete(dev_priv, power_well); } diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index 429ab2657841..9cc709a41a7d 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -44,6 +44,37 @@ static enum phy_fia tc_port_to_fia(struct drm_i915_private *i915, return tc_port / 2; } +static intel_wakeref_t +tc_cold_block(struct intel_digital_port *dig_port) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + enum intel_display_power_domain domain; + + if (INTEL_GEN(i915) != 11 || !dig_port->tc_legacy_port) + return 0; + + domain = intel_legacy_aux_to_power_domain(dig_port->aux_ch); + return intel_display_power_get(i915, domain); +} + +static void +tc_cold_unblock(struct intel_digital_port *dig_port, intel_wakeref_t wakeref) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + enum intel_display_power_domain domain; + + /* + * wakeref == -1, means some error happened saving save_depot_stack but + * power should still be put down and 0 is a invalid save_depot_stack + * id so can be used to skip it for non TC legacy ports. + */ + if (wakeref == 0) + return; + + domain = intel_legacy_aux_to_power_domain(dig_port->aux_ch); + intel_display_power_put_async(i915, domain, wakeref); +} + u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); @@ -389,8 +420,14 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port, enum tc_port_mode old_tc_mode = dig_port->tc_mode; intel_display_power_flush_work(i915); - WARN_ON(intel_display_power_is_enabled(i915, - intel_aux_power_domain(dig_port))); + if (INTEL_GEN(i915) != 11 || !dig_port->tc_legacy_port) { + enum intel_display_power_domain aux_domain; + bool aux_powered; + + aux_domain = intel_aux_power_domain(dig_port); + aux_powered = intel_display_power_is_enabled(i915, aux_domain); + WARN_ON(aux_powered); + } icl_tc_phy_disconnect(dig_port); icl_tc_phy_connect(dig_port, required_lanes); @@ -412,9 +449,11 @@ intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port, void intel_tc_port_sanitize(struct intel_digital_port *dig_port) { struct intel_encoder *encoder = &dig_port->base; + intel_wakeref_t tc_cold_wref; int active_links = 0; mutex_lock(&dig_port->tc_lock); + tc_cold_wref = tc_cold_block(dig_port); dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); if (dig_port->dp.is_mst) @@ -439,6 +478,7 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port) dig_port->tc_port_name, tc_port_mode_name(dig_port->tc_mode)); + tc_cold_unblock(dig_port, tc_cold_wref); mutex_unlock(&dig_port->tc_lock); } @@ -460,10 +500,15 @@ static bool intel_tc_port_needs_reset(struct intel_digital_port *dig_port) bool intel_tc_port_connected(struct intel_digital_port *dig_port) { bool is_connected; + intel_wakeref_t tc_cold_wref; intel_tc_port_lock(dig_port); + tc_cold_wref = tc_cold_block(dig_port); + is_connected = tc_port_live_status_mask(dig_port) & BIT(dig_port->tc_mode); + + tc_cold_unblock(dig_port, tc_cold_wref); intel_tc_port_unlock(dig_port); return is_connected; @@ -479,9 +524,16 @@ static void __intel_tc_port_lock(struct intel_digital_port *dig_port, mutex_lock(&dig_port->tc_lock); - if (!dig_port->tc_link_refcount && - intel_tc_port_needs_reset(dig_port)) - intel_tc_port_reset_mode(dig_port, required_lanes); + if (!dig_port->tc_link_refcount) { + intel_wakeref_t tc_cold_wref; + + tc_cold_wref = tc_cold_block(dig_port); + + if (intel_tc_port_needs_reset(dig_port)) + intel_tc_port_reset_mode(dig_port, required_lanes); + + tc_cold_unblock(dig_port, tc_cold_wref); + } WARN_ON(dig_port->tc_lock_wakeref); dig_port->tc_lock_wakeref = wakeref; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c111bdf498bc..edbdb7a2172c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8826,6 +8826,7 @@ enum { #define ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point) (((point) << 16) | (0x1 << 8)) #define GEN6_PCODE_READ_D_COMP 0x10 #define GEN6_PCODE_WRITE_D_COMP 0x11 +#define ICL_PCODE_EXIT_TCCOLD 0x12 #define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17 #define DISPLAY_IPS_CONTROL 0x19 /* See also IPS_CTL */