msm: mdss: make hpd call asynchronous for HDMI in certain cases

In some cases the hpd call cannot be blocked. For example, in
case of framework restart, both display and audio HALs are not
available, so nobody will notify and unblock hpd call. Another
case is continuous splash in which unblank is delayed till the
first display kickoff, so hpd cannot blocking wait for such a
late notification.

Change-Id: I6ed58c3ac35efdaeac2e73d36d78b7fd64a74f42
Signed-off-by: Ray Zhang <rayz@codeaurora.org>
This commit is contained in:
Ray Zhang 2017-01-06 16:25:15 +08:00 committed by zhaoyuan
parent 687a4eb82b
commit d679cf981b
3 changed files with 45 additions and 16 deletions

View file

@ -215,7 +215,8 @@ static int msm_ext_disp_process_display(struct msm_ext_disp *ext_disp,
{
int ret = 0;
if (!(flags & MSM_EXT_DISP_HPD_VIDEO)) {
if (!(flags & (MSM_EXT_DISP_HPD_VIDEO
| MSM_EXT_DISP_HPD_ASYNC_VIDEO))) {
pr_debug("skipping video setup for display (%s)\n",
msm_ext_disp_name(type));
goto end;
@ -224,7 +225,8 @@ static int msm_ext_disp_process_display(struct msm_ext_disp *ext_disp,
ret = msm_ext_disp_send_cable_notification(ext_disp, state);
/* positive ret value means audio node was switched */
if (IS_ERR_VALUE(ret) || !ret) {
if ((ret <= 0) ||
(flags & MSM_EXT_DISP_HPD_ASYNC_VIDEO)) {
pr_debug("not waiting for display\n");
goto end;
}
@ -237,9 +239,8 @@ static int msm_ext_disp_process_display(struct msm_ext_disp *ext_disp,
goto end;
}
ret = 0;
end:
return ret;
return (ret >= 0) ? 0 : -EINVAL;
}
static int msm_ext_disp_process_audio(struct msm_ext_disp *ext_disp,
@ -248,7 +249,8 @@ static int msm_ext_disp_process_audio(struct msm_ext_disp *ext_disp,
{
int ret = 0;
if (!(flags & MSM_EXT_DISP_HPD_AUDIO)) {
if (!(flags & (MSM_EXT_DISP_HPD_AUDIO
| MSM_EXT_DISP_HPD_ASYNC_AUDIO))) {
pr_debug("skipping audio setup for display (%s)\n",
msm_ext_disp_name(type));
goto end;
@ -257,7 +259,8 @@ static int msm_ext_disp_process_audio(struct msm_ext_disp *ext_disp,
ret = msm_ext_disp_send_audio_notification(ext_disp, state);
/* positive ret value means audio node was switched */
if (IS_ERR_VALUE(ret) || !ret || !ext_disp->ack_enabled) {
if ((ret <= 0) || !ext_disp->ack_enabled ||
(flags & MSM_EXT_DISP_HPD_ASYNC_AUDIO)) {
pr_debug("not waiting for audio\n");
goto end;
}
@ -270,9 +273,8 @@ static int msm_ext_disp_process_audio(struct msm_ext_disp *ext_disp,
goto end;
}
ret = 0;
end:
return ret;
return (ret >= 0) ? 0 : -EINVAL;
}
static bool msm_ext_disp_validate_connect(struct msm_ext_disp *ext_disp,

View file

@ -380,6 +380,13 @@ static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
return hdmi_edid_is_dvi_mode(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID));
} /* hdmi_tx_is_dvi_mode */
static inline u32 hdmi_tx_is_in_splash(struct hdmi_tx_ctrl *hdmi_ctrl)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
return mdata->handoff_pending;
}
static inline bool hdmi_tx_is_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl)
{
return hdmi_ctrl->hpd_state && hdmi_ctrl->panel_power_on;
@ -416,15 +423,27 @@ static inline void hdmi_tx_cec_device_suspend(struct hdmi_tx_ctrl *hdmi_ctrl)
}
static inline void hdmi_tx_send_cable_notification(
struct hdmi_tx_ctrl *hdmi_ctrl, int val)
struct hdmi_tx_ctrl *hdmi_ctrl, int val, bool async)
{
if (hdmi_ctrl && hdmi_ctrl->ext_audio_data.intf_ops.hpd) {
u32 flags = 0;
flags |= MSM_EXT_DISP_HPD_VIDEO;
if (async || hdmi_tx_is_in_splash(hdmi_ctrl)) {
flags |= MSM_EXT_DISP_HPD_ASYNC_VIDEO;
if (!hdmi_tx_is_dvi_mode(hdmi_ctrl))
flags |= MSM_EXT_DISP_HPD_AUDIO;
if (async) {
if (!hdmi_tx_is_dvi_mode(hdmi_ctrl))
flags |= MSM_EXT_DISP_HPD_ASYNC_AUDIO;
} else
if (!hdmi_tx_is_dvi_mode(hdmi_ctrl))
flags |= MSM_EXT_DISP_HPD_AUDIO;
} else {
flags |= MSM_EXT_DISP_HPD_VIDEO;
if (!hdmi_tx_is_dvi_mode(hdmi_ctrl))
flags |= MSM_EXT_DISP_HPD_AUDIO;
}
hdmi_ctrl->ext_audio_data.intf_ops.hpd(hdmi_ctrl->ext_pdev,
hdmi_ctrl->ext_audio_data.type, val, flags);
@ -859,7 +878,11 @@ static ssize_t hdmi_tx_sysfs_wta_hpd(struct device *dev,
hdmi_tx_config_5v(hdmi_ctrl, false);
} else {
hdmi_tx_hpd_off(hdmi_ctrl);
hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
/*
* No need to blocking wait for display/audio in this
* case since HAL is not up so no ACK can be expected.
*/
hdmi_tx_send_cable_notification(hdmi_ctrl, 0, true);
}
break;
@ -2339,7 +2362,7 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work)
mutex_unlock(&hdmi_ctrl->tx_lock);
hdmi_tx_send_cable_notification(hdmi_ctrl, hdmi_ctrl->hpd_state);
hdmi_tx_send_cable_notification(hdmi_ctrl, hdmi_ctrl->hpd_state, false);
} /* hdmi_tx_hpd_int_work */
static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl)
@ -3956,7 +3979,7 @@ static int hdmi_tx_post_evt_handle_resume(struct hdmi_tx_ctrl *hdmi_ctrl)
&hdmi_ctrl->hpd_int_done, HZ/10);
if (!timeout) {
pr_debug("cable removed during suspend\n");
hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
hdmi_tx_send_cable_notification(hdmi_ctrl, 0, false);
}
}
@ -3967,7 +3990,7 @@ static int hdmi_tx_post_evt_handle_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl)
{
if (hdmi_ctrl->panel_suspend) {
pr_debug("panel suspend has triggered\n");
hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
hdmi_tx_send_cable_notification(hdmi_ctrl, 0, false);
}
return 0;

View file

@ -26,9 +26,13 @@
* interface:
* MSM_EXT_DISP_HPD_AUDIO: audio will be routed to external display
* MSM_EXT_DISP_HPD_VIDEO: video will be routed to external display
* MSM_EXT_DISP_HPD_ASYNC_AUDIO: don't wait audio notification once wake it up
* MSM_EXT_DISP_HPD_ASYNC_VIDEO: don't wait video notification once wake it up
*/
#define MSM_EXT_DISP_HPD_AUDIO BIT(0)
#define MSM_EXT_DISP_HPD_VIDEO BIT(1)
#define MSM_EXT_DISP_HPD_ASYNC_AUDIO BIT(2)
#define MSM_EXT_DISP_HPD_ASYNC_VIDEO BIT(3)
/**
* struct ext_disp_cable_notify - cable notify handler structure