[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250620093104.2016196-6-shiyongbang@huawei.com>
Date: Fri, 20 Jun 2025 17:30:59 +0800
From: Yongbang Shi <shiyongbang@...wei.com>
To: <xinliang.liu@...aro.org>, <tiantao6@...ilicon.com>,
<maarten.lankhorst@...ux.intel.com>, <mripard@...nel.org>,
<tzimmermann@...e.de>, <airlied@...il.com>, <daniel@...ll.ch>,
<kong.kongxinwei@...ilicon.com>, <dmitry.baryshkov@....qualcomm.com>
CC: <liangjian010@...wei.com>, <chenjianmin@...wei.com>,
<lidongming5@...wei.com>, <shiyongbang@...wei.com>, <libaihan@...wei.com>,
<shenjian15@...wei.com>, <shaojijie@...wei.com>,
<jani.nikula@...ux.intel.com>, <dri-devel@...ts.freedesktop.org>,
<linux-kernel@...r.kernel.org>
Subject: [PATCH v2 drm-dp 05/10] drm/hisilicon/hibmc: fix rare monitors cannot display problem
From: Baihan Li <libaihan@...wei.com>
In some case, the dp link training success at 8.1Gbps, but the sink's
maximum supported rate is less than 8.1G. So change the default 8.1Gbps
link rate to the rate that reads from devices' capabilities.
Fixes: 54063d86e036 ("drm/hisilicon/hibmc: add dp link moduel in hibmc drivers")
Signed-off-by: Baihan Li <libaihan@...wei.com>
Signed-off-by: Yongbang Shi <shiyongbang@...wei.com>
---
ChangeLog:
v1 -> v2:
- fix the tag, suggested by Dmitry Baryshkov.
- add explanations in commit, suggested by Dmitry Baryshkov.
---
drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h | 4 ++-
drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c | 6 +---
drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c | 33 +++++++++++++------
.../gpu/drm/hisilicon/hibmc/dp/dp_serdes.c | 12 -------
4 files changed, 27 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
index 4add05c7f161..18a961466ff0 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
@@ -25,6 +25,9 @@ struct hibmc_link_status {
struct hibmc_link_cap {
u8 link_rate;
u8 lanes;
+ int rx_dpcd_revision;
+ bool is_tps3;
+ bool is_tps4;
};
struct hibmc_dp_link {
@@ -62,7 +65,6 @@ struct hibmc_dp_dev {
void hibmc_dp_aux_init(struct hibmc_dp *dp);
int hibmc_dp_link_training(struct hibmc_dp_dev *dp);
-int hibmc_dp_serdes_init(struct hibmc_dp_dev *dp);
int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp);
int hibmc_dp_serdes_set_tx_cfg(struct hibmc_dp_dev *dp, u8 train_set[HIBMC_DP_LANE_NUM_MAX]);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
index 8a965e143012..98cc534ba794 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
@@ -154,7 +154,6 @@ int hibmc_dp_hw_init(struct hibmc_dp *dp)
{
struct drm_device *drm_dev = dp->drm_dev;
struct hibmc_dp_dev *dp_dev;
- int ret;
dp_dev = devm_kzalloc(drm_dev->dev, sizeof(struct hibmc_dp_dev), GFP_KERNEL);
if (!dp_dev)
@@ -166,13 +165,10 @@ int hibmc_dp_hw_init(struct hibmc_dp *dp)
dp_dev->dev = drm_dev;
dp_dev->base = dp->mmio + HIBMC_DP_OFFSET;
+ dp_dev->serdes_base = dp_dev->base + HIBMC_DP_HOST_OFFSET;
hibmc_dp_aux_init(dp);
- ret = hibmc_dp_serdes_init(dp_dev);
- if (ret)
- return ret;
-
dp_dev->link.cap.lanes = 0x2;
dp_dev->link.cap.link_rate = DP_LINK_BW_8_1;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
index 74f7832ea53e..6c69fa2ae9cf 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
@@ -39,6 +39,14 @@ static int hibmc_dp_link_training_configure(struct hibmc_dp_dev *dp)
/* enhanced frame */
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_FRAME_MODE, 0x1);
+ ret = hibmc_dp_get_serdes_rate_cfg(dp);
+ if (ret < 0)
+ return ret;
+
+ ret = hibmc_dp_serdes_rate_switch(ret, dp);
+ if (ret)
+ return ret;
+
/* set rate and lane count */
buf[0] = dp->link.cap.link_rate;
buf[1] = DP_LANE_COUNT_ENHANCED_FRAME_EN | dp->link.cap.lanes;
@@ -325,6 +333,20 @@ static int hibmc_dp_link_downgrade_training_eq(struct hibmc_dp_dev *dp)
return hibmc_dp_link_reduce_rate(dp);
}
+static void hibmc_dp_update_caps(struct hibmc_dp_dev *dp)
+{
+ dp->link.cap.rx_dpcd_revision = dp->dpcd[DP_DPCD_REV];
+
+ dp->link.cap.is_tps3 = (dp->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_13) &&
+ (dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED);
+ dp->link.cap.is_tps4 = (dp->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14) &&
+ (dp->dpcd[DP_MAX_DOWNSPREAD] & DP_TPS4_SUPPORTED);
+ dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE];
+ dp->link.cap.lanes = dp->dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
+ if (dp->link.cap.lanes > HIBMC_DP_LANE_NUM_MAX)
+ dp->link.cap.lanes = HIBMC_DP_LANE_NUM_MAX;
+}
+
int hibmc_dp_link_training(struct hibmc_dp_dev *dp)
{
struct hibmc_dp_link *link = &dp->link;
@@ -334,16 +356,7 @@ int hibmc_dp_link_training(struct hibmc_dp_dev *dp)
if (ret)
drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret);
- dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE];
- dp->link.cap.lanes = 0x2;
-
- ret = hibmc_dp_get_serdes_rate_cfg(dp);
- if (ret < 0)
- return ret;
-
- ret = hibmc_dp_serdes_rate_switch(ret, dp);
- if (ret)
- return ret;
+ hibmc_dp_update_caps(dp);
while (true) {
ret = hibmc_dp_link_training_cr_pre(dp);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c
index 676059d4c1e6..8191233aa965 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c
@@ -57,15 +57,3 @@ int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp)
return 0;
}
-
-int hibmc_dp_serdes_init(struct hibmc_dp_dev *dp)
-{
- dp->serdes_base = dp->base + HIBMC_DP_HOST_OFFSET;
-
- writel(FIELD_PREP(HIBMC_DP_PMA_TXDEEMPH, DP_SERDES_VOL0_PRE0),
- dp->serdes_base + HIBMC_DP_PMA_LANE0_OFFSET);
- writel(FIELD_PREP(HIBMC_DP_PMA_TXDEEMPH, DP_SERDES_VOL0_PRE0),
- dp->serdes_base + HIBMC_DP_PMA_LANE1_OFFSET);
-
- return hibmc_dp_serdes_rate_switch(DP_SERDES_BW_8_1, dp);
-}
--
2.33.0
Powered by blists - more mailing lists