disp: msm: dp: fix for screen freeze on dp disconnect

The DP display driver issues an audio disconnect notification
after the video disconnect notification. Sometimes audio driver
is waiting for the video commit to complete before turning off
the audio engine. In such cases, there is a brief screen freeze
observed on the primary. In other cases, when the off call from
audio driver gets delayed, a momentary screen freeze is seen.
The audio notification happens as part of the display commit call.

The order of notification is video and then audio while
processing display connect and the same order is followed for
disconnect also, which is causing this issue. These changes will
modify the order of notification to send audio disconnect first
and then video while processing DP cable disconnect.

Change-Id: I8bece39c164620b319d971e5a2597d9dc187566e
Signed-off-by: Sankeerth Billakanti <sbillaka@codeaurora.org>
Signed-off-by: Tatenda Chipeperekwa <tatendac@codeaurora.org>
This commit is contained in:
Sankeerth Billakanti 2019-12-27 11:17:46 +05:30 committed by Tatenda Chipeperekwa
parent be267c80f7
commit 33f6b8e11e
2 changed files with 32 additions and 26 deletions

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/of_platform.h>
@ -766,6 +766,12 @@ static int dp_audio_off(struct dp_audio *dp_audio)
}
audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
if (!atomic_read(&audio->session_on)) {
DP_DEBUG("audio already off\n");
return rc;
}
ext = &audio->ext_audio_data;
work_pending = cancel_delayed_work_sync(&audio->notify_delayed_work);

View File

@ -246,6 +246,30 @@ static bool dp_display_is_ready(struct dp_display_private *dp)
dp->hpd->alt_mode_cfg_done;
}
static void dp_audio_enable(struct dp_display_private *dp, bool enable)
{
struct dp_panel *dp_panel;
int idx;
for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) {
if (!dp->active_panels[idx])
continue;
dp_panel = dp->active_panels[idx];
if (dp_panel->audio_supported) {
if (enable) {
dp_panel->audio->bw_code =
dp->link->link_params.bw_code;
dp_panel->audio->lane_count =
dp->link->link_params.lane_count;
dp_panel->audio->on(dp_panel->audio);
} else {
dp_panel->audio->off(dp_panel->audio);
}
}
}
}
static void dp_display_update_hdcp_status(struct dp_display_private *dp,
bool reset)
{
@ -1065,7 +1089,7 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp)
dp_display_state_remove(DP_STATE_CONNECTED);
dp->process_hpd_connect = false;
dp_audio_enable(dp, false);
dp_display_process_mst_hpd_low(dp);
if ((dp_display_state_is(DP_STATE_CONNECT_NOTIFIED) ||
@ -1150,30 +1174,6 @@ static void dp_display_stream_disable(struct dp_display_private *dp,
dp->active_stream_cnt--;
}
static void dp_audio_enable(struct dp_display_private *dp, bool enable)
{
struct dp_panel *dp_panel;
int idx;
for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) {
if (!dp->active_panels[idx])
continue;
dp_panel = dp->active_panels[idx];
if (dp_panel->audio_supported) {
if (enable) {
dp_panel->audio->bw_code =
dp->link->link_params.bw_code;
dp_panel->audio->lane_count =
dp->link->link_params.lane_count;
dp_panel->audio->on(dp_panel->audio);
} else {
dp_panel->audio->off(dp_panel->audio);
}
}
}
}
static void dp_display_clean(struct dp_display_private *dp)
{
int idx;