diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c index dd1ec46ad5c2..a030af02454b 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c @@ -25,6 +25,7 @@ #include #include "sde_kms.h" +#include "sde_connector.h" #include "msm_drv.h" #include "sde_hdmi.h" @@ -404,6 +405,8 @@ static void _sde_hdmi_hotplug_work(struct work_struct *work) connector = sde_hdmi->ctrl.ctrl->connector; drm_helper_hpd_irq_event(connector->dev); + + sde_hdmi_notify_clients(connector, connector->status); } static void _sde_hdmi_connector_irq(struct sde_hdmi *sde_hdmi) @@ -569,6 +572,41 @@ static int _sde_hdmi_ext_disp_init(struct sde_hdmi *display) return rc; } +void sde_hdmi_notify_clients(struct drm_connector *connector, + enum drm_connector_status status) +{ + struct sde_connector *c_conn = to_sde_connector(connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; + int state = (status == connector_status_connected) ? + EXT_DISPLAY_CABLE_CONNECT : EXT_DISPLAY_CABLE_DISCONNECT; + + if (display && display->ext_audio_data.intf_ops.hpd) { + struct hdmi *hdmi = display->ctrl.ctrl; + u32 flags = MSM_EXT_DISP_HPD_VIDEO; + + if (hdmi->hdmi_mode) + flags |= MSM_EXT_DISP_HPD_AUDIO; + + display->ext_audio_data.intf_ops.hpd(display->ext_pdev, + display->ext_audio_data.type, state, flags); + } +} + +void sde_hdmi_ack_state(struct drm_connector *connector, + enum drm_connector_status status) +{ + struct sde_connector *c_conn = to_sde_connector(connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; + + if (display) { + struct hdmi *hdmi = display->ctrl.ctrl; + + if (hdmi->hdmi_mode && display->ext_audio_data.intf_ops.notify) + display->ext_audio_data.intf_ops.notify( + display->ext_pdev, status); + } +} + void sde_hdmi_set_mode(struct hdmi *hdmi, bool power_on) { uint32_t ctrl = 0; diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h index 696752de1880..1004959ceb83 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h @@ -271,6 +271,27 @@ void sde_hdmi_audio_off(struct hdmi *hdmi); * Return: error code. */ int sde_hdmi_config_avmute(struct hdmi *hdmi, bool set); + +/** + * sde_hdmi_notify_clients() - notify hdmi clients of the connection status. + * @connector: Handle to the drm_connector. + * @status: connection status. + * + * Return: void. + */ +void sde_hdmi_notify_clients(struct drm_connector *connector, + enum drm_connector_status status); + +/** + * sde_hdmi_ack_state() - acknowledge the connection status. + * @connector: Handle to the drm_connector. + * @status: connection status. + * + * Return: void. + */ +void sde_hdmi_ack_state(struct drm_connector *connector, + enum drm_connector_status status); + #else /*#ifdef CONFIG_DRM_SDE_HDMI*/ static inline u32 sde_hdmi_get_num_of_displays(void) diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c index 7d3871cbe783..681dca501f9b 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c @@ -18,6 +18,7 @@ #include "drm_edid.h" #include "sde_kms.h" +#include "sde_connector.h" #include "sde_hdmi.h" #include "hdmi.h" @@ -120,14 +121,42 @@ static void _sde_hdmi_bridge_pre_enable(struct drm_bridge *bridge) if (hdmi->hdcp_ctrl && hdmi->is_hdcp_supported) hdmi_hdcp_ctrl_on(hdmi->hdcp_ctrl); + + sde_hdmi_ack_state(hdmi->connector, EXT_DISPLAY_CABLE_CONNECT); +} + +static void sde_hdmi_force_update_audio(struct drm_connector *connector, + enum drm_connector_status status) +{ + struct sde_connector *c_conn = to_sde_connector(connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; + + if (display && display->non_pluggable) { + display->ext_audio_data.intf_ops.hpd(display->ext_pdev, + display->ext_audio_data.type, + status, + MSM_EXT_DISP_HPD_AUDIO); + } } static void _sde_hdmi_bridge_enable(struct drm_bridge *bridge) { + struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = sde_hdmi_bridge->hdmi; + + /* force update audio ops when there's no HPD event */ + sde_hdmi_force_update_audio(hdmi->connector, + EXT_DISPLAY_CABLE_CONNECT); } static void _sde_hdmi_bridge_disable(struct drm_bridge *bridge) { + struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = sde_hdmi_bridge->hdmi; + + /* force update audio ops when there's no HPD event */ + sde_hdmi_force_update_audio(hdmi->connector, + EXT_DISPLAY_CABLE_DISCONNECT); } static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge) @@ -151,6 +180,8 @@ static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge) _sde_hdmi_bridge_power_off(bridge); hdmi->power_on = false; } + + sde_hdmi_ack_state(hdmi->connector, EXT_DISPLAY_CABLE_DISCONNECT); } static void _sde_hdmi_bridge_set_avi_infoframe(struct hdmi *hdmi,