Re: [PATCH v3 5/6] drm: bridge/analogix: add fast link train for eDP
On Tue, Oct 18, 2016 at 2:22 AM, Zain Wangwrote: > From: zain wang > > we would meet a short black screen when exit PSR with the full link > training, In this case, we should use fast link train instead of full > link training. > > Signed-off-by: zain wang > --- > drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 89 > +- > drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 1 + > 2 files changed, 86 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > index 561b644..0516621 100644 > --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > @@ -21,6 +21,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -35,6 +36,8 @@ > > #define to_dp(nm) container_of(nm, struct analogix_dp_device, nm) > > +static const int FAST_LINK_VERIFICATION = false; /* Set this to true to verify fast link training succeeded */ static const bool verify_fast_training = false; > + > struct bridge_init { > struct i2c_client *client; > struct device_node *node; > @@ -244,6 +247,7 @@ static int analogix_dp_link_start(struct > analogix_dp_device *dp) > usleep_range(90, 120); > } > > + remove extra line > /* Set training pattern 1 */ > analogix_dp_set_training_pattern(dp, TRAINING_PTN1); > > @@ -481,7 +485,7 @@ static int analogix_dp_process_equalizer_training(struct > analogix_dp_device *dp) > { > int lane, lane_count, retval; > u32 reg; > - u8 link_align, link_status[2], adjust_request[2]; > + u8 link_align, link_status[2], adjust_request[2], spread; > > usleep_range(400, 401); > > @@ -524,6 +528,12 @@ static int analogix_dp_process_equalizer_training(struct > analogix_dp_device *dp) > dev_dbg(dp->dev, "final lane count = %.2x\n", > dp->link_train.lane_count); > > + drm_dp_dpcd_readb(>aux, DP_MAX_DOWNSPREAD, ); check return value > + dp->fast_train_support = (spread & > + DP_NO_AUX_HANDSHAKE_LINK_TRAINING) ? true : false; > + dev_dbg(dp->dev, "fast link training %s\n", > + dp->fast_train_support ? "supported" : "unsupported"); > + > /* set enhanced mode if available */ > analogix_dp_set_enhanced_mode(dp); > dp->link_train.lt_state = FINISHED; > @@ -655,6 +665,75 @@ static int analogix_dp_sw_link_training(struct > analogix_dp_device *dp) > return retval; > } > > +static int analogix_dp_full_link_train(struct analogix_dp_device *dp, > + u32 count, u32 bwtype) > +{ > + analogix_dp_init_training(dp, count, bwtype); > + return analogix_dp_sw_link_training(dp); > +} > + > +static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) > +{ > + int lane; > + int retval; int ret; > + u8 link_align, link_status[2]; > + enum pll_status status; > + > + analogix_dp_reset_macro(dp); > + > + analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); > + analogix_dp_set_lane_count(dp, dp->link_train.lane_count); > + > + for (lane = 0; lane < dp->link_train.lane_count; lane++) { > + analogix_dp_set_lane_link_training(dp, > + dp->link_train.training_lane[lane], lane); > + } > + > + retval = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, > status, > + status != PLL_UNLOCKED, > + 120, 120 * DP_TIMEOUT_LOOP_COUNT); > + > + if (retval) > + return retval; > + > + /* source Set training pattern 1 */ > + analogix_dp_set_training_pattern(dp, TRAINING_PTN1); > + usleep_range(500, 600); Add a comment to these sleeps explaining that the spec dictates each training pattern must be output for minimum 500us > + > + analogix_dp_set_training_pattern(dp, TRAINING_PTN2); > + usleep_range(500, 600); > + > + /* TODO: enhanced_mode?*/ > + analogix_dp_set_training_pattern(dp, DP_NONE); > + > + if (FAST_LINK_VERIFICATION) { > + retval = drm_dp_dpcd_readb(>aux, > + DP_LANE_ALIGN_STATUS_UPDATED, > + _align); > + if (retval < 0) > + return retval; > + > + retval = drm_dp_dpcd_read(>aux, DP_LANE0_1_STATUS, > + link_status, 2); > + if (retval < 0) > + return retval; > + > + if (analogix_dp_clock_recovery_ok(link_status, > +
Re: [PATCH v3 5/6] drm: bridge/analogix: add fast link train for eDP
On Tue, Oct 18, 2016 at 2:22 AM, Zain Wang wrote: > From: zain wang > > we would meet a short black screen when exit PSR with the full link > training, In this case, we should use fast link train instead of full > link training. > > Signed-off-by: zain wang > --- > drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 89 > +- > drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 1 + > 2 files changed, 86 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > index 561b644..0516621 100644 > --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > @@ -21,6 +21,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -35,6 +36,8 @@ > > #define to_dp(nm) container_of(nm, struct analogix_dp_device, nm) > > +static const int FAST_LINK_VERIFICATION = false; /* Set this to true to verify fast link training succeeded */ static const bool verify_fast_training = false; > + > struct bridge_init { > struct i2c_client *client; > struct device_node *node; > @@ -244,6 +247,7 @@ static int analogix_dp_link_start(struct > analogix_dp_device *dp) > usleep_range(90, 120); > } > > + remove extra line > /* Set training pattern 1 */ > analogix_dp_set_training_pattern(dp, TRAINING_PTN1); > > @@ -481,7 +485,7 @@ static int analogix_dp_process_equalizer_training(struct > analogix_dp_device *dp) > { > int lane, lane_count, retval; > u32 reg; > - u8 link_align, link_status[2], adjust_request[2]; > + u8 link_align, link_status[2], adjust_request[2], spread; > > usleep_range(400, 401); > > @@ -524,6 +528,12 @@ static int analogix_dp_process_equalizer_training(struct > analogix_dp_device *dp) > dev_dbg(dp->dev, "final lane count = %.2x\n", > dp->link_train.lane_count); > > + drm_dp_dpcd_readb(>aux, DP_MAX_DOWNSPREAD, ); check return value > + dp->fast_train_support = (spread & > + DP_NO_AUX_HANDSHAKE_LINK_TRAINING) ? true : false; > + dev_dbg(dp->dev, "fast link training %s\n", > + dp->fast_train_support ? "supported" : "unsupported"); > + > /* set enhanced mode if available */ > analogix_dp_set_enhanced_mode(dp); > dp->link_train.lt_state = FINISHED; > @@ -655,6 +665,75 @@ static int analogix_dp_sw_link_training(struct > analogix_dp_device *dp) > return retval; > } > > +static int analogix_dp_full_link_train(struct analogix_dp_device *dp, > + u32 count, u32 bwtype) > +{ > + analogix_dp_init_training(dp, count, bwtype); > + return analogix_dp_sw_link_training(dp); > +} > + > +static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) > +{ > + int lane; > + int retval; int ret; > + u8 link_align, link_status[2]; > + enum pll_status status; > + > + analogix_dp_reset_macro(dp); > + > + analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); > + analogix_dp_set_lane_count(dp, dp->link_train.lane_count); > + > + for (lane = 0; lane < dp->link_train.lane_count; lane++) { > + analogix_dp_set_lane_link_training(dp, > + dp->link_train.training_lane[lane], lane); > + } > + > + retval = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, > status, > + status != PLL_UNLOCKED, > + 120, 120 * DP_TIMEOUT_LOOP_COUNT); > + > + if (retval) > + return retval; > + > + /* source Set training pattern 1 */ > + analogix_dp_set_training_pattern(dp, TRAINING_PTN1); > + usleep_range(500, 600); Add a comment to these sleeps explaining that the spec dictates each training pattern must be output for minimum 500us > + > + analogix_dp_set_training_pattern(dp, TRAINING_PTN2); > + usleep_range(500, 600); > + > + /* TODO: enhanced_mode?*/ > + analogix_dp_set_training_pattern(dp, DP_NONE); > + > + if (FAST_LINK_VERIFICATION) { > + retval = drm_dp_dpcd_readb(>aux, > + DP_LANE_ALIGN_STATUS_UPDATED, > + _align); > + if (retval < 0) > + return retval; > + > + retval = drm_dp_dpcd_read(>aux, DP_LANE0_1_STATUS, > + link_status, 2); > + if (retval < 0) > + return retval; > + > + if (analogix_dp_clock_recovery_ok(link_status, > + dp->link_train.lane_count)) > { > +
[PATCH v3 5/6] drm: bridge/analogix: add fast link train for eDP
From: zain wangwe would meet a short black screen when exit PSR with the full link training, In this case, we should use fast link train instead of full link training. Signed-off-by: zain wang --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 89 +- drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 1 + 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 561b644..0516621 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,8 @@ #define to_dp(nm) container_of(nm, struct analogix_dp_device, nm) +static const int FAST_LINK_VERIFICATION = false; + struct bridge_init { struct i2c_client *client; struct device_node *node; @@ -244,6 +247,7 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp) usleep_range(90, 120); } + /* Set training pattern 1 */ analogix_dp_set_training_pattern(dp, TRAINING_PTN1); @@ -481,7 +485,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) { int lane, lane_count, retval; u32 reg; - u8 link_align, link_status[2], adjust_request[2]; + u8 link_align, link_status[2], adjust_request[2], spread; usleep_range(400, 401); @@ -524,6 +528,12 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) dev_dbg(dp->dev, "final lane count = %.2x\n", dp->link_train.lane_count); + drm_dp_dpcd_readb(>aux, DP_MAX_DOWNSPREAD, ); + dp->fast_train_support = (spread & + DP_NO_AUX_HANDSHAKE_LINK_TRAINING) ? true : false; + dev_dbg(dp->dev, "fast link training %s\n", + dp->fast_train_support ? "supported" : "unsupported"); + /* set enhanced mode if available */ analogix_dp_set_enhanced_mode(dp); dp->link_train.lt_state = FINISHED; @@ -655,6 +665,75 @@ static int analogix_dp_sw_link_training(struct analogix_dp_device *dp) return retval; } +static int analogix_dp_full_link_train(struct analogix_dp_device *dp, + u32 count, u32 bwtype) +{ + analogix_dp_init_training(dp, count, bwtype); + return analogix_dp_sw_link_training(dp); +} + +static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) +{ + int lane; + int retval; + u8 link_align, link_status[2]; + enum pll_status status; + + analogix_dp_reset_macro(dp); + + analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); + analogix_dp_set_lane_count(dp, dp->link_train.lane_count); + + for (lane = 0; lane < dp->link_train.lane_count; lane++) { + analogix_dp_set_lane_link_training(dp, + dp->link_train.training_lane[lane], lane); + } + + retval = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, + status != PLL_UNLOCKED, + 120, 120 * DP_TIMEOUT_LOOP_COUNT); + + if (retval) + return retval; + + /* source Set training pattern 1 */ + analogix_dp_set_training_pattern(dp, TRAINING_PTN1); + usleep_range(500, 600); + + analogix_dp_set_training_pattern(dp, TRAINING_PTN2); + usleep_range(500, 600); + + /* TODO: enhanced_mode?*/ + analogix_dp_set_training_pattern(dp, DP_NONE); + + if (FAST_LINK_VERIFICATION) { + retval = drm_dp_dpcd_readb(>aux, + DP_LANE_ALIGN_STATUS_UPDATED, + _align); + if (retval < 0) + return retval; + + retval = drm_dp_dpcd_read(>aux, DP_LANE0_1_STATUS, + link_status, 2); + if (retval < 0) + return retval; + + if (analogix_dp_clock_recovery_ok(link_status, + dp->link_train.lane_count)) { + analogix_dp_reduce_link_rate(dp); + return -EIO; + } + + if (analogix_dp_channel_eq_ok(link_status, link_align, + dp->link_train.lane_count)) { + analogix_dp_reduce_link_rate(dp); + return -EIO; + } + } + + return 0; +} + static int analogix_dp_set_link_train(struct analogix_dp_device *dp, u32 count, u32 bwtype) { @@ -662,11 +741,13
[PATCH v3 5/6] drm: bridge/analogix: add fast link train for eDP
From: zain wang we would meet a short black screen when exit PSR with the full link training, In this case, we should use fast link train instead of full link training. Signed-off-by: zain wang --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 89 +- drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 1 + 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 561b644..0516621 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,8 @@ #define to_dp(nm) container_of(nm, struct analogix_dp_device, nm) +static const int FAST_LINK_VERIFICATION = false; + struct bridge_init { struct i2c_client *client; struct device_node *node; @@ -244,6 +247,7 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp) usleep_range(90, 120); } + /* Set training pattern 1 */ analogix_dp_set_training_pattern(dp, TRAINING_PTN1); @@ -481,7 +485,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) { int lane, lane_count, retval; u32 reg; - u8 link_align, link_status[2], adjust_request[2]; + u8 link_align, link_status[2], adjust_request[2], spread; usleep_range(400, 401); @@ -524,6 +528,12 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) dev_dbg(dp->dev, "final lane count = %.2x\n", dp->link_train.lane_count); + drm_dp_dpcd_readb(>aux, DP_MAX_DOWNSPREAD, ); + dp->fast_train_support = (spread & + DP_NO_AUX_HANDSHAKE_LINK_TRAINING) ? true : false; + dev_dbg(dp->dev, "fast link training %s\n", + dp->fast_train_support ? "supported" : "unsupported"); + /* set enhanced mode if available */ analogix_dp_set_enhanced_mode(dp); dp->link_train.lt_state = FINISHED; @@ -655,6 +665,75 @@ static int analogix_dp_sw_link_training(struct analogix_dp_device *dp) return retval; } +static int analogix_dp_full_link_train(struct analogix_dp_device *dp, + u32 count, u32 bwtype) +{ + analogix_dp_init_training(dp, count, bwtype); + return analogix_dp_sw_link_training(dp); +} + +static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) +{ + int lane; + int retval; + u8 link_align, link_status[2]; + enum pll_status status; + + analogix_dp_reset_macro(dp); + + analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); + analogix_dp_set_lane_count(dp, dp->link_train.lane_count); + + for (lane = 0; lane < dp->link_train.lane_count; lane++) { + analogix_dp_set_lane_link_training(dp, + dp->link_train.training_lane[lane], lane); + } + + retval = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, + status != PLL_UNLOCKED, + 120, 120 * DP_TIMEOUT_LOOP_COUNT); + + if (retval) + return retval; + + /* source Set training pattern 1 */ + analogix_dp_set_training_pattern(dp, TRAINING_PTN1); + usleep_range(500, 600); + + analogix_dp_set_training_pattern(dp, TRAINING_PTN2); + usleep_range(500, 600); + + /* TODO: enhanced_mode?*/ + analogix_dp_set_training_pattern(dp, DP_NONE); + + if (FAST_LINK_VERIFICATION) { + retval = drm_dp_dpcd_readb(>aux, + DP_LANE_ALIGN_STATUS_UPDATED, + _align); + if (retval < 0) + return retval; + + retval = drm_dp_dpcd_read(>aux, DP_LANE0_1_STATUS, + link_status, 2); + if (retval < 0) + return retval; + + if (analogix_dp_clock_recovery_ok(link_status, + dp->link_train.lane_count)) { + analogix_dp_reduce_link_rate(dp); + return -EIO; + } + + if (analogix_dp_channel_eq_ok(link_status, link_align, + dp->link_train.lane_count)) { + analogix_dp_reduce_link_rate(dp); + return -EIO; + } + } + + return 0; +} + static int analogix_dp_set_link_train(struct analogix_dp_device *dp, u32 count, u32 bwtype) { @@ -662,11 +741,13 @@ static int