Message ID | 1476771741-11997-1-git-send-email-wzz@rock-chips.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Oct 18, 2016 at 2:22 AM, Zain Wang <wzz@rock-chips.com> wrote: > From: zain wang <wzz@rock-chips.com> > > 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 <wzz@rock-chips.com> > --- > 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 <linux/gpio.h> > #include <linux/component.h> > #include <linux/phy/phy.h> > +#include <linux/iopoll.h> > > #include <drm/drmP.h> > #include <drm/drm_atomic_helper.h> > @@ -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(&dp->aux, DP_MAX_DOWNSPREAD, &spread); 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(&dp->aux, > + DP_LANE_ALIGN_STATUS_UPDATED, > + &link_align); > + if (retval < 0) > + return retval; > + > + retval = drm_dp_dpcd_read(&dp->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 analogix_dp_set_link_train(struct analogix_dp_device *dp, > int retval; > > for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) { > - analogix_dp_init_training(dp, count, bwtype); > - retval = analogix_dp_sw_link_training(dp); > + if (dp->fast_train_support) > + retval = analogix_dp_fast_link_train(dp); > + else > + retval = analogix_dp_full_link_train(dp, count, > + bwtype); > if (retval == 0) > break; > - > usleep_range(100, 110); > } > > diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h > index cdc0535..b86039b 100644 > --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h > +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h > @@ -171,6 +171,7 @@ struct analogix_dp_device { > int hpd_gpio; > bool force_hpd; > bool psr_support; > + bool fast_train_support; > > struct mutex panel_lock; > bool panel_is_modeset; > -- > 1.9.1 > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
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 <linux/gpio.h> #include <linux/component.h> #include <linux/phy/phy.h> +#include <linux/iopoll.h> #include <drm/drmP.h> #include <drm/drm_atomic_helper.h> @@ -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(&dp->aux, DP_MAX_DOWNSPREAD, &spread); + 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(&dp->aux, + DP_LANE_ALIGN_STATUS_UPDATED, + &link_align); + if (retval < 0) + return retval; + + retval = drm_dp_dpcd_read(&dp->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 analogix_dp_set_link_train(struct analogix_dp_device *dp, int retval; for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) { - analogix_dp_init_training(dp, count, bwtype); - retval = analogix_dp_sw_link_training(dp); + if (dp->fast_train_support) + retval = analogix_dp_fast_link_train(dp); + else + retval = analogix_dp_full_link_train(dp, count, + bwtype); if (retval == 0) break; - usleep_range(100, 110); } diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index cdc0535..b86039b 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -171,6 +171,7 @@ struct analogix_dp_device { int hpd_gpio; bool force_hpd; bool psr_support; + bool fast_train_support; struct mutex panel_lock; bool panel_is_modeset;