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; @@ -2407,6 +2408,22 @@ u32 hdmi_edid_get_sink_mode(void *input) return sink_mode; } /* 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; diff --git a/include/linux/msm_ext_display.h b/include/linux/msm_ext_display.h index 59ba776b5f9b..b3a7e4ad722a 100644 --- a/include/linux/msm_ext_display.h +++ b/include/linux/msm_ext_display.h @@ -21,6 +21,15 @@ #define AUDIO_ACK_ENABLE BIT(4) #define AUDIO_ACK_CONNECT BIT(0) +/** + * Flags to be used with the HPD operation of the external display + * interface: + * MSM_EXT_DISP_HPD_NO_AUDIO: audio will not be routed to external display + * MSM_EXT_DISP_HPD_NO_VIDEO: video will not be routed to external display + */ +#define MSM_EXT_DISP_HPD_NO_AUDIO BIT(0) +#define MSM_EXT_DISP_HPD_NO_VIDEO BIT(1) + /** * struct ext_disp_cable_notify - cable notify handler structure * @link: a link for the linked list @@ -87,7 +96,8 @@ enum msm_ext_disp_power_state { struct msm_ext_disp_intf_ops { int (*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 (*notify)(struct platform_device *pdev, enum msm_ext_disp_cable_state state); int (*ack)(struct platform_device *pdev,