diff options
author | Linux Build Service Account <lnxbuild@quicinc.com> | 2017-05-10 23:03:57 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-05-10 23:03:56 -0700 |
commit | abb1d6bee641b1c711d9179850b3343a2ea55190 (patch) | |
tree | 7247b5b4c822b8645207393e5f8b680cc40caad5 | |
parent | 4952fa00375232217890ec1536c23e7677029cad (diff) | |
parent | c74b2c0e58562e35883ebba0f6edf969279d7233 (diff) |
Merge "drm/msm: notify hpd status when audio codec is ready"
-rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c | 41 | ||||
-rw-r--r-- | drivers/platform/msm/msm_ext_display.c | 17 | ||||
-rw-r--r-- | include/linux/msm_ext_display.h | 2 |
5 files changed, 56 insertions, 60 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c index 1ff3ee2bdca6..dec3c8ae8b17 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c @@ -934,7 +934,6 @@ static void _sde_hdmi_hotplug_work(struct work_struct *work) } else sde_free_edid((void **)&sde_hdmi->edid_ctrl); - sde_hdmi_notify_clients(connector, sde_hdmi->connected); drm_helper_hpd_irq_event(connector->dev); } @@ -964,8 +963,7 @@ static void _sde_hdmi_connector_irq(struct sde_hdmi *sde_hdmi) hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT; hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl); - if (!sde_hdmi->non_pluggable) - queue_work(hdmi->workq, &sde_hdmi->hpd_work); + queue_work(hdmi->workq, &sde_hdmi->hpd_work); } } @@ -1054,6 +1052,25 @@ static int _sde_hdmi_get_cable_status(struct platform_device *pdev, u32 vote) return hdmi->power_on && display->connected; } +static void _sde_hdmi_audio_codec_ready(struct platform_device *pdev) +{ + struct sde_hdmi *display = platform_get_drvdata(pdev); + + if (!display) { + SDE_ERROR("invalid param(s), display %pK\n", display); + return; + } + + mutex_lock(&display->display_lock); + if (!display->codec_ready) { + display->codec_ready = true; + + if (display->client_notify_pending) + sde_hdmi_notify_clients(display, display->connected); + } + mutex_unlock(&display->display_lock); +} + static int _sde_hdmi_ext_disp_init(struct sde_hdmi *display) { int rc = 0; @@ -1073,6 +1090,8 @@ static int _sde_hdmi_ext_disp_init(struct sde_hdmi *display) _sde_hdmi_get_audio_edid_blk; display->ext_audio_data.codec_ops.cable_status = _sde_hdmi_get_cable_status; + display->ext_audio_data.codec_ops.codec_ready = + _sde_hdmi_audio_codec_ready; if (!display->pdev->dev.of_node) { SDE_ERROR("[%s]cannot find sde_hdmi of_node\n", display->name); @@ -1101,17 +1120,14 @@ static int _sde_hdmi_ext_disp_init(struct sde_hdmi *display) return rc; } -void sde_hdmi_notify_clients(struct drm_connector *connector, - bool connected) +void sde_hdmi_notify_clients(struct sde_hdmi *display, bool connected) { - struct sde_connector *c_conn = to_sde_connector(connector); - struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; int state = 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; + u32 flags = MSM_EXT_DISP_HPD_ASYNC_VIDEO; if (hdmi->hdmi_mode) flags |= MSM_EXT_DISP_HPD_AUDIO; @@ -1121,21 +1137,6 @@ void sde_hdmi_notify_clients(struct drm_connector *connector, } } -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 ecdace10d0c3..ffa9a27e7dfe 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h @@ -84,6 +84,8 @@ struct sde_hdmi_ctrl { * @connected: If HDMI display is connected. * @is_tpg_enabled: TPG state. * @hpd_work: HPD work structure. + * @codec_ready: If audio codec is ready. + * @client_notify_pending: If there is client notification pending. * @root: Debug fs root entry. */ struct sde_hdmi { @@ -109,6 +111,8 @@ struct sde_hdmi { bool is_tpg_enabled; struct work_struct hpd_work; + bool codec_ready; + bool client_notify_pending; /* DEBUG FS */ struct dentry *root; @@ -379,13 +383,12 @@ 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. + * @display: Handle to sde_hdmi. * @connected: connection status. * * Return: void. */ -void sde_hdmi_notify_clients(struct drm_connector *connector, - bool connected); +void sde_hdmi_notify_clients(struct sde_hdmi *display, bool connected); /** * sde_hdmi_ack_state() - acknowledge the connection status. 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 6c82c3d4826d..34268aaedfc0 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c @@ -372,6 +372,8 @@ static void _sde_hdmi_bridge_pre_enable(struct drm_bridge *bridge) struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = sde_hdmi_bridge->hdmi; struct hdmi_phy *phy = hdmi->phy; + struct sde_connector *c_conn = to_sde_connector(hdmi->connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; DRM_DEBUG("power up"); @@ -388,41 +390,20 @@ 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); - } + mutex_lock(&display->display_lock); + if (display->codec_ready) + sde_hdmi_notify_clients(display, display->connected); + else + display->client_notify_pending = true; + mutex_unlock(&display->display_lock); } 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) @@ -430,6 +411,10 @@ static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge) struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = sde_hdmi_bridge->hdmi; struct hdmi_phy *phy = hdmi->phy; + struct sde_connector *c_conn = to_sde_connector(hdmi->connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; + + sde_hdmi_notify_clients(display, display->connected); if (hdmi->hdcp_ctrl && hdmi->is_hdcp_supported) hdmi_hdcp_ctrl_off(hdmi->hdcp_ctrl); @@ -446,8 +431,6 @@ 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, diff --git a/drivers/platform/msm/msm_ext_display.c b/drivers/platform/msm/msm_ext_display.c index 6f9a13040cd5..c7c1b1567bf3 100644 --- a/drivers/platform/msm/msm_ext_display.c +++ b/drivers/platform/msm/msm_ext_display.c @@ -654,6 +654,7 @@ int msm_ext_disp_register_audio_codec(struct platform_device *pdev, { int ret = 0; struct msm_ext_disp *ext_disp = NULL; + struct msm_ext_disp_list *node = NULL; if (!pdev || !ops) { pr_err("Invalid params\n"); @@ -671,17 +672,23 @@ int msm_ext_disp_register_audio_codec(struct platform_device *pdev, if ((ext_disp->current_disp != EXT_DISPLAY_TYPE_MAX) && ext_disp->ops) { pr_err("Codec already registered\n"); - ret = -EINVAL; - goto end; + mutex_unlock(&ext_disp->lock); + return -EINVAL; } ext_disp->ops = ops; - pr_debug("audio codec registered\n"); - -end: mutex_unlock(&ext_disp->lock); + list_for_each_entry(node, &ext_disp->display_list, list) { + struct msm_ext_disp_init_data *data = node->data; + + if (data->codec_ops.codec_ready) + data->codec_ops.codec_ready(data->pdev); + } + + pr_debug("audio codec registered\n"); + return ret; } diff --git a/include/linux/msm_ext_display.h b/include/linux/msm_ext_display.h index fc53e861eba4..9a03b79e09d7 100644 --- a/include/linux/msm_ext_display.h +++ b/include/linux/msm_ext_display.h @@ -114,6 +114,7 @@ struct msm_ext_disp_intf_ops { * @cable_status: cable connected/disconnected * @get_intf_id: id of connected interface * @acknowledge: acknowledge audio status + * @codec_ready: notify when codec is ready */ struct msm_ext_disp_audio_codec_ops { int (*audio_info_setup)(struct platform_device *pdev, @@ -124,6 +125,7 @@ struct msm_ext_disp_audio_codec_ops { int (*get_intf_id)(struct platform_device *pdev); void (*teardown_done)(struct platform_device *pdev); int (*acknowledge)(struct platform_device *pdev, u32 ack); + void (*codec_ready)(struct platform_device *pdev); }; /* |