summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Zhang <rayz@codeaurora.org>2017-01-06 16:25:15 +0800
committerzhaoyuan <yzhao@codeaurora.org>2017-03-24 17:46:58 +0800
commitd679cf981bd35f67b38d82e03507e2c869d14842 (patch)
tree63922943fed4a5b28a5a1f12b34f5f2d065eca00
parent687a4eb82be5905f5400678dcaff4e98dad72e3c (diff)
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>
-rw-r--r--drivers/platform/msm/msm_ext_display.c18
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c39
-rw-r--r--include/linux/msm_ext_display.h4
3 files changed, 45 insertions, 16 deletions
diff --git a/drivers/platform/msm/msm_ext_display.c b/drivers/platform/msm/msm_ext_display.c
index a35ed1afc720..6f9a13040cd5 100644
--- a/drivers/platform/msm/msm_ext_display.c
+++ b/drivers/platform/msm/msm_ext_display.c
@@ -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,
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index f05d4cb2922a..42845f9ff192 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -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;
diff --git a/include/linux/msm_ext_display.h b/include/linux/msm_ext_display.h
index d9831d7cbb4e..fc53e861eba4 100644
--- a/include/linux/msm_ext_display.h
+++ b/include/linux/msm_ext_display.h
@@ -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