Skip to content

Commit 62671d2

Browse files
Kuogee Hsiehrobclark
authored andcommitted
drm/msm/dp: fixes wrong connection state caused by failure of link train
Connection state is not set correctly happen when either failure of link train due to cable unplugged in the middle of aux channel reading or cable plugged in while in suspended state. This patch fixes these problems. This patch also replace ST_SUSPEND_PENDING with ST_DISPLAY_OFF. Changes in V2: -- Add more information to commit message. Changes in V3: -- change base Changes in V4: -- add Fixes tag Signed-off-by: Kuogee Hsieh <[email protected]> Signed-off-by: Rob Clark <[email protected]>
1 parent 19e52bc commit 62671d2

File tree

2 files changed

+25
-22
lines changed

2 files changed

+25
-22
lines changed

drivers/gpu/drm/msm/dp/dp_display.c

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ enum {
4545
ST_CONNECT_PENDING,
4646
ST_CONNECTED,
4747
ST_DISCONNECT_PENDING,
48-
ST_SUSPEND_PENDING,
48+
ST_DISPLAY_OFF,
4949
ST_SUSPENDED,
5050
};
5151

@@ -504,7 +504,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
504504
mutex_lock(&dp->event_mutex);
505505

506506
state = dp->hpd_state;
507-
if (state == ST_SUSPEND_PENDING) {
507+
if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) {
508508
mutex_unlock(&dp->event_mutex);
509509
return 0;
510510
}
@@ -526,14 +526,14 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
526526
hpd->hpd_high = 1;
527527

528528
ret = dp_display_usbpd_configure_cb(&dp->pdev->dev);
529-
if (ret) { /* failed */
529+
if (ret) { /* link train failed */
530530
hpd->hpd_high = 0;
531531
dp->hpd_state = ST_DISCONNECTED;
532+
} else {
533+
/* start sentinel checking in case of missing uevent */
534+
dp_add_event(dp, EV_CONNECT_PENDING_TIMEOUT, 0, tout);
532535
}
533536

534-
/* start sanity checking */
535-
dp_add_event(dp, EV_CONNECT_PENDING_TIMEOUT, 0, tout);
536-
537537
mutex_unlock(&dp->event_mutex);
538538

539539
/* uevent will complete connection part */
@@ -578,11 +578,6 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
578578
mutex_lock(&dp->event_mutex);
579579

580580
state = dp->hpd_state;
581-
if (state == ST_SUSPEND_PENDING) {
582-
mutex_unlock(&dp->event_mutex);
583-
return 0;
584-
}
585-
586581
if (state == ST_DISCONNECT_PENDING || state == ST_DISCONNECTED) {
587582
mutex_unlock(&dp->event_mutex);
588583
return 0;
@@ -609,7 +604,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
609604
*/
610605
dp_display_usbpd_disconnect_cb(&dp->pdev->dev);
611606

612-
/* start sanity checking */
607+
/* start sentinel checking in case of missing uevent */
613608
dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND);
614609

615610
/* signal the disconnect event early to ensure proper teardown */
@@ -649,7 +644,7 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
649644

650645
/* irq_hpd can happen at either connected or disconnected state */
651646
state = dp->hpd_state;
652-
if (state == ST_SUSPEND_PENDING) {
647+
if (state == ST_DISPLAY_OFF) {
653648
mutex_unlock(&dp->event_mutex);
654649
return 0;
655650
}
@@ -1074,7 +1069,7 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
10741069
}
10751070

10761071
if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) {
1077-
/* delete connect pending event first */
1072+
/* stop sentinel connect pending checking */
10781073
dp_del_event(dp, EV_CONNECT_PENDING_TIMEOUT);
10791074
dp_add_event(dp, EV_IRQ_HPD_INT, 0, 0);
10801075
}
@@ -1205,13 +1200,10 @@ static int dp_pm_resume(struct device *dev)
12051200

12061201
status = dp_catalog_hpd_get_state_status(dp->catalog);
12071202

1208-
if (status) {
1203+
if (status)
12091204
dp->dp_display.is_connected = true;
1210-
} else {
1205+
else
12111206
dp->dp_display.is_connected = false;
1212-
/* make sure next resume host_init be called */
1213-
dp->core_initialized = false;
1214-
}
12151207

12161208
mutex_unlock(&dp->event_mutex);
12171209

@@ -1233,6 +1225,9 @@ static int dp_pm_suspend(struct device *dev)
12331225

12341226
dp->hpd_state = ST_SUSPENDED;
12351227

1228+
/* host_init will be called at pm_resume */
1229+
dp->core_initialized = false;
1230+
12361231
mutex_unlock(&dp->event_mutex);
12371232

12381233
return 0;
@@ -1362,6 +1357,7 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder)
13621357

13631358
mutex_lock(&dp_display->event_mutex);
13641359

1360+
/* stop sentinel checking */
13651361
dp_del_event(dp_display, EV_CONNECT_PENDING_TIMEOUT);
13661362

13671363
rc = dp_display_set_mode(dp, &dp_display->dp_mode);
@@ -1380,7 +1376,7 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder)
13801376

13811377
state = dp_display->hpd_state;
13821378

1383-
if (state == ST_SUSPEND_PENDING)
1379+
if (state == ST_DISPLAY_OFF)
13841380
dp_display_host_init(dp_display);
13851381

13861382
dp_display_enable(dp_display, 0);
@@ -1392,7 +1388,8 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder)
13921388
dp_display_unprepare(dp);
13931389
}
13941390

1395-
if (state == ST_SUSPEND_PENDING)
1391+
/* manual kick off plug event to train link */
1392+
if (state == ST_DISPLAY_OFF)
13961393
dp_add_event(dp_display, EV_IRQ_HPD_INT, 0, 0);
13971394

13981395
/* completed connection */
@@ -1424,6 +1421,7 @@ int msm_dp_display_disable(struct msm_dp *dp, struct drm_encoder *encoder)
14241421

14251422
mutex_lock(&dp_display->event_mutex);
14261423

1424+
/* stop sentinel checking */
14271425
dp_del_event(dp_display, EV_DISCONNECT_PENDING_TIMEOUT);
14281426

14291427
dp_display_disable(dp_display, 0);
@@ -1437,7 +1435,7 @@ int msm_dp_display_disable(struct msm_dp *dp, struct drm_encoder *encoder)
14371435
/* completed disconnection */
14381436
dp_display->hpd_state = ST_DISCONNECTED;
14391437
} else {
1440-
dp_display->hpd_state = ST_SUSPEND_PENDING;
1438+
dp_display->hpd_state = ST_DISPLAY_OFF;
14411439
}
14421440

14431441
mutex_unlock(&dp_display->event_mutex);

drivers/gpu/drm/msm/dp/dp_panel.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
196196
&panel->aux->ddc);
197197
if (!dp_panel->edid) {
198198
DRM_ERROR("panel edid read failed\n");
199+
/* check edid read fail is due to unplug */
200+
if (!dp_catalog_hpd_get_state_status(panel->catalog)) {
201+
rc = -ETIMEDOUT;
202+
goto end;
203+
}
199204

200205
/* fail safe edid */
201206
mutex_lock(&connector->dev->mode_config.mutex);

0 commit comments

Comments
 (0)