summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-05-10 23:03:57 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-05-10 23:03:56 -0700
commitabb1d6bee641b1c711d9179850b3343a2ea55190 (patch)
tree7247b5b4c822b8645207393e5f8b680cc40caad5
parent4952fa00375232217890ec1536c23e7677029cad (diff)
parentc74b2c0e58562e35883ebba0f6edf969279d7233 (diff)
Merge "drm/msm: notify hpd status when audio codec is ready"
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c47
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h9
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c41
-rw-r--r--drivers/platform/msm/msm_ext_display.c17
-rw-r--r--include/linux/msm_ext_display.h2
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);
};
/*