diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp.c | 100 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp.h | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp_aux.c | 16 |
3 files changed, 89 insertions, 29 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 516cbdc9192b..caaedf2f0ff6 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -1303,17 +1303,23 @@ int mdss_dp_on(struct mdss_panel_data *pdata) return mdss_dp_on_hpd(dp_drv); } -static void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp) +static inline void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp) { dp->test_data = (const struct dpcd_test_request){ 0 }; } -static bool mdss_dp_is_link_training_requested(struct mdss_dp_drv_pdata *dp) +static inline bool mdss_dp_is_link_status_updated(struct mdss_dp_drv_pdata *dp) +{ + return dp->link_status.link_status_updated; +} + +static inline bool mdss_dp_is_link_training_requested( + struct mdss_dp_drv_pdata *dp) { return (dp->test_data.test_requested == TEST_LINK_TRAINING); } -static bool mdss_dp_soft_hpd_reset(struct mdss_dp_drv_pdata *dp) +static inline bool mdss_dp_soft_hpd_reset(struct mdss_dp_drv_pdata *dp) { return mdss_dp_is_link_training_requested(dp) && dp->alt_mode.dp_status.hpd_irq; @@ -2281,7 +2287,7 @@ end: * This function will send the test response to the sink but only after * any previous link training has been completed. */ -static void mdss_dp_send_test_response(struct mdss_dp_drv_pdata *dp) +static inline void mdss_dp_send_test_response(struct mdss_dp_drv_pdata *dp) { mutex_lock(&dp->train_mutex); mdss_dp_aux_send_test_response(dp); @@ -2318,11 +2324,76 @@ static int mdss_dp_hpd_irq_notify_clients(struct mdss_dp_drv_pdata *dp) } /** + * mdss_dp_link_retraining() - initiates link retraining + * @dp: Display Port Driver data + * + * This function will initiate link retraining by first notifying + * DP clients and triggering DP shutdown, and then enabling DP after + * notification is done successfully. + */ +static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp) +{ + if (mdss_dp_hpd_irq_notify_clients(dp)) + return; + + mdss_dp_on_irq(dp); +} + +/** + * mdss_dp_process_link_status_update() - processes link status updates + * @dp: Display Port Driver data + * + * This function will check for changes in the link status, e.g. clock + * recovery done on all lanes, and trigger link training if there is a + * failure/error on the link. + */ +static void mdss_dp_process_link_status_update(struct mdss_dp_drv_pdata *dp) +{ + if (!mdss_dp_is_link_status_updated(dp) || + (mdss_dp_aux_channel_eq_done(dp) && + mdss_dp_aux_clock_recovery_done(dp))) + return; + + pr_info("channel_eq_done = %d, clock_recovery_done = %d\n", + mdss_dp_aux_channel_eq_done(dp), + mdss_dp_aux_clock_recovery_done(dp)); + + mdss_dp_link_retraining(dp); +} + +/** + * mdss_dp_process_link_training_request() - processes new training requests + * @dp: Display Port Driver data + * + * This function will handle new link training requests that are initiated by + * the sink. In particular, it will update the requested lane count and link + * link rate, and then trigger the link retraining procedure. + */ +static void mdss_dp_process_link_training_request(struct mdss_dp_drv_pdata *dp) +{ + if (!mdss_dp_is_link_training_requested(dp)) + return; + + mdss_dp_send_test_response(dp); + + pr_info("%s link rate = 0x%x, lane count = 0x%x\n", + mdss_dp_get_test_name(TEST_LINK_TRAINING), + dp->test_data.test_link_rate, + dp->test_data.test_lane_count); + dp->dpcd.max_lane_count = + dp->test_data.test_lane_count; + dp->link_rate = dp->test_data.test_link_rate; + + mdss_dp_link_retraining(dp); +} + +/** * mdss_dp_process_hpd_irq_high() - handle HPD IRQ transition to HIGH * @dp: Display Port Driver data * - * This function will handle the HPD IRQ state transitions from HIGH to HIGH - * or LOW to HIGH, indicating the start of a new test request. + * This function will handle the HPD IRQ state transitions from LOW to HIGH + * (including cases when there are back to back HPD IRQ HIGH) indicating + * the start of a new link training request or sink status update. */ static void mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp) { @@ -2332,22 +2403,9 @@ static void mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp) mdss_dp_aux_parse_sink_status_field(dp); - if (mdss_dp_is_link_training_requested(dp)) { - mdss_dp_send_test_response(dp); - - pr_info("%s requested: link rate = 0x%x, lane count = 0x%x\n", - mdss_dp_get_test_name(TEST_LINK_TRAINING), - dp->test_data.test_link_rate, - dp->test_data.test_lane_count); - dp->dpcd.max_lane_count = - dp->test_data.test_lane_count; - dp->link_rate = dp->test_data.test_link_rate; + mdss_dp_process_link_training_request(dp); - if (mdss_dp_hpd_irq_notify_clients(dp)) - return; - - mdss_dp_on_irq(dp); - } + mdss_dp_process_link_status_update(dp); mdss_dp_reset_test_data(dp); diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index beeb4d4b1a91..4ba2d20d4261 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -585,5 +585,7 @@ int mdss_dp_aux_set_sink_power_state(struct mdss_dp_drv_pdata *ep, char state); void mdss_dp_aux_send_test_response(struct mdss_dp_drv_pdata *ep); void *mdss_dp_get_hdcp_data(struct device *dev); int mdss_dp_hdcp2p2_init(struct mdss_dp_drv_pdata *dp_drv); +bool mdss_dp_aux_clock_recovery_done(struct mdss_dp_drv_pdata *ep); +bool mdss_dp_aux_channel_eq_done(struct mdss_dp_drv_pdata *ep); #endif /* MDSS_DP_H */ diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index 4d9a110cf6af..91066662e793 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -1238,7 +1238,7 @@ static int dp_train_pattern_set_write(struct mdss_dp_drv_pdata *ep, return dp_aux_write_buf(ep, 0x102, buf, 1, 0); } -static int dp_sink_clock_recovery_done(struct mdss_dp_drv_pdata *ep) +bool mdss_dp_aux_clock_recovery_done(struct mdss_dp_drv_pdata *ep) { u32 mask; u32 data; @@ -1259,12 +1259,12 @@ static int dp_sink_clock_recovery_done(struct mdss_dp_drv_pdata *ep) pr_debug("data=%x mask=%x\n", data, mask); data &= mask; if (data == mask) /* all done */ - return 1; + return true; - return 0; + return false; } -static int dp_sink_channel_eq_done(struct mdss_dp_drv_pdata *ep) +bool mdss_dp_aux_channel_eq_done(struct mdss_dp_drv_pdata *ep) { u32 mask; u32 data; @@ -1293,9 +1293,9 @@ static int dp_sink_channel_eq_done(struct mdss_dp_drv_pdata *ep) data &= mask; if (data == mask)/* all done */ - return 1; + return true; - return 0; + return false; } void dp_sink_train_set_adjust(struct mdss_dp_drv_pdata *ep) @@ -1446,7 +1446,7 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep) usleep_range(usleep_time, usleep_time); dp_link_status_read(ep, 6); - if (dp_sink_clock_recovery_done(ep)) { + if (mdss_dp_aux_clock_recovery_done(ep)) { ret = 0; break; } @@ -1499,7 +1499,7 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep) dp_link_status_read(ep, 6); - if (dp_sink_channel_eq_done(ep)) { + if (mdss_dp_aux_channel_eq_done(ep)) { ret = 0; break; } |
