summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorAravind Venkateswaran <aravindh@codeaurora.org>2016-12-08 15:19:23 -0800
committerAravind Venkateswaran <aravindh@codeaurora.org>2016-12-08 15:47:13 -0800
commit1bd7966d14bf125a8d53dd53229ed2c8dda174e5 (patch)
treec4a9b38413370a862922af00049d47a449784912 /drivers/video
parent368fecd7df5b203a5ce684a0c77726a5690c1147 (diff)
msm: mdss: fix handling of audio for DVI sinks
Certain sinks (such as DVI monitors) do not support audio which can be identified using the sink's EDID. For such sinks, ensure that audio is not routed over the external display. Change-Id: I1c1a634bf096392094b5fd868a87385764657e6b CRs-Fixed: 1093442 Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fbdev/msm/mdss_dba_utils.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c13
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.c19
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c15
-rw-r--r--drivers/video/fbdev/msm/msm_ext_display.c56
6 files changed, 84 insertions, 23 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dba_utils.c b/drivers/video/fbdev/msm/mdss_dba_utils.c
index 76671b539aa7..0808a1a6e14b 100644
--- a/drivers/video/fbdev/msm/mdss_dba_utils.c
+++ b/drivers/video/fbdev/msm/mdss_dba_utils.c
@@ -542,7 +542,7 @@ int mdss_dba_utils_video_on(void *data, struct mdss_panel_info *pinfo)
video_cfg.h_pulse_width = pinfo->lcdc.h_pulse_width;
video_cfg.v_pulse_width = pinfo->lcdc.v_pulse_width;
video_cfg.pclk_khz = (unsigned long)pinfo->clk_rate / 1000;
- video_cfg.hdmi_mode = hdmi_edid_get_sink_mode(ud->edid_data);
+ video_cfg.hdmi_mode = !hdmi_edid_is_dvi_mode(ud->edid_data);
/* Calculate number of DSI lanes configured */
video_cfg.num_of_input_lanes = 0;
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 032f4ca38e50..e1ef4999e882 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -898,6 +898,11 @@ static int dp_get_cable_status(struct platform_device *pdev, u32 vote)
return hpd;
}
+static bool mdss_dp_is_dvi_mode(struct mdss_dp_drv_pdata *dp)
+{
+ return hdmi_edid_is_dvi_mode(dp->panel_data.panel_info.edid_data);
+}
+
static int dp_audio_info_setup(struct platform_device *pdev,
struct msm_ext_disp_audio_setup_params *params)
{
@@ -1447,6 +1452,7 @@ static int mdss_dp_send_cable_notification(
struct mdss_dp_drv_pdata *dp, int val)
{
int ret = 0;
+ u32 flags = 0;
if (!dp) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -1454,9 +1460,12 @@ static int mdss_dp_send_cable_notification(
goto end;
}
- if (dp && dp->ext_audio_data.intf_ops.hpd)
+ if (mdss_dp_is_dvi_mode(dp))
+ flags |= MSM_EXT_DISP_HPD_NO_AUDIO;
+
+ if (dp->ext_audio_data.intf_ops.hpd)
ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
- dp->ext_audio_data.type, val);
+ dp->ext_audio_data.type, val, flags);
end:
return ret;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
index 0a316fa19909..3adf04214d87 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
@@ -2294,6 +2294,7 @@ int hdmi_edid_parser(void *input)
edid_buf += EDID_BLOCK_SIZE;
ieee_reg_id = hdmi_edid_extract_ieee_reg_id(edid_ctrl, edid_buf);
+ DEV_DBG("%s: ieee_reg_id = 0x%08x\n", __func__, ieee_reg_id);
if (ieee_reg_id == EDID_IEEE_REG_ID)
edid_ctrl->sink_mode = SINK_MODE_HDMI;
else
@@ -2388,7 +2389,7 @@ end:
return scaninfo;
} /* hdmi_edid_get_sink_scaninfo */
-u32 hdmi_edid_get_sink_mode(void *input)
+static u32 hdmi_edid_get_sink_mode(void *input)
{
struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
bool sink_mode;
@@ -2408,6 +2409,22 @@ u32 hdmi_edid_get_sink_mode(void *input)
} /* hdmi_edid_get_sink_mode */
/**
+ * hdmi_edid_is_dvi_mode() - check if the dvi mode is set in the EDID
+ * @input: edid parser data
+ *
+ * This API returns true is the DVI mode bit in the EDID is set. This
+ * API can be used to check if the sink associated with the EDID data
+ * is a DVI sink or not
+ */
+bool hdmi_edid_is_dvi_mode(void *input)
+{
+ if (hdmi_edid_get_sink_mode(input))
+ return false;
+ else
+ return true;
+}
+
+/**
* hdmi_edid_get_deep_color() - get deep color info supported by sink
* @input: edid parser data
*
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.h b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
index 43e1adb1f139..5ee77fcf2066 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
@@ -47,7 +47,7 @@ struct hdmi_edid_hdr_data {
int hdmi_edid_parser(void *edid_ctrl);
u32 hdmi_edid_get_raw_data(void *edid_ctrl, u8 *buf, u32 size);
u8 hdmi_edid_get_sink_scaninfo(void *edid_ctrl, u32 resolution);
-u32 hdmi_edid_get_sink_mode(void *edid_ctrl);
+bool hdmi_edid_is_dvi_mode(void *input);
bool hdmi_edid_sink_scramble_override(void *input);
bool hdmi_edid_get_sink_scrambler_support(void *input);
bool hdmi_edid_get_scdc_support(void *input);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index e9ae30bb6914..fe9198f2d17a 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -374,8 +374,7 @@ static void hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- return hdmi_edid_get_sink_mode(
- hdmi_tx_get_fd(HDMI_TX_FEAT_EDID)) ? 0 : 1;
+ return hdmi_edid_is_dvi_mode(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID));
} /* hdmi_tx_is_dvi_mode */
static inline bool hdmi_tx_is_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -417,9 +416,15 @@ 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)
{
- if (hdmi_ctrl && hdmi_ctrl->ext_audio_data.intf_ops.hpd)
+ if (hdmi_ctrl && hdmi_ctrl->ext_audio_data.intf_ops.hpd) {
+ u32 flags = 0;
+
+ if (hdmi_tx_is_dvi_mode(hdmi_ctrl))
+ flags |= MSM_EXT_DISP_HPD_NO_AUDIO;
+
hdmi_ctrl->ext_audio_data.intf_ops.hpd(hdmi_ctrl->ext_pdev,
- hdmi_ctrl->ext_audio_data.type, val);
+ hdmi_ctrl->ext_audio_data.type, val, flags);
+ }
}
static inline void hdmi_tx_set_audio_switch_node(
@@ -2450,7 +2455,7 @@ static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
hdmi_ctrl_reg |= BIT(2);
/* Set transmission mode to DVI based in EDID info */
- if (!hdmi_edid_get_sink_mode(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID)))
+ if (hdmi_edid_is_dvi_mode(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID)))
hdmi_ctrl_reg &= ~BIT(1); /* DVI mode */
/*
diff --git a/drivers/video/fbdev/msm/msm_ext_display.c b/drivers/video/fbdev/msm/msm_ext_display.c
index ca01ee6345d2..4fccf1178dac 100644
--- a/drivers/video/fbdev/msm/msm_ext_display.c
+++ b/drivers/video/fbdev/msm/msm_ext_display.c
@@ -49,7 +49,8 @@ static int msm_ext_disp_get_intf_data(struct msm_ext_disp *ext_disp,
struct msm_ext_disp_init_data **data);
static int msm_ext_disp_audio_ack(struct platform_device *pdev, u32 ack);
static int msm_ext_disp_update_audio_ops(struct msm_ext_disp *ext_disp,
- enum msm_ext_disp_cable_state state);
+ enum msm_ext_disp_type type,
+ enum msm_ext_disp_cable_state state, u32 flags);
static int msm_ext_disp_switch_dev_register(struct msm_ext_disp *ext_disp)
{
@@ -359,9 +360,18 @@ static int msm_ext_disp_send_audio_notification(struct msm_ext_disp *ext_disp,
}
static int msm_ext_disp_process_display(struct msm_ext_disp *ext_disp,
- enum msm_ext_disp_cable_state state)
+ enum msm_ext_disp_type type,
+ enum msm_ext_disp_cable_state state, u32 flags)
{
- int ret = msm_ext_disp_send_cable_notification(ext_disp, state);
+ int ret = 0;
+
+ if (flags & MSM_EXT_DISP_HPD_NO_VIDEO) {
+ pr_debug("skipping video setup for display (%s)\n",
+ msm_ext_disp_name(type));
+ goto end;
+ }
+
+ ret = msm_ext_disp_send_cable_notification(ext_disp, state);
/* positive ret value means audio node was switched */
if (IS_ERR_VALUE(ret) || !ret) {
@@ -383,9 +393,18 @@ end:
}
static int msm_ext_disp_process_audio(struct msm_ext_disp *ext_disp,
- enum msm_ext_disp_cable_state state)
+ enum msm_ext_disp_type type,
+ enum msm_ext_disp_cable_state state, u32 flags)
{
- int ret = msm_ext_disp_send_audio_notification(ext_disp, state);
+ int ret = 0;
+
+ if (flags & MSM_EXT_DISP_HPD_NO_AUDIO) {
+ pr_debug("skipping audio setup for display (%s)\n",
+ msm_ext_disp_name(type));
+ goto end;
+ }
+
+ 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) {
@@ -408,7 +427,8 @@ end:
static int msm_ext_disp_hpd(struct platform_device *pdev,
enum msm_ext_disp_type type,
- enum msm_ext_disp_cable_state state)
+ enum msm_ext_disp_cable_state state,
+ u32 flags)
{
int ret = 0;
struct msm_ext_disp *ext_disp = NULL;
@@ -455,21 +475,24 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
if (state == EXT_DISPLAY_CABLE_CONNECT) {
ext_disp->current_disp = type;
- ret = msm_ext_disp_process_display(ext_disp, state);
+ ret = msm_ext_disp_process_display(ext_disp, type, state,
+ flags);
if (ret)
goto end;
- msm_ext_disp_update_audio_ops(ext_disp, state);
+ ret = msm_ext_disp_update_audio_ops(ext_disp, type, state,
+ flags);
if (ret)
goto end;
- ret = msm_ext_disp_process_audio(ext_disp, state);
+ ret = msm_ext_disp_process_audio(ext_disp, type, state,
+ flags);
if (ret)
goto end;
} else {
- msm_ext_disp_process_audio(ext_disp, state);
- msm_ext_disp_update_audio_ops(ext_disp, state);
- msm_ext_disp_process_display(ext_disp, state);
+ msm_ext_disp_process_audio(ext_disp, type, state, flags);
+ msm_ext_disp_update_audio_ops(ext_disp, type, state, flags);
+ msm_ext_disp_process_display(ext_disp, type, state, flags);
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
}
@@ -624,11 +647,18 @@ end:
}
static int msm_ext_disp_update_audio_ops(struct msm_ext_disp *ext_disp,
- enum msm_ext_disp_cable_state state)
+ enum msm_ext_disp_type type,
+ enum msm_ext_disp_cable_state state, u32 flags)
{
int ret = 0;
struct msm_ext_disp_audio_codec_ops *ops = ext_disp->ops;
+ if (flags & MSM_EXT_DISP_HPD_NO_AUDIO) {
+ pr_debug("skipping audio ops setup for display (%s)\n",
+ msm_ext_disp_name(type));
+ goto end;
+ }
+
if (!ops) {
pr_err("Invalid audio ops\n");
ret = -EINVAL;