Merge "msm: mdss: dp: fix no display issues during cable plugin/plugouts"
This commit is contained in:
commit
6d08baec31
2 changed files with 79 additions and 12 deletions
|
@ -1568,6 +1568,19 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv, bool lt_needed)
|
|||
{
|
||||
int ret = 0;
|
||||
char ln_map[4];
|
||||
bool connected;
|
||||
|
||||
mutex_lock(&dp_drv->attention_lock);
|
||||
connected = dp_drv->cable_connected;
|
||||
mutex_unlock(&dp_drv->attention_lock);
|
||||
|
||||
/*
|
||||
* If DP cable disconnected, Avoid link training or turning on DP Path
|
||||
*/
|
||||
if (!connected) {
|
||||
pr_err("DP sink not connected\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* wait until link training is completed */
|
||||
pr_debug("enter, lt_needed=%s\n", lt_needed ? "true" : "false");
|
||||
|
@ -1609,6 +1622,13 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv, bool lt_needed)
|
|||
dp_drv->power_on = true;
|
||||
|
||||
ret = mdss_dp_setup_main_link(dp_drv, lt_needed);
|
||||
if (ret) {
|
||||
if (ret == -ENODEV || ret == -EINVAL) {
|
||||
pr_err("main link setup failed\n");
|
||||
mutex_unlock(&dp_drv->train_mutex);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
mutex_unlock(&dp_drv->train_mutex);
|
||||
|
@ -2209,7 +2229,7 @@ static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp)
|
|||
ret = mdss_dp_dpcd_cap_read(dp);
|
||||
if (ret || !mdss_dp_aux_is_link_rate_valid(dp->dpcd.max_link_rate) ||
|
||||
!mdss_dp_aux_is_lane_count_valid(dp->dpcd.max_lane_count)) {
|
||||
if (ret == EDP_AUX_ERR_TOUT) {
|
||||
if ((ret == -ENODEV) || (ret == EDP_AUX_ERR_TOUT)) {
|
||||
pr_err("DPCD read timedout, skip connect notification\n");
|
||||
goto end;
|
||||
}
|
||||
|
@ -2241,6 +2261,9 @@ static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp)
|
|||
read_edid:
|
||||
ret = mdss_dp_edid_read(dp);
|
||||
if (ret) {
|
||||
if (ret == -ENODEV)
|
||||
goto end;
|
||||
|
||||
pr_err("edid read error, setting default resolution\n");
|
||||
goto notify;
|
||||
}
|
||||
|
@ -3558,9 +3581,33 @@ static void mdss_dp_reset_event_list(struct mdss_dp_drv_pdata *dp)
|
|||
|
||||
static void mdss_dp_reset_sw_state(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
pr_debug("enter\n");
|
||||
mdss_dp_reset_event_list(dp);
|
||||
|
||||
/*
|
||||
* IRQ_HPD attention event handler first turns on DP path and then
|
||||
* notifies CONNECT_IRQ_HPD and waits for userspace to trigger UNBLANK.
|
||||
* In such cases, before UNBLANK call, if cable is disconnected, if
|
||||
* DISCONNECT is notified immediately, userspace might not sense any
|
||||
* change in connection status, leaving DP controller ON.
|
||||
*
|
||||
* To avoid such cases, wait for the connection event to complete before
|
||||
* sending disconnection event
|
||||
*/
|
||||
if (atomic_read(&dp->notification_pending)) {
|
||||
pr_debug("waiting for the pending notitfication\n");
|
||||
ret = wait_for_completion_timeout(&dp->notification_comp, HZ);
|
||||
if (ret <= 0) {
|
||||
pr_err("%s timed out\n",
|
||||
mdss_dp_notification_status_to_string(
|
||||
dp->hpd_notification_status));
|
||||
}
|
||||
}
|
||||
|
||||
atomic_set(&dp->notification_pending, 0);
|
||||
/* complete any waiting completions */
|
||||
complete_all(&dp->notification_comp);
|
||||
}
|
||||
|
||||
|
|
|
@ -411,7 +411,8 @@ retry:
|
|||
|
||||
if (!connected) {
|
||||
pr_err("dp cable disconnected\n");
|
||||
break;
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
dp->aux_error_num = EDP_AUX_ERR_NONE;
|
||||
|
@ -877,7 +878,7 @@ void dp_extract_edid_detailed_timing_description(struct edp_edid *edid,
|
|||
|
||||
static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep)
|
||||
{
|
||||
int cnt, ret;
|
||||
int cnt, ret = 0;
|
||||
char data = 0;
|
||||
|
||||
for (cnt = 5; cnt; cnt--) {
|
||||
|
@ -886,6 +887,10 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep)
|
|||
ret, mdss_dp_get_aux_error(ep->aux_error_num));
|
||||
if (ret >= 0)
|
||||
break;
|
||||
|
||||
if (ret == -ENODEV)
|
||||
return ret;
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
|
@ -973,6 +978,7 @@ int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp)
|
|||
u32 checksum = 0;
|
||||
bool phy_aux_update_requested = false;
|
||||
bool ext_block_parsing_done = false;
|
||||
bool connected = false;
|
||||
|
||||
ret = dp_aux_chan_ready(dp);
|
||||
if (ret) {
|
||||
|
@ -992,6 +998,15 @@ int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp)
|
|||
u8 segment;
|
||||
u8 edid_buf[EDID_BLOCK_SIZE] = {0};
|
||||
|
||||
mutex_lock(&dp->attention_lock);
|
||||
connected = dp->cable_connected;
|
||||
mutex_unlock(&dp->attention_lock);
|
||||
|
||||
if (!connected) {
|
||||
pr_err("DP sink not connected\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the segment first.
|
||||
* Segment = 0, for blocks 0 and 1
|
||||
|
@ -1243,7 +1258,7 @@ int mdss_dp_aux_link_status_read(struct mdss_dp_drv_pdata *ep, int len)
|
|||
rlen = dp_aux_read_buf(ep, 0x202, len, 0);
|
||||
if (rlen < len) {
|
||||
pr_err("edp aux read failed\n");
|
||||
return 0;
|
||||
return rlen;
|
||||
}
|
||||
rp = &ep->rxp;
|
||||
bp = rp->data;
|
||||
|
@ -2459,21 +2474,24 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
|
|||
usleep_time = ep->dpcd.training_read_interval;
|
||||
usleep_range(usleep_time, usleep_time);
|
||||
|
||||
mdss_dp_aux_link_status_read(ep, 6);
|
||||
ret = mdss_dp_aux_link_status_read(ep, 6);
|
||||
if (ret == -ENODEV)
|
||||
break;
|
||||
|
||||
if (mdss_dp_aux_clock_recovery_done(ep)) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ep->v_level == DPCD_LINK_VOLTAGE_MAX) {
|
||||
ret = -1;
|
||||
ret = -EAGAIN;
|
||||
break; /* quit */
|
||||
}
|
||||
|
||||
if (old_v_level == ep->v_level) {
|
||||
tries++;
|
||||
if (tries >= maximum_retries) {
|
||||
ret = -1;
|
||||
ret = -EAGAIN;
|
||||
break; /* quit */
|
||||
}
|
||||
} else {
|
||||
|
@ -2511,7 +2529,9 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
|
|||
usleep_time = ep->dpcd.training_read_interval;
|
||||
usleep_range(usleep_time, usleep_time);
|
||||
|
||||
mdss_dp_aux_link_status_read(ep, 6);
|
||||
ret = mdss_dp_aux_link_status_read(ep, 6);
|
||||
if (ret == -ENODEV)
|
||||
break;
|
||||
|
||||
if (mdss_dp_aux_channel_eq_done(ep)) {
|
||||
ret = 0;
|
||||
|
@ -2519,7 +2539,7 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
|
|||
}
|
||||
|
||||
if (tries > maximum_retries) {
|
||||
ret = -1;
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
tries++;
|
||||
|
@ -2584,7 +2604,7 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
|
|||
|
||||
ret = dp_start_link_train_1(dp);
|
||||
if (ret < 0) {
|
||||
if (!dp_link_rate_down_shift(dp)) {
|
||||
if ((ret == -EAGAIN) && !dp_link_rate_down_shift(dp)) {
|
||||
pr_debug("retry with lower rate\n");
|
||||
dp_clear_training_pattern(dp);
|
||||
return -EAGAIN;
|
||||
|
@ -2603,7 +2623,7 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
|
|||
|
||||
ret = dp_start_link_train_2(dp);
|
||||
if (ret < 0) {
|
||||
if (!dp_link_rate_down_shift(dp)) {
|
||||
if ((ret == -EAGAIN) && !dp_link_rate_down_shift(dp)) {
|
||||
pr_debug("retry with lower rate\n");
|
||||
dp_clear_training_pattern(dp);
|
||||
return -EAGAIN;
|
||||
|
@ -2640,7 +2660,7 @@ int mdss_dp_dpcd_status_read(struct mdss_dp_drv_pdata *ep)
|
|||
|
||||
ret = mdss_dp_aux_link_status_read(ep, 6);
|
||||
|
||||
if (ret) {
|
||||
if (ret > 0) {
|
||||
sp = &ep->link_status;
|
||||
ret = sp->port_0_in_sync; /* 1 == sync */
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue