From patchwork Tue Mar 11 23:38:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksandrs Vinarskis X-Patchwork-Id: 872528 Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6BA71F09B4; Tue, 11 Mar 2025 23:41:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741736479; cv=none; b=Vu5x2mcKp7pknaS4ZzVt8BWC3EBVSYI9OLyMiGhHNamSutr5eRF3OH+bs+aqj2UwB1JYNM55uRlQ5Z6tI9yUQWCLp9OvaN+bM/O72S1Y7prbcOTXOayiDts44beCCkk3dlh1Qn9j4P6TF3Ctapcsv2ZvZTnmtZgJaDFFX5jyKDw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741736479; c=relaxed/simple; bh=OyUUgOWlnDebmz4S1DRu13bg5gOUB5HPBWPcU0aM6QY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lONT77g5b/GipkgLCvBlREkR6GrEQldi/kojfgE1NJKXn5JBuZtT//1Mav0Gc3G4p08tA8AmWCV9LR+xoCmh6T2u/kfSpySE3uVaOGaENXJ/F3v3WUpc73+pLXmIG/RVS9/m9tm6zrn7pfnyCPITqXJH7cXo6Szmq6WZx1GZ2Dw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=guks1As+; arc=none smtp.client-ip=209.85.221.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="guks1As+" Received: by mail-wr1-f54.google.com with SMTP id ffacd0b85a97d-39104c1cbbdso3016591f8f.3; Tue, 11 Mar 2025 16:41:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741736476; x=1742341276; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=M4l/oaCQRVDlXaGgtOTR3rjmRlzQQJyPgMUHku9RrsM=; b=guks1As+3zM1R+yslRrFexsb0uB6nHLbHt8P/N+7jFW7YjS1bJj8p6QSnMp7j3u59j FTCvWCeo/7Zw2NQ3SRma9Wz8TfqdoQjXUWuzxiU0ubhIy6IUsl7p+qQn//NhXMk++k7r 2xxJzHAeegMFnTWt9V/Ue6S96iic9e7+UQpW2EJoffwi+UFUvzUd8PhqrojqbYb8gdi/ X1x8OTI6AFXSDUiGk0b60P9+N1ZxjiDvPy+82aPx3evmwrZkSyab2ITA1ANR+FYUcmcJ z1uzooAXT2wCRasAujW48YB16SShtlJPKxQnS0+/DF5F9r+GA2r0Z77h/u3oEwzSFcdS h9Uw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741736476; x=1742341276; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=M4l/oaCQRVDlXaGgtOTR3rjmRlzQQJyPgMUHku9RrsM=; b=FhatLkwCQrTKvYBWcPB0gmSiW2OFUIpqM5vzdkivraJ7D+6/tHcD9EdIWBid0teIxz Z6qMhNUjvZv4W84g14o0iv+nJTziDCcoRPDj2T4vh+86C4qQsg2xD9atyDkirWJ7G9QH t/SM31K7HZCDJV3/H+upppzqVuCAH3RgPM5Iqk/CGioSAb5NO/6ZnXdwKeNLbDyJR6m+ jJz1iXKjqhY5dRl/kezK9YdfHfoNskf9STDhc12H3T9MnK4sC3bS6oeSlMaKRm52Pamv d+VPr8whcEKola2Pq+11RQVoJ1HO+ELJ2zPqy7bL1EUapmQodTfUruJIymGS4bpHW1fX cv/Q== X-Forwarded-Encrypted: i=1; AJvYcCU5cjQGYXEzULh7L511ZHlizul+toJ5H9D7yX3lIBgAKbo+IZvH1PHbYCuKXP/3lcEferY79b/kPvf2bK1h@vger.kernel.org, AJvYcCXwwUhy2VDnKD4mHG8Nj26cFqAtwd8XIwDhszL9/lZiuJ4AS1pKUfRRvUc2RuBa1yr2EhjnByRoF00p5zKG@vger.kernel.org X-Gm-Message-State: AOJu0YwrJijcP/kGespDTmRZrAW31MX6GK9RInfipPRk0RoWuC7ZO+U0 eT4aUTva78VEsw5ua8cZ9M5tj9lRUyiE49AuUt7frOJ0uyAzZJ8= X-Gm-Gg: ASbGncumGe8L1UvYDIA8m91WAxR4F/kTMV1XCeJ6K596sQC/mhuLvfLF1inxkyw+iqR jAmibz9ZJ1NzXuOc4rFCMehmoRY8hXXsroSJdO+u4zpNpZLyW6Y88fcaAGrdS7uy0isR9AGDuwc zCRtVqJODD3vO9U+WkgG/eUtCJYJjv9wUs0CD5Jyw0rnFgme72+wW6mCVcfgQkuG3beoNdK6VF4 6X27//7A0CmWQfDygMJ4hg0F/BLTBqiYONiH5HGUTR3POgqUsTtUKCslIYBLy9cQ0H/j0jSE1CN tLlJCeJ1MyOwUySKs98vFdJG5XLtMxn3gUL+xcY8Mlg56PNi6/MhAVx1NQfOx7LDZJbPMREDJt4 LHkf3iA== X-Google-Smtp-Source: AGHT+IHB9g+En0CWc1s3jiznwqoGbtpaeJW2BYwZ/bRVnWuTmdukJCDX5lWiuhj/D6s9X3feftILPQ== X-Received: by 2002:adf:b197:0:b0:394:570b:aab6 with SMTP id ffacd0b85a97d-394570bac03mr217849f8f.37.1741736475279; Tue, 11 Mar 2025 16:41:15 -0700 (PDT) Received: from alex-x1e.lan (adsl-178-39-53-103.adslplus.ch. [178.39.53.103]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d0a72ea88sm3988345e9.7.2025.03.11.16.41.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Mar 2025 16:41:15 -0700 (PDT) From: Aleksandrs Vinarskis To: Dmitry Baryshkov , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org Cc: Rob Clark , Abhinav Kumar , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , laurentiu.tudor1@dell.com, abel.vesa@linaro.org, johan@kernel.org, Aleksandrs Vinarskis Subject: [PATCH v2 1/2] drm/msm/dp: Fix support of LTTPR handling Date: Wed, 12 Mar 2025 00:38:03 +0100 Message-ID: <20250311234109.136510-2-alex.vinarskis@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250311234109.136510-1-alex.vinarskis@gmail.com> References: <20250311234109.136510-1-alex.vinarskis@gmail.com> Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Take into account LTTPR capabilities when selecting maximum allowed link rate, number of data lines. Initialize LTTPR before msm_dp_panel_read_sink_caps, as a) Link params computation need to take into account LTTPR's caps b) It appears DPTX shall (re)read DPRX caps after LTTPR detection Return lttpr_count to prepare for per-segment link training. Signed-off-by: Aleksandrs Vinarskis Reviewed-by: Abel Vesa --- drivers/gpu/drm/msm/dp/dp_display.c | 29 +++++++++++++++++++--------- drivers/gpu/drm/msm/dp/dp_panel.c | 30 ++++++++++++++++++++--------- drivers/gpu/drm/msm/dp/dp_panel.h | 2 ++ 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index bbc47d86ae9e..d0c2dc7e6648 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -108,6 +108,8 @@ struct msm_dp_display_private { struct msm_dp_event event_list[DP_EVENT_Q_MAX]; spinlock_t event_lock; + u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE]; + bool wide_bus_supported; struct msm_dp_audio *audio; @@ -367,17 +369,21 @@ static int msm_dp_display_send_hpd_notification(struct msm_dp_display_private *d return 0; } -static void msm_dp_display_lttpr_init(struct msm_dp_display_private *dp) +static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd) { - u8 lttpr_caps[DP_LTTPR_COMMON_CAP_SIZE]; - int rc; + int rc, lttpr_count; - if (drm_dp_read_lttpr_common_caps(dp->aux, dp->panel->dpcd, lttpr_caps)) - return; + if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, dp->lttpr_common_caps)) + return 0; - rc = drm_dp_lttpr_init(dp->aux, drm_dp_lttpr_count(lttpr_caps)); - if (rc) + lttpr_count = drm_dp_lttpr_count(dp->lttpr_common_caps); + rc = drm_dp_lttpr_init(dp->aux, lttpr_count); + if (rc) { DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", rc); + return 0; + } + + return lttpr_count; } static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) @@ -385,12 +391,17 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) struct drm_connector *connector = dp->msm_dp_display.connector; const struct drm_display_info *info = &connector->display_info; int rc = 0; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; - rc = msm_dp_panel_read_sink_caps(dp->panel, connector); + rc = drm_dp_read_dpcd_caps(dp->aux, dpcd); if (rc) goto end; - msm_dp_display_lttpr_init(dp); + msm_dp_display_lttpr_init(dp, dpcd); + + rc = msm_dp_panel_read_sink_caps(dp->panel, dp->lttpr_common_caps, connector); + if (rc) + goto end; msm_dp_link_process_request(dp->link); diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 92415bf8aa16..f41b4cf7002e 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -45,9 +45,12 @@ static void msm_dp_panel_read_psr_cap(struct msm_dp_panel_private *panel) } } -static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) +static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel, + const u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE]) { int rc; + int max_sink_lanes, max_source_lanes, max_lttpr_lanes; + int max_sink_rate, max_source_rate, max_lttpr_rate; struct msm_dp_panel_private *panel; struct msm_dp_link_info *link_info; u8 *dpcd, major, minor; @@ -64,16 +67,24 @@ static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) major = (link_info->revision >> 4) & 0x0f; minor = link_info->revision & 0x0f; - link_info->rate = drm_dp_max_link_rate(dpcd); - link_info->num_lanes = drm_dp_max_lane_count(dpcd); + max_source_lanes = msm_dp_panel->max_dp_lanes; + max_source_rate = msm_dp_panel->max_dp_link_rate; - /* Limit data lanes from data-lanes of endpoint property of dtsi */ - if (link_info->num_lanes > msm_dp_panel->max_dp_lanes) - link_info->num_lanes = msm_dp_panel->max_dp_lanes; + max_sink_lanes = drm_dp_max_lane_count(dpcd); + max_sink_rate = drm_dp_max_link_rate(dpcd); + + max_lttpr_lanes = drm_dp_lttpr_max_lane_count(lttpr_common_caps); + max_lttpr_rate = drm_dp_lttpr_max_link_rate(lttpr_common_caps); + if (max_lttpr_lanes) + max_sink_lanes = min(max_sink_lanes, max_lttpr_lanes); + if (max_lttpr_rate) + max_sink_rate = min(max_sink_rate, max_lttpr_rate); + + /* Limit data lanes from data-lanes of endpoint property of dtsi */ + link_info->num_lanes = min(max_sink_lanes, max_source_lanes); /* Limit link rate from link-frequencies of endpoint property of dtsi */ - if (link_info->rate > msm_dp_panel->max_dp_link_rate) - link_info->rate = msm_dp_panel->max_dp_link_rate; + link_info->rate = min(max_sink_rate, max_source_rate); drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor); drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate); @@ -109,6 +120,7 @@ static u32 msm_dp_panel_get_supported_bpp(struct msm_dp_panel *msm_dp_panel, } int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, + const u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE], struct drm_connector *connector) { int rc, bw_code; @@ -125,7 +137,7 @@ int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, drm_dbg_dp(panel->drm_dev, "max_lanes=%d max_link_rate=%d\n", msm_dp_panel->max_dp_lanes, msm_dp_panel->max_dp_link_rate); - rc = msm_dp_panel_read_dpcd(msm_dp_panel); + rc = msm_dp_panel_read_dpcd(msm_dp_panel, lttpr_common_caps); if (rc) { DRM_ERROR("read dpcd failed %d\n", rc); return rc; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 4906f4f09f24..d89e17a9add5 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -7,6 +7,7 @@ #define _DP_PANEL_H_ #include +#include #include "dp_aux.h" #include "dp_link.h" @@ -49,6 +50,7 @@ int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel); int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel); int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel); int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, + const u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE], struct drm_connector *connector); u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp, u32 mode_pclk_khz); From patchwork Tue Mar 11 23:38:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksandrs Vinarskis X-Patchwork-Id: 872873 Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DDB2F233153; Tue, 11 Mar 2025 23:41:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741736481; cv=none; b=m5nVEyTy9EdXb5MW4JQbgHcFGkTM8iYg26w5SqJIhPWRL4fuPwGCKDQOoYWHCbn0sLA9fWo0jXJx4H4DjhCq1xtAbQVu228U472tzFUL+yOkd8Htt85CekN8frZlCdARFgP9ny3i9V0ktIeIqNNRcaTe2RcNYZneAye6t2TCjSs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741736481; c=relaxed/simple; bh=y/xbpRBmppnFp/8l9KodJ/bO27vFGwbZLfXzBMfGDfs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cZCSb+87tiUQzE0sXQj45l/xrPcznZYKBzxrMDZW7lCwckntJmvvAsjajkjT4Tek8PMCNzIFDewxrai8pEk+1E+OMaXowVASfQDqjnKgsjZ9cdCOGa8YrTPsfcKTvMQCXSqkz1N8v7kKF7b/iX913/ZgiVV1T0GACRhFDG6CNwg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=IJkb1i9Y; arc=none smtp.client-ip=209.85.128.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IJkb1i9Y" Received: by mail-wm1-f43.google.com with SMTP id 5b1f17b1804b1-43690d4605dso37809555e9.0; Tue, 11 Mar 2025 16:41:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741736476; x=1742341276; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=eX7SOrrBoNTjTEGxb8kT2VfXVXA7PfnzBcp2MvNlsF8=; b=IJkb1i9YkSXwZTQtpOkT1hxq4dXkbLCybFfdI5gnZH/xJLsBI5PYMbDxfd1TiSdKnc Y9DRG4jiL1vlcjpwmvF2QORcAqWnAAbOdMLwRwN7TO+U1IX2raT+aIfgfUznNLEo2T5E 4iW8eORy8hbFmOtaSD0qnNtdnLSVYI4ESU9yY/Lt9qaj/RlU6Q/YdrshGi4fg60kcsWY DKzD0HcxTEAru/Llk2YXOo471OaUfO7Sp5jC5Y9nqxBGoYY4DDN/R49H15Pg2T4qtlGl w9dq+CFsKhW+jAkUqpf38pz+PbvOVfvGRZ2iKCFNuV/fJiuoTLYiLoi3Xnp3jkj+Qh8d 59aw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741736476; x=1742341276; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eX7SOrrBoNTjTEGxb8kT2VfXVXA7PfnzBcp2MvNlsF8=; b=phQhqq6bcjQwC8iDt92JR9twlw4kFNUe1QxuKGlIe7hod6xBOq4hR4FFGfHuT6+UYw 5Z8NDM6MFRSw1UlgJsxPT7eYz1baElXMV3gBZEdXT3wRlkQdk+0SVjwnCjIExKZQrtuS ubPAP1gZQ4SIRrm4LMcGnVzlAkSDFHJQHt4t7XkliPaGNS0AHodh7tR5IOcrpnNpGLhO Kf1bdd459pKHiTwofaV9Cl7xSciZhryjMC2PAkdQOxlYxmJCgqt4gYeo6tSOdIQaxm1l oo852HXl2HqtDQYQT9esypMIKeO6j0IDCGX3ugmXH88kdoqmI3vChIiLOFuGQFmgE82I xmhw== X-Forwarded-Encrypted: i=1; AJvYcCWD+VX6WVLrSXKBRsK/M58L9qTbJDYQs1iRHJ50WJpKa0DvIGVosG1/hcTJBDtlsrsZ2kdU8fsZ4I+d+nlJ@vger.kernel.org, AJvYcCXLv5bN25zPHaA8/fKoWaoyaGomNppYXMis5zEU/3E5JWvsAo/PhbUZhet7Qnri6c21SlxX9tTSlLkzvLty@vger.kernel.org X-Gm-Message-State: AOJu0Yym7x28zrSSU/Cq+i55zkI9l1C/drdIfcJFtSP2ZW7ktXrLr6oX A78i9LM82+68WqCLKL8C8cqnXMibgJ1g46E347FOgGrsB6xakEo= X-Gm-Gg: ASbGnctxaPiPMCtc4rcAPgcDNyjVOH79PQ5KaiOtOUVCy6ARXII6nEPh7mP5zTu0zxQ kCY6urMt3KaaY9M1N+84j0OrUEgMitMYrpTKZ7SldH5lDh5ty7/U8WLUUCPUEJDUK3wMAiscRRN doWxX4n+ms8gyFkbdJTcAeWyW1zjrNEZxargmndXrRyDbnmJiWYj8+sy9VJ/jrseacVYqA+lbGO jRQoWM2A3lEmq+Z+rxYl1UyDfnHQEnU99u3qtLq+ErxChD9s/xI+Zu6elmUDTdZ2YwU4NFDUrx+ 5MkFXXoLNGpTsV/GnTO0jb8EMAnEz7lnKbGR8AdBiFb5LeFWSJ6/oztheiKmcSLqHS7ZtBUdcKA BhKY1Sg== X-Google-Smtp-Source: AGHT+IGHp6At2Jp4YGnh957BdyyOSkALG9t6GQL/m1Fd3Nt7shBgucH4fAaBu7D0vvwbqbufEGFeWA== X-Received: by 2002:a05:600c:3b9f:b0:43d:ea:51d2 with SMTP id 5b1f17b1804b1-43d00ea53e3mr87822275e9.14.1741736475954; Tue, 11 Mar 2025 16:41:15 -0700 (PDT) Received: from alex-x1e.lan (adsl-178-39-53-103.adslplus.ch. [178.39.53.103]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d0a72ea88sm3988345e9.7.2025.03.11.16.41.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Mar 2025 16:41:15 -0700 (PDT) From: Aleksandrs Vinarskis To: Dmitry Baryshkov , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org Cc: Rob Clark , Abhinav Kumar , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , laurentiu.tudor1@dell.com, abel.vesa@linaro.org, johan@kernel.org, Aleksandrs Vinarskis Subject: [PATCH v2 2/2] drm/msm/dp: Introduce link training per-segment for LTTPRs Date: Wed, 12 Mar 2025 00:38:04 +0100 Message-ID: <20250311234109.136510-3-alex.vinarskis@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250311234109.136510-1-alex.vinarskis@gmail.com> References: <20250311234109.136510-1-alex.vinarskis@gmail.com> Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 DisplayPort requires per-segment link training when LTTPR are switched to non-transparent mode, starting with LTTPR closest to the source. Only when each segment is trained individually, source can link train to sink. Implement per-segment link traning when LTTPR(s) are detected, to support external docking stations. On higher level, changes are: * Pass phy being trained down to all required helpers * Run CR, EQ link training per phy * Set voltage swing, pre-emphasis levels per phy This ensures successful link training both when connected directly to the monitor (single LTTPR onboard most X1E laptops) and via the docking station (at least two LTTPRs). Signed-off-by: Aleksandrs Vinarskis Reviewed-by: Abel Vesa --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 137 +++++++++++++++++++--------- drivers/gpu/drm/msm/dp/dp_ctrl.h | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 4 +- 3 files changed, 99 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index d8633a596f8d..419a519ccf6b 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -79,6 +79,8 @@ struct msm_dp_ctrl_private { struct msm_dp_link *link; struct msm_dp_catalog *catalog; + int *lttpr_count; + struct phy *phy; unsigned int num_core_clks; @@ -1034,9 +1036,11 @@ static int msm_dp_ctrl_set_vx_px(struct msm_dp_ctrl_private *ctrl, return 0; } -static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_update_phy_vx_px(struct msm_dp_ctrl_private *ctrl, + enum drm_dp_phy dp_phy) { struct msm_dp_link *link = ctrl->link; + int reg = DP_TRAINING_LANE0_SET; int ret = 0, lane, lane_cnt; u8 buf[4]; u32 max_level_reached = 0; @@ -1075,8 +1079,11 @@ static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) drm_dbg_dp(ctrl->drm_dev, "sink: p|v=0x%x\n", voltage_swing_level | pre_emphasis_level); - ret = drm_dp_dpcd_write(ctrl->aux, DP_TRAINING_LANE0_SET, - buf, lane_cnt); + + if (dp_phy != DP_PHY_DPRX) + reg = DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy); + + ret = drm_dp_dpcd_write(ctrl->aux, reg, buf, lane_cnt); if (ret == lane_cnt) ret = 0; @@ -1084,9 +1091,10 @@ static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) } static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl, - u8 pattern) + u8 pattern, enum drm_dp_phy dp_phy) { u8 buf; + int reg = DP_TRAINING_PATTERN_SET; int ret = 0; drm_dbg_dp(ctrl->drm_dev, "sink: pattern=%x\n", pattern); @@ -1096,7 +1104,10 @@ static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl, if (pattern && pattern != DP_TRAINING_PATTERN_4) buf |= DP_LINK_SCRAMBLING_DISABLE; - ret = drm_dp_dpcd_writeb(ctrl->aux, DP_TRAINING_PATTERN_SET, buf); + if (dp_phy != DP_PHY_DPRX) + reg = DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy); + + ret = drm_dp_dpcd_writeb(ctrl->aux, reg, buf); return ret == 1; } @@ -1115,12 +1126,16 @@ static int msm_dp_ctrl_read_link_status(struct msm_dp_ctrl_private *ctrl, } static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, enum drm_dp_phy dp_phy) { + int delay_us; int tries, old_v_level, ret = 0; u8 link_status[DP_LINK_STATUS_SIZE]; int const maximum_retries = 4; + delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); *training_step = DP_TRAINING_1; @@ -1129,18 +1144,19 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, if (ret) return ret; msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE); + DP_LINK_SCRAMBLING_DISABLE, dp_phy); - ret = msm_dp_ctrl_update_vx_px(ctrl); + msm_dp_link_reset_phy_params_vx_px(ctrl->link); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; tries = 0; old_v_level = ctrl->link->phy_params.v_level; for (tries = 0; tries < maximum_retries; tries++) { - drm_dp_link_train_clock_recovery_delay(ctrl->aux, ctrl->panel->dpcd); + fsleep(delay_us); - ret = msm_dp_ctrl_read_link_status(ctrl, link_status); + ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status); if (ret) return ret; @@ -1161,7 +1177,7 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, } msm_dp_link_adjust_levels(ctrl->link, link_status); - ret = msm_dp_ctrl_update_vx_px(ctrl); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; } @@ -1213,21 +1229,31 @@ static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) return 0; } -static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, + enum drm_dp_phy dp_phy) { - msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE); - drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd); + int delay_us; + + msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy); + + delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + fsleep(delay_us); } static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, enum drm_dp_phy dp_phy) { + int delay_us; int tries = 0, ret = 0; u8 pattern; u32 state_ctrl_bit; int const maximum_retries = 5; u8 link_status[DP_LINK_STATUS_SIZE]; + delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); *training_step = DP_TRAINING_2; @@ -1247,12 +1273,12 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, if (ret) return ret; - msm_dp_ctrl_train_pattern_set(ctrl, pattern); + msm_dp_ctrl_train_pattern_set(ctrl, pattern, dp_phy); for (tries = 0; tries <= maximum_retries; tries++) { - drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd); + fsleep(delay_us); - ret = msm_dp_ctrl_read_link_status(ctrl, link_status); + ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status); if (ret) return ret; @@ -1262,7 +1288,7 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, } msm_dp_link_adjust_levels(ctrl->link, link_status); - ret = msm_dp_ctrl_update_vx_px(ctrl); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; @@ -1271,10 +1297,32 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, return -ETIMEDOUT; } +static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, + int *training_step, enum drm_dp_phy dp_phy) +{ + int ret; + + ret = msm_dp_ctrl_link_train_1(ctrl, training_step, dp_phy); + if (ret) { + DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret); + return ret; + } + drm_dbg_dp(ctrl->drm_dev, "link training #1 on phy %d successful\n", dp_phy); + + ret = msm_dp_ctrl_link_train_2(ctrl, training_step, dp_phy); + if (ret) { + DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret); + return ret; + } + drm_dbg_dp(ctrl->drm_dev, "link training #2 on phy %d successful\n", dp_phy); + + return 0; +} + static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, int *training_step) { - int ret = 0; + int ret = 0, i; const u8 *dpcd = ctrl->panel->dpcd; u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; u8 assr; @@ -1286,8 +1334,6 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, link_info.rate = ctrl->link->link_params.rate; link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING; - msm_dp_link_reset_phy_params_vx_px(ctrl->link); - msm_dp_aux_link_configure(ctrl->aux, &link_info); if (drm_dp_max_downspread(dpcd)) @@ -1302,23 +1348,29 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, &assr, 1); } - ret = msm_dp_ctrl_link_train_1(ctrl, training_step); + for (i = *ctrl->lttpr_count - 1; i >= 0; i--) { + enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i); + + ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, dp_phy); + msm_dp_ctrl_clear_training_pattern(ctrl, dp_phy); + + if (ret) + break; + } + if (ret) { - DRM_ERROR("link training #1 failed. ret=%d\n", ret); + DRM_ERROR("link training of LTTPR(s) failed. ret=%d\n", ret); goto end; } - /* print success info as this is a result of user initiated action */ - drm_dbg_dp(ctrl->drm_dev, "link training #1 successful\n"); - - ret = msm_dp_ctrl_link_train_2(ctrl, training_step); + ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, DP_PHY_DPRX); if (ret) { - DRM_ERROR("link training #2 failed. ret=%d\n", ret); + DRM_ERROR("link training on sink failed. ret=%d\n", ret); goto end; } /* print success info as this is a result of user initiated action */ - drm_dbg_dp(ctrl->drm_dev, "link training #2 successful\n"); + drm_dbg_dp(ctrl->drm_dev, "link training on sink successful\n"); end: msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); @@ -1636,7 +1688,7 @@ static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) if (ret) goto end; - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); @@ -1660,7 +1712,7 @@ static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl) return false; } msm_dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested); - msm_dp_ctrl_update_vx_px(ctrl); + msm_dp_ctrl_update_phy_vx_px(ctrl, DP_PHY_DPRX); msm_dp_link_send_test_response(ctrl->link); pattern_sent = msm_dp_catalog_ctrl_read_phy_pattern(ctrl->catalog); @@ -1902,7 +1954,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) } /* stop link training before start re training */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); } rc = msm_dp_ctrl_reinitialize_mainlink(ctrl); @@ -1926,7 +1978,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) * link training failed * end txing train pattern here */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); msm_dp_ctrl_deinitialize_mainlink(ctrl); rc = -ECONNRESET; @@ -1997,7 +2049,7 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train msm_dp_ctrl_link_retrain(ctrl); /* stop txing train pattern to end link training */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); /* * Set up transfer unit values and set controller state to send @@ -2207,7 +2259,7 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, struct msm_dp_panel *panel, struct drm_dp_aux *aux, - struct msm_dp_catalog *catalog, + struct msm_dp_catalog *catalog, int *lttpr_count, struct phy *phy) { struct msm_dp_ctrl_private *ctrl; @@ -2242,12 +2294,13 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link init_completion(&ctrl->video_comp); /* in parameters */ - ctrl->panel = panel; - ctrl->aux = aux; - ctrl->link = link; - ctrl->catalog = catalog; - ctrl->dev = dev; - ctrl->phy = phy; + ctrl->panel = panel; + ctrl->aux = aux; + ctrl->link = link; + ctrl->catalog = catalog; + ctrl->dev = dev; + ctrl->phy = phy; + ctrl->lttpr_count = lttpr_count; ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl); if (ret) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index b7abfedbf574..3fb45b138b31 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -27,7 +27,7 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl); struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, struct msm_dp_panel *panel, struct drm_dp_aux *aux, - struct msm_dp_catalog *catalog, + struct msm_dp_catalog *catalog, int *lttpr_count, struct phy *phy); void msm_dp_ctrl_reset_irq_ctrl(struct msm_dp_ctrl *msm_dp_ctrl, bool enable); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index d0c2dc7e6648..393ce3479a7e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -108,6 +108,7 @@ struct msm_dp_display_private { struct msm_dp_event event_list[DP_EVENT_Q_MAX]; spinlock_t event_lock; + int lttpr_count; u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE]; bool wide_bus_supported; @@ -397,7 +398,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) if (rc) goto end; - msm_dp_display_lttpr_init(dp, dpcd); + dp->lttpr_count = msm_dp_display_lttpr_init(dp, dpcd); rc = msm_dp_panel_read_sink_caps(dp->panel, dp->lttpr_common_caps, connector); if (rc) @@ -798,6 +799,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, dp->catalog, + &dp->lttpr_count, phy); if (IS_ERR(dp->ctrl)) { rc = PTR_ERR(dp->ctrl);