From nobody Sun Feb 8 00:34:43 2026 Received: from mail-wr1-f66.google.com (mail-wr1-f66.google.com [209.85.221.66]) (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 01E341F4634 for ; Thu, 18 Dec 2025 00:19:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766017185; cv=none; b=l6uRbfpUnqrkru+0X+BsFsqYulhuLkrBnczAyIMVPLM+oxL4cUqUBhwa4hVl4gEBzCoGYiWHhCg3q3I2ZE+t19rd6DX/KgJxZ7xwEfPF6YvryZDNz7jPgx3gf1Em6+F1OEGAQqdRb89hW534sBqVqtwgOxDwwmW0GLV8BpW+gh0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766017185; c=relaxed/simple; bh=MWwdmCJQUimtCRSKhTPNjOdSH8ty9Q7hQ/j7WkOhuO0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=lZFH5/jU+KxnnS3HVcwnoKx8sF+BBdd/CeiRtLTqZTd1gvYWjmPS+oKXbVtcvMGzV8zxNKxerLRbWQUd/5Cuo04VwGpFiDLjY0vITHordJFSsnUL7EptoPfNt0TrGkr5rQXrUmlRRNp75Ksy763JBuaBzJm1qQjbfY/e2QD5AiI= 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=N1WjChcD; arc=none smtp.client-ip=209.85.221.66 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="N1WjChcD" Received: by mail-wr1-f66.google.com with SMTP id ffacd0b85a97d-42e2d02a3c9so15057f8f.3 for ; Wed, 17 Dec 2025 16:19:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766017181; x=1766621981; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:from:to:cc:subject:date:message-id:reply-to; bh=3kUVQaLKncxiRp/vqoDgQl5p2NRR1lum8QhNB8KPTe8=; b=N1WjChcD5JFPreyA8VCEkWh6Jz3zHBxr/fuzDvSvIg3G9BquHB8Qx7UC1W5URarAGb QT2e5xxC6WqfKiNajUXuA5gEz273dQyaEwIQz57SC46n1j28tHoTsKecHLTBT+ECpWLV 9TB4SFkpqUJ9hrMqhFo0+J429BnEc8rbwL1bXuMJmWYwaeCqbGmTOGzDD+CLNWiCXFYt Mc8wkG/u64rqhb2/hrTCN8pL1as1hysJUAMYfxilrn/RUJxlJ7EGOPrsOeDZgPLZWnIo XDOiYCfr2ZnkBvGjzJXU7F0KPDuS3Npd0yb15HoSGTvpC8tDg7MhmTYB5KwgjwPkCIb6 D0Zw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766017181; x=1766621981; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=3kUVQaLKncxiRp/vqoDgQl5p2NRR1lum8QhNB8KPTe8=; b=Bv7vWsZWEAo5OEzfNY4NKz9qAQ5688/pIJR60DyGQ/Y8Nn2xQ2XhjP/gTfvXuwTVOj HzEqzGTA0sdFvBYoCT2LUOQdqoZy7V2FoWvgEXVIuuibKIDRanjKUQm6kk7FwankxdPh xtqwMG6+CuhKoZmIzvKxqsAqy5VfUrnZxfSwW2cyBN+4MaPV/mhUNXp/u1I/1NX+Cskq AoBlM8d31XfUfVlV5+H+jq5N035hP2DnpawRtZ9o+boIsEriwB236N3uPtZTetwqtxfC UcPeu9YNZdE3pNe1B5fa2XgW2ettFztGCI1owmQGuUf5YYadXDI+u6YUtRJFqui2cudU 3FCw== X-Forwarded-Encrypted: i=1; AJvYcCVOuoOn4NRFCL5vRYLJ1SkWz3NW9NtgRR8p9cyhpWLrR6qvcf38IKG47Bfo0T4dBAowCU0mvi60UrJth+c=@vger.kernel.org X-Gm-Message-State: AOJu0YwlVUU8pgURHnAtrERUgmxqwoIhIka1t6yq90y1aGGw/n6jrBd+ iC+4FOejr+QD6jTyxuEC3ZLTXaFa06Gg2OhEtUmZD+xku1WjAqNU1nx8 X-Gm-Gg: AY/fxX4+gZrkc1XFeNWVs71dNS5SNbuGSx0xGWq2e0wlubblZveoGgZNaZYZazKl0bQ 5z0Yfdm2EOWuF++O3ydUEJsL3pi4tKurpncIPzhQzJUEL3/rTaPuvfuFbj5RF/ac2Vzi7YQIJ40 DAjKfbHpyqUN2xOSYZEs9IGByih3Z7zQ6K5ldLh5PoqUlfigj/nygPmMI1oMqNES9ayj1rIsVHW Tt3GJ/h1wRFaGevAInMKGOXjtZ/sUwQ9TPJGEAOdtdm4VIE4mH0sy+Yrez8c8DMSa4k4sTxNlQt lKI7lSUjpx1yc/TufoclP0VWJ/uALfdvMpOJoyLEx+oODEhN2N8h8RVUmPwGoqGnO+MAF7gmwtT a6c9kgTfzsUliTV1rg0zasOXsAwwMwyfZKi4z8jUtiPW5LgT187hY/Q6+yNJv669tSsLMmIALpS DFVnRDeNqjr8W8d6iUckCbc0ZjatoWBNyAmsw9oBJAr4c+EYVtft4xXKZs+Hua4ep4vn910w== X-Google-Smtp-Source: AGHT+IHpXOK6G9ypAXb1YFAcTnbHKHq1QrwSCQMOelXbJG6LwWV50H/93CE5g/zG6iKkk+5NqSaRVQ== X-Received: by 2002:a05:6000:144e:b0:431:66a:cbc3 with SMTP id ffacd0b85a97d-431066acfc6mr6234585f8f.6.1766017181032; Wed, 17 Dec 2025 16:19:41 -0800 (PST) Received: from [192.168.1.5] (92.40.201.212.threembb.co.uk. [92.40.201.212]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-4324498f8fcsm1736920f8f.24.2025.12.17.16.19.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Dec 2025 16:19:40 -0800 (PST) From: Dale Whinham Date: Thu, 18 Dec 2025 00:19:32 +0000 Subject: [PATCH v2] drm/msm/dp: Enable support for eDP v1.4+ link rates table Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251218-drm-msm-edp14-v2-1-2e56c2338ab1@gmail.com> X-B4-Tracking: v=1; b=H4sIAJNIQ2kC/3XMQQrCMBCF4auUWRtxYlKCK+8hXYTJtB0wbUkkK CV3N3bv8nvw/h0yJ+EMt26HxEWyrEuDPnVAs18mVhKaQV+0RY1GhRRVzFFx2JrcaAL1NtDVeGi fLfEo76P3GJpnya81fY58wd/6r1RQoTI2sCPsHTHdp+jleaY1wlBr/QIThsWHqgAAAA== X-Change-ID: 20251214-drm-msm-edp14-8f4dc65dc34a To: Rob Clark , Dmitry Baryshkov , Abhinav Kumar , Jessica Zhang , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org, Dale Whinham , =?utf-8?q?J=C3=A9r=C3=B4me_de_Bretagne?= , Steev Klimaszewski X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1766017179; l=8706; i=daleyo@gmail.com; s=20251214; h=from:subject:message-id; bh=MWwdmCJQUimtCRSKhTPNjOdSH8ty9Q7hQ/j7WkOhuO0=; b=f0edPEKpkgbHI5mZQN3mY3VQIh3N25NN+HNlwzJPp1EwfvqNNICpubZI6gIYXI0B4H6wcA3qU PWh8iNH82egB+ECHp4FI7Ui56p7Cu9wvDUkHJlex/eoWq8ag3L9+Yye X-Developer-Key: i=daleyo@gmail.com; a=ed25519; pk=M4mvgx1TB2TniKaedTDsO3PbLKgFosJuegXRXPbn2Ds= The MSM DRM driver currently does not support panels which report their supported link rates via the SUPPORTED_LINK_RATES table. For panels which do not offer the optional eDP v1.3 fallback via MAX_LINK_RATE, this will cause a panel probe failure (e.g. Samsung ATNA30DW01-1 as found in Microsoft Surface Pro 11). Detect eDP v1.4 panels and parse the SUPPORTED_LINK_RATES table when present. Additionally, set the rate using LINK_RATE_SET instead of LINK_BW_SET, but only if LINK_BW_SET hasn't already been written to. Signed-off-by: Dale Whinham Tested-by: J=C3=A9r=C3=B4me de Bretagne Tested-by: Steev Klimaszewski Reviewed-by: Dmitry Baryshkov --- Changes in v2: - Re-ordered writing of LANE_COUNT_SET/LINK_BW_SET registers to match i915 = [Dmitry] - Fix detection of eDP by reading EDP_CONFIGURATION_CAP and EDP_REV (in v1 = we were mistakenly checking DPCD_REV) [Dmitry] - Link to v1: https://lore.kernel.org/r/20251214-drm-msm-edp14-v1-1-45de8c1= 68cec@gmail.com --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 56 ++++++++++++++--------- drivers/gpu/drm/msm/dp/dp_link.h | 3 ++ drivers/gpu/drm/msm/dp/dp_panel.c | 93 ++++++++++++++++++++++++++++++++++-= ---- 3 files changed, 120 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_c= trl.c index cbcc7c2f0ffc..aa2303d0e148 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -175,20 +175,28 @@ static inline void msm_dp_write_link(struct msm_dp_ct= rl_private *ctrl, static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, struct msm_dp_link_info *link) { - u8 values[2]; + u8 lane_count, bw_code; int err; =20 - values[0] =3D drm_dp_link_rate_to_bw_code(link->rate); - values[1] =3D link->num_lanes; + lane_count =3D link->num_lanes; =20 if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING) - values[1] |=3D DP_LANE_COUNT_ENHANCED_FRAME_EN; + lane_count |=3D DP_LANE_COUNT_ENHANCED_FRAME_EN; =20 - err =3D drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values)); + err =3D drm_dp_dpcd_writeb(aux, DP_LANE_COUNT_SET, lane_count); if (err < 0) return err; =20 - return 0; + if (link->use_rate_set) { + DRM_DEBUG_DP("using LINK_RATE_SET: 0x%02x", link->rate_set); + err =3D drm_dp_dpcd_writeb(aux, DP_LINK_RATE_SET, link->rate_set); + } else { + bw_code =3D drm_dp_link_rate_to_bw_code(link->rate); + DRM_DEBUG_DP("using LINK_BW_SET: 0x%02x", bw_code); + err =3D drm_dp_dpcd_writeb(aux, DP_LINK_BW_SET, bw_code); + } + + return err; } =20 /* @@ -1474,26 +1482,32 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_c= trl_private *ctrl, static int msm_dp_ctrl_link_rate_down_shift(struct msm_dp_ctrl_private *ct= rl) { int ret =3D 0; + struct msm_dp_link_info *link_params =3D &ctrl->link->link_params; =20 - switch (ctrl->link->link_params.rate) { - case 810000: - ctrl->link->link_params.rate =3D 540000; - break; - case 540000: - ctrl->link->link_params.rate =3D 270000; - break; - case 270000: - ctrl->link->link_params.rate =3D 162000; - break; - case 162000: - default: - ret =3D -EINVAL; - break; + if (link_params->rate_set) { + --link_params->rate_set; + link_params->rate =3D link_params->supported_rates[link_params->rate_set= ]; + } else { + switch (link_params->rate) { + case 810000: + link_params->rate =3D 540000; + break; + case 540000: + link_params->rate =3D 270000; + break; + case 270000: + link_params->rate =3D 162000; + break; + case 162000: + default: + ret =3D -EINVAL; + break; + } } =20 if (!ret) { drm_dbg_dp(ctrl->drm_dev, "new rate=3D0x%x\n", - ctrl->link->link_params.rate); + link_params->rate); } =20 return ret; diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_l= ink.h index b1eb2de6d2a7..725e08f75574 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -17,6 +17,9 @@ struct msm_dp_link_info { unsigned char revision; unsigned int rate; + unsigned int supported_rates[DP_MAX_SUPPORTED_RATES]; + unsigned int rate_set; + bool use_rate_set; unsigned int num_lanes; unsigned long capabilities; }; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_= panel.c index ad5d55bf009d..891211b23202 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -13,6 +13,8 @@ #include =20 #include +#include +#include =20 #define DP_INTF_CONFIG_DATABUS_WIDEN BIT(4) =20 @@ -107,29 +109,98 @@ static int msm_dp_panel_read_dpcd(struct msm_dp_panel= *msm_dp_panel) drm_dbg_dp(panel->drm_dev, "max_lanes=3D%d max_link_rate=3D%d\n", link->max_dp_lanes, link->max_dp_link_rate); =20 - link_info->rate =3D drm_dp_max_link_rate(dpcd); + max_lttpr_lanes =3D drm_dp_lttpr_max_lane_count(link->lttpr_common_caps); + max_lttpr_rate =3D drm_dp_lttpr_max_link_rate(link->lttpr_common_caps); + + /* eDP sink */ + if (msm_dp_panel->dpcd[DP_EDP_CONFIGURATION_CAP]) { + u8 edp_rev; + + rc =3D drm_dp_dpcd_read_byte(panel->aux, DP_EDP_DPCD_REV, &edp_rev); + if (rc) + return rc; + + drm_dbg_dp(panel->drm_dev, "edp_rev=3D0x%x\n", edp_rev); + + /* For eDP v1.4+, parse the SUPPORTED_LINK_RATES table */ + if (edp_rev >=3D DP_EDP_14) { + __le16 rates[DP_MAX_SUPPORTED_RATES]; + u8 bw_set; + int i; + + rc =3D drm_dp_dpcd_read_data(panel->aux, DP_SUPPORTED_LINK_RATES, + rates, sizeof(rates)); + if (rc) + return rc; + + rc =3D drm_dp_dpcd_read_byte(panel->aux, DP_LINK_BW_SET, &bw_set); + if (rc) + return rc; + + /* Find index of max supported link rate that does not exceed dtsi limi= ts */ + for (i =3D 0; i < ARRAY_SIZE(rates); i++) { + /* + * The value from the DPCD multiplied by 200 gives + * the link rate in kHz. Divide by 10 to convert to + * symbol rate, accounting for 8b/10b encoding. + */ + u32 rate =3D (le16_to_cpu(rates[i]) * 200) / 10; + + if (!rate) + break; + + drm_dbg_dp(panel->drm_dev, + "SUPPORTED_LINK_RATES[%d]: %d\n", i, rate); + + /* + * Limit link rate from link-frequencies of endpoint + * property of dtsi + */ + if (rate > link->max_dp_link_rate) + break; + + /* Limit link rate from LTTPR capabilities, if any */ + if (max_lttpr_rate && rate > max_lttpr_rate) + break; + + link_info->rate =3D rate; + link_info->supported_rates[i] =3D rate; + link_info->rate_set =3D i; + } + + /* Only use LINK_RATE_SET if LINK_BW_SET hasn't already been written to= */ + if (!bw_set && link_info->rate) + link_info->use_rate_set =3D true; + } + } + + /* Fall back on MAX_LINK_RATE/LINK_BW_SET (DP, eDP <=3D v1.3) */ + if (!link_info->rate) { + link_info->rate =3D drm_dp_max_link_rate(dpcd); + + /* Limit link rate from link-frequencies of endpoint property of dtsi */ + if (link_info->rate > link->max_dp_link_rate) + link_info->rate =3D link->max_dp_link_rate; + + /* Limit link rate from LTTPR capabilities, if any */ + if (max_lttpr_rate && max_lttpr_rate < link_info->rate) + link_info->rate =3D max_lttpr_rate; + } + link_info->num_lanes =3D drm_dp_max_lane_count(dpcd); =20 /* Limit data lanes from data-lanes of endpoint property of dtsi */ if (link_info->num_lanes > link->max_dp_lanes) link_info->num_lanes =3D link->max_dp_lanes; =20 - /* Limit link rate from link-frequencies of endpoint property of dtsi */ - if (link_info->rate > link->max_dp_link_rate) - link_info->rate =3D link->max_dp_link_rate; - /* Limit data lanes from LTTPR capabilities, if any */ - max_lttpr_lanes =3D drm_dp_lttpr_max_lane_count(panel->link->lttpr_common= _caps); if (max_lttpr_lanes && max_lttpr_lanes < link_info->num_lanes) link_info->num_lanes =3D max_lttpr_lanes; =20 - /* Limit link rate from LTTPR capabilities, if any */ - max_lttpr_rate =3D drm_dp_lttpr_max_link_rate(panel->link->lttpr_common_c= aps); - if (max_lttpr_rate && max_lttpr_rate < link_info->rate) - link_info->rate =3D max_lttpr_rate; - drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor); drm_dbg_dp(panel->drm_dev, "link_rate=3D%d\n", link_info->rate); + drm_dbg_dp(panel->drm_dev, "link_rate_set=3D%d\n", link_info->rate_set); + drm_dbg_dp(panel->drm_dev, "use_rate_set=3D%d\n", link_info->use_rate_set= ); drm_dbg_dp(panel->drm_dev, "lane_count=3D%d\n", link_info->num_lanes); =20 if (drm_dp_enhanced_frame_cap(dpcd)) --- base-commit: 7bc29d5fb6faff2f547323c9ee8d3a0790cd2530 change-id: 20251214-drm-msm-edp14-8f4dc65dc34a Best regards, --=20 Dale Whinham