Message ID | 20250210144959.100551-6-shiyongbang@huawei.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add HPD, getting EDID, colorbar features in DP function | expand |
On Mon, Feb 10, 2025 at 10:49:57PM +0800, Yongbang Shi wrote: > From: Baihan Li <libaihan@huawei.com> > > Prepare the hibmc_dp_get_foo() functions for debugfs using in > next patch. We also add dpcd's if statement in link training process, > because we have the dpcd. Unrelated, split to a separate patch. > > Signed-off-by: Baihan Li <libaihan@huawei.com> > Signed-off-by: Yongbang Shi <shiyongbang@huawei.com> > --- > drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h | 3 ++ > drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c | 15 ++++++++ > drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h | 3 ++ > drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c | 39 ++++++++++++++++---- > 4 files changed, 52 insertions(+), 8 deletions(-) > > diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h > index d613da8b544c..8eb1659c7685 100644 > --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h > +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h > @@ -26,6 +26,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 { > diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c > index 8adace0befde..5e889c377117 100644 > --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c > +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c > @@ -227,6 +227,21 @@ int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode) > return 0; > } > > +u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp) > +{ > + return dp->dp_dev->link.cap.link_rate; > +} > + > +u8 hibmc_dp_get_lanes(struct hibmc_dp *dp) > +{ > + return dp->dp_dev->link.cap.lanes; > +} > + > +int hibmc_dp_get_dpcd(struct hibmc_dp *dp) > +{ > + return dp->dp_dev->link.cap.rx_dpcd_revision; > +} > + > static const struct hibmc_dp_color_raw g_rgb_raw[] = { > {CBAR_COLOR_BAR, 0x000, 0x000, 0x000}, > {CBAR_WHITE, 0xfff, 0xfff, 0xfff}, > diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h > index 621a0a1d7eb7..823544b8008b 100644 > --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h > +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h > @@ -54,6 +54,9 @@ struct hibmc_dp { > int hibmc_dp_hw_init(struct hibmc_dp *dp); > int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode); > void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable); > +int hibmc_dp_get_dpcd(struct hibmc_dp *dp); > +u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp); > +u8 hibmc_dp_get_lanes(struct hibmc_dp *dp); > void hibmc_dp_set_cbar(struct hibmc_dp *dp, const struct hibmc_dp_cbar_cfg *cfg); > > #endif > diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c > index 4a99a9b7e3c4..39345fc78c06 100644 > --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c > +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c > @@ -7,6 +7,7 @@ > #include "dp_comm.h" > #include "dp_reg.h" > #include "dp_serdes.h" > +#include "dp_config.h" > > #define HIBMC_EQ_MAX_RETRY 5 > > @@ -42,11 +43,7 @@ static int hibmc_dp_link_training_configure(struct hibmc_dp_dev *dp) > return ret >= 0 ? -EIO : ret; > } > > - ret = drm_dp_read_dpcd_caps(dp->aux, dp->dpcd); > - if (ret) > - drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret); > - > - return ret; > + return 0; > } > > static int hibmc_dp_link_set_pattern(struct hibmc_dp_dev *dp, int pattern) > @@ -189,15 +186,17 @@ static int hibmc_dp_link_training_cr(struct hibmc_dp_dev *dp) > bool level_changed; > u32 voltage_tries; > u32 cr_tries; > + u32 max_cr; > int ret; > > /* > * DP 1.4 spec define 10 for maxtries value, for pre DP 1.4 version set a limit of 80 > * (4 voltage levels x 4 preemphasis levels x 5 identical voltage retries) > */ > + max_cr = dp->link.cap.rx_dpcd_revision >= DP_DPCD_REV_14 ? 10 : 80; > > voltage_tries = 1; > - for (cr_tries = 0; cr_tries < 80; cr_tries++) { > + for (cr_tries = 0; cr_tries < max_cr; cr_tries++) { > drm_dp_link_train_clock_recovery_delay(dp->aux, dp->dpcd); > > ret = drm_dp_dpcd_read_link_status(dp->aux, lane_status); > @@ -234,7 +233,7 @@ static int hibmc_dp_link_training_cr(struct hibmc_dp_dev *dp) > voltage_tries = level_changed ? 1 : voltage_tries + 1; > } > > - drm_err(dp->dev, "dp link training clock recovery 80 times failed\n"); > + drm_err(dp->dev, "dp link training clock recovery %u times failed\n", max_cr); > dp->link.status.clock_recovered = false; > > return 0; > @@ -244,9 +243,17 @@ static int hibmc_dp_link_training_channel_eq(struct hibmc_dp_dev *dp) > { > u8 lane_status[DP_LINK_STATUS_SIZE] = {0}; > u8 eq_tries; > + int tps; > int ret; > > - ret = hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_2); > + if (dp->link.cap.is_tps4) > + tps = DP_TRAINING_PATTERN_4; > + else if (dp->link.cap.is_tps3) > + tps = DP_TRAINING_PATTERN_3; > + else > + tps = DP_TRAINING_PATTERN_2; > + > + ret = hibmc_dp_link_set_pattern(dp, tps); > if (ret) > return ret; > > @@ -313,11 +320,27 @@ 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); > +} > + > int hibmc_dp_link_training(struct hibmc_dp_dev *dp) > { > struct hibmc_dp_link *link = &dp->link; > int ret; > > + ret = drm_dp_read_dpcd_caps(dp->aux, dp->dpcd); > + if (ret) > + drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret); > + > + hibmc_dp_update_caps(dp); > + > while (true) { > ret = hibmc_dp_link_training_cr_pre(dp); > if (ret) > -- > 2.33.0 >
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h index d613da8b544c..8eb1659c7685 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h @@ -26,6 +26,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 { diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c index 8adace0befde..5e889c377117 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c @@ -227,6 +227,21 @@ int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode) return 0; } +u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp) +{ + return dp->dp_dev->link.cap.link_rate; +} + +u8 hibmc_dp_get_lanes(struct hibmc_dp *dp) +{ + return dp->dp_dev->link.cap.lanes; +} + +int hibmc_dp_get_dpcd(struct hibmc_dp *dp) +{ + return dp->dp_dev->link.cap.rx_dpcd_revision; +} + static const struct hibmc_dp_color_raw g_rgb_raw[] = { {CBAR_COLOR_BAR, 0x000, 0x000, 0x000}, {CBAR_WHITE, 0xfff, 0xfff, 0xfff}, diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h index 621a0a1d7eb7..823544b8008b 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h @@ -54,6 +54,9 @@ struct hibmc_dp { int hibmc_dp_hw_init(struct hibmc_dp *dp); int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode); void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable); +int hibmc_dp_get_dpcd(struct hibmc_dp *dp); +u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp); +u8 hibmc_dp_get_lanes(struct hibmc_dp *dp); void hibmc_dp_set_cbar(struct hibmc_dp *dp, const struct hibmc_dp_cbar_cfg *cfg); #endif diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c index 4a99a9b7e3c4..39345fc78c06 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c @@ -7,6 +7,7 @@ #include "dp_comm.h" #include "dp_reg.h" #include "dp_serdes.h" +#include "dp_config.h" #define HIBMC_EQ_MAX_RETRY 5 @@ -42,11 +43,7 @@ static int hibmc_dp_link_training_configure(struct hibmc_dp_dev *dp) return ret >= 0 ? -EIO : ret; } - ret = drm_dp_read_dpcd_caps(dp->aux, dp->dpcd); - if (ret) - drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret); - - return ret; + return 0; } static int hibmc_dp_link_set_pattern(struct hibmc_dp_dev *dp, int pattern) @@ -189,15 +186,17 @@ static int hibmc_dp_link_training_cr(struct hibmc_dp_dev *dp) bool level_changed; u32 voltage_tries; u32 cr_tries; + u32 max_cr; int ret; /* * DP 1.4 spec define 10 for maxtries value, for pre DP 1.4 version set a limit of 80 * (4 voltage levels x 4 preemphasis levels x 5 identical voltage retries) */ + max_cr = dp->link.cap.rx_dpcd_revision >= DP_DPCD_REV_14 ? 10 : 80; voltage_tries = 1; - for (cr_tries = 0; cr_tries < 80; cr_tries++) { + for (cr_tries = 0; cr_tries < max_cr; cr_tries++) { drm_dp_link_train_clock_recovery_delay(dp->aux, dp->dpcd); ret = drm_dp_dpcd_read_link_status(dp->aux, lane_status); @@ -234,7 +233,7 @@ static int hibmc_dp_link_training_cr(struct hibmc_dp_dev *dp) voltage_tries = level_changed ? 1 : voltage_tries + 1; } - drm_err(dp->dev, "dp link training clock recovery 80 times failed\n"); + drm_err(dp->dev, "dp link training clock recovery %u times failed\n", max_cr); dp->link.status.clock_recovered = false; return 0; @@ -244,9 +243,17 @@ static int hibmc_dp_link_training_channel_eq(struct hibmc_dp_dev *dp) { u8 lane_status[DP_LINK_STATUS_SIZE] = {0}; u8 eq_tries; + int tps; int ret; - ret = hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_2); + if (dp->link.cap.is_tps4) + tps = DP_TRAINING_PATTERN_4; + else if (dp->link.cap.is_tps3) + tps = DP_TRAINING_PATTERN_3; + else + tps = DP_TRAINING_PATTERN_2; + + ret = hibmc_dp_link_set_pattern(dp, tps); if (ret) return ret; @@ -313,11 +320,27 @@ 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); +} + int hibmc_dp_link_training(struct hibmc_dp_dev *dp) { struct hibmc_dp_link *link = &dp->link; int ret; + ret = drm_dp_read_dpcd_caps(dp->aux, dp->dpcd); + if (ret) + drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret); + + hibmc_dp_update_caps(dp); + while (true) { ret = hibmc_dp_link_training_cr_pre(dp); if (ret)