@@ -576,7 +576,7 @@ u32 dp_catalog_hpd_get_state_status(struct dp_catalog *dp_catalog)
{
struct dp_catalog_private *catalog = container_of(dp_catalog,
struct dp_catalog_private, dp_catalog);
- u32 status = 0;
+ u32 status;
status = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT;
@@ -1403,6 +1403,8 @@ int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip)
void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)
{
struct dp_ctrl_private *ctrl;
+ struct dp_io *dp_io;
+ struct phy *phy;
if (!dp_ctrl) {
DRM_ERROR("Invalid input data\n");
@@ -1410,8 +1412,11 @@ void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)
}
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ dp_io = &ctrl->parser->io;
+ phy = dp_io->phy;
dp_catalog_ctrl_enable_irq(ctrl->catalog, false);
+ phy_exit(phy);
DRM_DEBUG_DP("Host deinitialized successfully\n");
}
@@ -108,7 +108,7 @@ struct dp_display_private {
/* event related only access by event thread */
struct mutex event_mutex;
wait_queue_head_t event_q;
- atomic_t hpd_state;
+ u32 hpd_state;
u32 event_pndx;
u32 event_gndx;
struct dp_event event_list[DP_EVENT_Q_MAX];
@@ -365,6 +365,20 @@ static void dp_display_host_init(struct dp_display_private *dp)
dp->core_initialized = true;
}
+static void dp_display_host_deinit(struct dp_display_private *dp)
+{
+ if (!dp->core_initialized) {
+ DRM_DEBUG_DP("DP core not initialized\n");
+ return;
+ }
+
+ dp_ctrl_host_deinit(dp->ctrl);
+ dp_aux_deinit(dp->aux);
+ dp_power_deinit(dp->power);
+
+ dp->core_initialized = false;
+}
+
static int dp_display_usbpd_configure_cb(struct device *dev)
{
int rc = 0;
@@ -489,7 +503,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
mutex_lock(&dp->event_mutex);
- state = atomic_read(&dp->hpd_state);
+ state = dp->hpd_state;
if (state == ST_SUSPEND_PENDING) {
mutex_unlock(&dp->event_mutex);
return 0;
@@ -507,14 +521,14 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
return 0;
}
- atomic_set(&dp->hpd_state, ST_CONNECT_PENDING);
+ dp->hpd_state = ST_CONNECT_PENDING;
hpd->hpd_high = 1;
ret = dp_display_usbpd_configure_cb(&dp->pdev->dev);
if (ret) { /* failed */
hpd->hpd_high = 0;
- atomic_set(&dp->hpd_state, ST_DISCONNECTED);
+ dp->hpd_state = ST_DISCONNECTED;
}
/* start sanity checking */
@@ -535,10 +549,10 @@ static int dp_connect_pending_timeout(struct dp_display_private *dp, u32 data)
mutex_lock(&dp->event_mutex);
- state = atomic_read(&dp->hpd_state);
+ state = dp->hpd_state;
if (state == ST_CONNECT_PENDING) {
dp_display_enable(dp, 0);
- atomic_set(&dp->hpd_state, ST_CONNECTED);
+ dp->hpd_state = ST_CONNECTED;
}
mutex_unlock(&dp->event_mutex);
@@ -571,7 +585,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
mutex_lock(&dp->event_mutex);
- state = atomic_read(&dp->hpd_state);
+ state = dp->hpd_state;
if (state == ST_SUSPEND_PENDING) {
mutex_unlock(&dp->event_mutex);
return 0;
@@ -589,7 +603,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
return 0;
}
- atomic_set(&dp->hpd_state, ST_DISCONNECT_PENDING);
+ dp->hpd_state = ST_DISCONNECT_PENDING;
/* disable HPD plug interrupt until disconnect is done */
dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK
@@ -624,10 +638,10 @@ static int dp_disconnect_pending_timeout(struct dp_display_private *dp, u32 data
mutex_lock(&dp->event_mutex);
- state = atomic_read(&dp->hpd_state);
+ state = dp->hpd_state;
if (state == ST_DISCONNECT_PENDING) {
dp_display_disable(dp, 0);
- atomic_set(&dp->hpd_state, ST_DISCONNECTED);
+ dp->hpd_state = ST_DISCONNECTED;
}
mutex_unlock(&dp->event_mutex);
@@ -642,7 +656,7 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
mutex_lock(&dp->event_mutex);
/* irq_hpd can happen at either connected or disconnected state */
- state = atomic_read(&dp->hpd_state);
+ state = dp->hpd_state;
if (state == ST_SUSPEND_PENDING) {
mutex_unlock(&dp->event_mutex);
return 0;
@@ -793,11 +807,6 @@ static int dp_display_enable(struct dp_display_private *dp, u32 data)
dp_display = g_dp_display;
- if (dp_display->power_on) {
- DRM_DEBUG_DP("Link already setup, return\n");
- return 0;
- }
-
rc = dp_ctrl_on_stream(dp->ctrl);
if (!rc)
dp_display->power_on = true;
@@ -830,9 +839,6 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data)
dp_display = g_dp_display;
- if (!dp_display->power_on)
- return -EINVAL;
-
/* wait only if audio was enabled */
if (dp_display->audio_enabled) {
if (!wait_for_completion_timeout(&dp->audio_comp,
@@ -1195,6 +1201,12 @@ static int dp_pm_resume(struct device *dev)
dp = container_of(dp_display, struct dp_display_private, dp_display);
+ mutex_lock(&dp->event_mutex);
+
+ /* start from disconnected state */
+ dp->hpd_state = ST_DISCONNECTED;
+
+ /* turn on dp ctrl/phy */
dp_display_host_init(dp);
dp_catalog_ctrl_hpd_config(dp->catalog);
@@ -1209,6 +1221,8 @@ static int dp_pm_resume(struct device *dev)
dp->core_initialized = false;
}
+ mutex_unlock(&dp->event_mutex);
+
return 0;
}
@@ -1220,10 +1234,14 @@ static int dp_pm_suspend(struct device *dev)
dp = container_of(dp_display, struct dp_display_private, dp_display);
- if (dp_display->power_on == true)
- dp_display_disable(dp, 0);
+ mutex_lock(&dp->event_mutex);
- atomic_set(&dp->hpd_state, ST_SUSPENDED);
+ if (dp->core_initialized == true)
+ dp_display_host_deinit(dp);
+
+ dp->hpd_state = ST_SUSPENDED;
+
+ mutex_unlock(&dp->event_mutex);
return 0;
}
@@ -1352,6 +1370,8 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder)
mutex_lock(&dp_display->event_mutex);
+ dp_del_event(dp_display, EV_CONNECT_PENDING_TIMEOUT);
+
rc = dp_display_set_mode(dp, &dp_display->dp_mode);
if (rc) {
DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc);
@@ -1366,7 +1386,10 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder)
return rc;
}
- state = atomic_read(&dp_display->hpd_state);
+ state = dp_display->hpd_state;
+
+ if (state == ST_DISPLAY_OFF)
+ dp_display_host_init(dp_display);
dp_display_enable(dp_display, 0);
@@ -1377,13 +1400,11 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder)
dp_display_unprepare(dp);
}
- dp_del_event(dp_display, EV_CONNECT_PENDING_TIMEOUT);
-
if (state == ST_SUSPEND_PENDING)
dp_add_event(dp_display, EV_IRQ_HPD_INT, 0, 0);
/* completed connection */
- atomic_set(&dp_display->hpd_state, ST_CONNECTED);
+ dp_display->hpd_state = ST_CONNECTED;
mutex_unlock(&dp_display->event_mutex);
@@ -1411,20 +1432,20 @@ int msm_dp_display_disable(struct msm_dp *dp, struct drm_encoder *encoder)
mutex_lock(&dp_display->event_mutex);
+ dp_del_event(dp_display, EV_DISCONNECT_PENDING_TIMEOUT);
+
dp_display_disable(dp_display, 0);
rc = dp_display_unprepare(dp);
if (rc)
DRM_ERROR("DP display unprepare failed, rc=%d\n", rc);
- dp_del_event(dp_display, EV_DISCONNECT_PENDING_TIMEOUT);
-
- state = atomic_read(&dp_display->hpd_state);
+ state = dp_display->hpd_state;
if (state == ST_DISCONNECT_PENDING) {
/* completed disconnection */
- atomic_set(&dp_display->hpd_state, ST_DISCONNECTED);
+ dp_display->hpd_state = ST_DISCONNECTED;
} else {
- atomic_set(&dp_display->hpd_state, ST_SUSPEND_PENDING);
+ dp_display->hpd_state = ST_SUSPEND_PENDING;
}
mutex_unlock(&dp_display->event_mutex);