OSDN Git Service

Merge "drm/msm: notify hpd status when audio codec is ready"
authorLinux Build Service Account <lnxbuild@quicinc.com>
Thu, 11 May 2017 06:03:57 +0000 (23:03 -0700)
committerGerrit - the friendly Code Review server <code-review@localhost>
Thu, 11 May 2017 06:03:56 +0000 (23:03 -0700)
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
drivers/platform/msm/msm_ext_display.c
include/linux/msm_ext_display.h

index 1ff3ee2..dec3c8a 100644 (file)
@@ -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;
index ecdace1..ffa9a27 100644 (file)
@@ -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.
index 6c82c3d..34268aa 100644 (file)
@@ -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,
index 6f9a130..c7c1b15 100644 (file)
@@ -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;
 }
 
index fc53e86..9a03b79 100644 (file)
@@ -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);
 };
 
 /*