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>
This commit is contained in:
parent
368fecd7df
commit
1bd7966d14
7 changed files with 95 additions and 24 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue