summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-10-10 18:28:15 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-10-10 18:28:15 -0700
commit31e788f9f2d967bc8a0b7e8e4160487e9a9c4aeb (patch)
treef6bea752e7df7adf632afc1d5bd39fef5a975093
parent5cdf898e80161a6104a3d28488ad38a371b65d34 (diff)
parent92618b15ee45d8bf47affb23a4147c924f4638cf (diff)
Merge "mdss: DisplayPort: update link-training settings and do DP reset"
-rw-r--r--drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c83
-rw-r--r--drivers/clk/msm/mdss/mdss-dp-pll-cobalt.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c119
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_aux.c14
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.c23
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.h5
-rw-r--r--drivers/video/fbdev/msm/msm_ext_display.c18
-rw-r--r--include/linux/msm_ext_display.h1
9 files changed, 222 insertions, 44 deletions
diff --git a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c
index 9a080e4ee39b..a574a9cd2b5a 100644
--- a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c
+++ b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c
@@ -18,6 +18,7 @@
#include <linux/iopoll.h>
#include <linux/delay.h>
#include <linux/clk/msm-clock-generic.h>
+#include <linux/usb/usbpd.h>
#include "mdss-pll.h"
#include "mdss-dp-pll.h"
@@ -172,9 +173,27 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)
{
u32 res = 0;
struct mdss_pll_resources *dp_res = vco->priv;
+ u8 orientation, ln_cnt;
+ u32 spare_value;
+
+ spare_value = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_SPARE0);
+ ln_cnt = spare_value & 0x0F;
+ orientation = (spare_value & 0xF0) >> 4;
+ pr_debug("%s: spare_value=0x%x, ln_cnt=0x%x, orientation=0x%x\n",
+ __func__, spare_value, ln_cnt, orientation);
+
+ if (ln_cnt != 4) {
+ if (orientation == ORIENTATION_CC2)
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_PD_CTL, 0x2d);
+ else
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_PD_CTL, 0x35);
+ } else {
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_PD_CTL, 0x3d);
+ }
- MDSS_PLL_REG_W(dp_res->phy_base,
- DP_PHY_PD_CTL, 0x3d);
/* Make sure the PHY register writes are done */
wmb();
MDSS_PLL_REG_W(dp_res->pll_base,
@@ -314,8 +333,13 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate)
/* Make sure the PLL register writes are done */
wmb();
- MDSS_PLL_REG_W(dp_res->phy_base,
- DP_PHY_MODE, 0x58);
+ if (orientation == ORIENTATION_CC2)
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_MODE, 0x48);
+ else
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_MODE, 0x58);
+
MDSS_PLL_REG_W(dp_res->phy_base,
DP_PHY_TX0_TX1_LANE_CTL, 0x05);
MDSS_PLL_REG_W(dp_res->phy_base,
@@ -427,6 +451,12 @@ static int dp_pll_enable(struct clk *c)
u32 status;
struct dp_pll_vco_clk *vco = mdss_dp_to_vco_clk(c);
struct mdss_pll_resources *dp_res = vco->priv;
+ u8 orientation, ln_cnt;
+ u32 spare_value, bias_en, drvr_en;
+
+ spare_value = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_SPARE0);
+ ln_cnt = spare_value & 0x0F;
+ orientation = (spare_value & 0xF0) >> 4;
MDSS_PLL_REG_W(dp_res->phy_base,
DP_PHY_CFG, 0x01);
@@ -474,18 +504,45 @@ static int dp_pll_enable(struct clk *c)
pr_debug("%s: PLL is locked\n", __func__);
- MDSS_PLL_REG_W(dp_res->phy_base,
+ if (ln_cnt == 1) {
+ bias_en = 0x3e;
+ drvr_en = 0x13;
+ } else {
+ bias_en = 0x3f;
+ drvr_en = 0x10;
+ }
+
+ if (ln_cnt != 4) {
+ if (orientation == ORIENTATION_CC1) {
+ MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
- 0x3f);
- MDSS_PLL_REG_W(dp_res->phy_base,
+ bias_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN,
- 0x10);
- MDSS_PLL_REG_W(dp_res->phy_base,
+ drvr_en);
+ } else {
+ MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
- 0x3f);
- MDSS_PLL_REG_W(dp_res->phy_base,
+ bias_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN,
+ drvr_en);
+ }
+ } else {
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
+ bias_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN,
- 0x10);
+ drvr_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN,
+ bias_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN,
+ drvr_en);
+ }
+
MDSS_PLL_REG_W(dp_res->phy_base,
QSERDES_TX0_OFFSET + TXn_TX_POL_INV,
0x0a);
@@ -615,7 +672,7 @@ int dp_vco_prepare(struct clk *c)
rc = dp_pll_enable(c);
if (rc) {
mdss_pll_resource_enable(dp_pll_res, false);
- pr_err("ndx=%d failed to enable dsi pll\n",
+ pr_err("ndx=%d failed to enable dp pll\n",
dp_pll_res->index);
goto error;
}
diff --git a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.h b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.h
index d89545b38e64..28f21ed1fe0d 100644
--- a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.h
+++ b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.h
@@ -41,6 +41,7 @@
#define DP_PHY_TX0_TX1_LANE_CTL 0x0068
#define DP_PHY_TX2_TX3_LANE_CTL 0x0084
+#define DP_PHY_SPARE0 0x00A8
#define DP_PHY_STATUS 0x00BC
/* Tx registers */
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 57e18a7dc5e1..42334941f809 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -789,17 +789,34 @@ void mdss_dp_config_ctrl(struct mdss_dp_drv_pdata *dp)
cap = &dp->dpcd;
- data = dp->lane_cnt - 1;
- data <<= 4;
+ data |= (2 << 13); /* Default-> LSCLK DIV: 1/4 LCLK */
+
+ /* Color Format */
+ switch (dp->panel_data.panel_info.out_format) {
+ case MDP_Y_CBCR_H2V2:
+ data |= (1 << 11); /* YUV420 */
+ break;
+ case MDP_Y_CBCR_H2V1:
+ data |= (2 << 11); /* YUV422 */
+ break;
+ default:
+ data |= (0 << 11); /* RGB */
+ break;
+ }
+
+ /* Scrambler reset enable */
+ if (cap->scrambler_reset)
+ data |= (1 << 10);
+
+ if (dp->edid.color_depth != 6)
+ data |= 0x100; /* Default: 8 bits */
+
+ /* Num of Lanes */
+ data |= ((dp->lane_cnt - 1) << 4);
if (cap->enhanced_frame)
data |= 0x40;
- if (dp->edid.color_depth == 8) {
- /* 0 == 6 bits, 1 == 8 bits */
- data |= 0x100; /* bit 8 */
- }
-
if (!timing->interlaced) /* progressive */
data |= 0x04;
@@ -863,6 +880,8 @@ static int dp_audio_info_setup(struct platform_device *pdev,
mdss_dp_set_safe_to_exit_level(&dp_ctrl->ctrl_io, dp_ctrl->lane_cnt);
mdss_dp_audio_enable(&dp_ctrl->ctrl_io, true);
+ dp_ctrl->wait_for_audio_comp = true;
+
return rc;
} /* dp_audio_info_setup */
@@ -885,6 +904,17 @@ static int dp_get_audio_edid_blk(struct platform_device *pdev,
return rc;
} /* dp_get_audio_edid_blk */
+static void dp_audio_codec_teardown_done(struct platform_device *pdev)
+{
+ struct mdss_dp_drv_pdata *dp = platform_get_drvdata(pdev);
+
+ if (!dp)
+ pr_err("invalid input\n");
+
+ pr_debug("audio codec teardown done\n");
+ complete_all(&dp->audio_comp);
+}
+
static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp)
{
int ret = 0;
@@ -906,6 +936,8 @@ static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp)
dp_get_audio_edid_blk;
dp->ext_audio_data.codec_ops.cable_status =
dp_get_cable_status;
+ dp->ext_audio_data.codec_ops.teardown_done =
+ dp_audio_codec_teardown_done;
if (!dp->pdev->dev.of_node) {
pr_err("%s cannot find dp dev.of_node\n", __func__);
@@ -987,6 +1019,13 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
return 0;
} /* dp_init_panel_info */
+static inline void mdss_dp_set_audio_switch_node(
+ struct mdss_dp_drv_pdata *dp, int val)
+{
+ if (dp && dp->ext_audio_data.intf_ops.notify)
+ dp->ext_audio_data.intf_ops.notify(dp->ext_pdev,
+ val);
+}
int mdss_dp_on(struct mdss_panel_data *pdata)
{
@@ -1054,6 +1093,9 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
goto exit;
}
+ mdss_dp_phy_share_lane_config(&dp_drv->phy_io,
+ orientation, dp_drv->dpcd.max_lane_count);
+
pr_debug("link_rate = 0x%x\n", dp_drv->link_rate);
dp_drv->power_data[DP_CTRL_PM].clk_config[0].rate =
@@ -1096,6 +1138,7 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
pr_debug("mainlink ready\n");
dp_drv->power_on = true;
+ mdss_dp_set_audio_switch_node(dp_drv, true);
pr_debug("End-\n");
exit:
@@ -1119,14 +1162,15 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
mutex_lock(&dp_drv->train_mutex);
reinit_completion(&dp_drv->idle_comp);
-
- mdss_dp_state_ctrl(&dp_drv->ctrl_io, 0);
+ mdss_dp_state_ctrl(&dp_drv->ctrl_io, ST_PUSH_IDLE);
if (dp_drv->link_clks_on)
mdss_dp_mainlink_ctrl(&dp_drv->ctrl_io, false);
mdss_dp_aux_ctrl(&dp_drv->ctrl_io, false);
+ mdss_dp_audio_enable(&dp_drv->ctrl_io, false);
+
mdss_dp_irq_disable(dp_drv);
mdss_dp_config_gpios(dp_drv, false);
@@ -1147,14 +1191,6 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
return 0;
}
-static inline void mdss_dp_set_audio_switch_node(
- struct mdss_dp_drv_pdata *dp, int val)
-{
- if (dp && dp->ext_audio_data.intf_ops.notify)
- dp->ext_audio_data.intf_ops.notify(dp->ext_pdev,
- val);
-}
-
static void mdss_dp_send_cable_notification(
struct mdss_dp_drv_pdata *dp, int val)
{
@@ -1169,6 +1205,38 @@ static void mdss_dp_send_cable_notification(
dp->ext_audio_data.type, val);
}
+static void mdss_dp_audio_codec_wait(struct mdss_dp_drv_pdata *dp)
+{
+ const int audio_completion_timeout_ms = HZ * 3;
+ int ret = 0;
+
+ if (!dp->wait_for_audio_comp)
+ return;
+
+ reinit_completion(&dp->audio_comp);
+ ret = wait_for_completion_timeout(&dp->audio_comp,
+ audio_completion_timeout_ms);
+ if (ret <= 0)
+ pr_warn("audio codec teardown timed out\n");
+
+ dp->wait_for_audio_comp = false;
+}
+
+static void mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp, bool enable)
+{
+ if (enable) {
+ mdss_dp_send_cable_notification(dp, enable);
+ } else {
+ mdss_dp_set_audio_switch_node(dp, enable);
+ mdss_dp_audio_codec_wait(dp);
+ mdss_dp_send_cable_notification(dp, enable);
+ }
+
+ pr_debug("notify state %s done\n",
+ enable ? "ENABLE" : "DISABLE");
+}
+
+
static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
{
struct mdss_dp_drv_pdata *dp_drv = NULL;
@@ -1236,15 +1304,19 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata)
mdss_dp_aux_init(dp_drv);
+ mdss_dp_phy_initialize(dp_drv);
+ mdss_dp_ctrl_reset(&dp_drv->ctrl_io);
mdss_dp_phy_reset(&dp_drv->ctrl_io);
mdss_dp_aux_reset(&dp_drv->ctrl_io);
- mdss_dp_phy_initialize(dp_drv);
mdss_dp_aux_ctrl(&dp_drv->ctrl_io, true);
pr_debug("Ctrl_hw_rev =0x%x, phy hw_rev =0x%x\n",
mdss_dp_get_ctrl_hw_version(&dp_drv->ctrl_io),
mdss_dp_get_phy_hw_version(&dp_drv->phy_io));
+ pr_debug("plug Orientation = %d\n",
+ usbpd_get_plug_orientation(dp_drv->pd));
+
mdss_dp_phy_aux_setup(&dp_drv->phy_io);
mdss_dp_irq_enable(dp_drv);
@@ -1264,8 +1336,7 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata)
goto edid_error;
}
- mdss_dp_send_cable_notification(dp_drv, true);
- mdss_dp_set_audio_switch_node(dp_drv, true);
+ mdss_dp_notify_clients(dp_drv, true);
dp_drv->dp_initialized = true;
return ret;
@@ -1771,8 +1842,7 @@ static void dp_send_events(struct mdss_dp_drv_pdata *dp, u32 events)
{
spin_lock(&dp->event_lock);
dp->current_event = events;
- queue_delayed_work(dp->workq,
- &dp->dwork, HZ);
+ queue_delayed_work(dp->workq, &dp->dwork, HZ / 100);
spin_unlock(&dp->event_lock);
}
@@ -1883,8 +1953,7 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
mutex_lock(&dp_drv->pd_msg_mutex);
dp_drv->cable_connected = false;
mutex_unlock(&dp_drv->pd_msg_mutex);
- mdss_dp_send_cable_notification(dp_drv, false);
- mdss_dp_set_audio_switch_node(dp_drv, false);
+ mdss_dp_notify_clients(dp_drv, false);
}
static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
@@ -2135,6 +2204,8 @@ static int mdss_dp_probe(struct platform_device *pdev)
mdss_dp_device_register(dp_drv);
dp_drv->inited = true;
+ dp_drv->wait_for_audio_comp = false;
+ init_completion(&dp_drv->audio_comp);
pr_debug("done\n");
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index 4710cf7a98e2..ddadb7b6709c 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -399,6 +399,7 @@ struct mdss_dp_drv_pdata {
struct completion train_comp;
struct completion idle_comp;
struct completion video_comp;
+ struct completion audio_comp;
struct mutex aux_mutex;
struct mutex train_mutex;
struct mutex pd_msg_mutex;
@@ -423,6 +424,7 @@ struct mdss_dp_drv_pdata {
char delay_start;
u32 bpp;
struct dp_statistic dp_stat;
+ bool wait_for_audio_comp;
/* event */
struct workqueue_struct *workq;
diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c
index d9297a7af764..136dbb13cc62 100644
--- a/drivers/video/fbdev/msm/mdss_dp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_dp_aux.c
@@ -1113,17 +1113,17 @@ static void dp_host_train_set(struct mdss_dp_drv_pdata *ep, int train)
}
char vm_pre_emphasis[4][4] = {
- {0x00, 0x06, 0x09, 0x0C}, /* pe0, 0 db */
- {0x00, 0x06, 0x09, 0xFF}, /* pe1, 3.5 db */
- {0x03, 0x06, 0xFF, 0xFF}, /* pe2, 6.0 db */
- {0x03, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */
+ {0x00, 0x09, 0x11, 0x0C}, /* pe0, 0 db */
+ {0x00, 0x0A, 0x10, 0xFF}, /* pe1, 3.5 db */
+ {0x00, 0x0C, 0xFF, 0xFF}, /* pe2, 6.0 db */
+ {0x00, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */
};
/* voltage swing, 0.2v and 1.0v are not support */
char vm_voltage_swing[4][4] = {
- {0x0a, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v */
- {0x07, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */
- {0x1A, 0x1E, 0xFF, 0xFF}, /* sw1, 0.8 v */
+ {0x07, 0x0f, 0x12, 0x1E}, /* sw0, 0.4v */
+ {0x11, 0x1D, 0x1F, 0xFF}, /* sw1, 0.6 v */
+ {0x18, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8 v */
{0x1E, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
};
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c
index bdf5d92f7053..f6f2b54c2d80 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.c
+++ b/drivers/video/fbdev/msm/mdss_dp_util.c
@@ -143,6 +143,18 @@ void mdss_dp_aux_reset(struct dss_io_data *ctrl_io)
writel_relaxed(aux_ctrl, ctrl_io->base + DP_AUX_CTRL);
}
+/* reset DP controller */
+void mdss_dp_ctrl_reset(struct dss_io_data *ctrl_io)
+{
+ u32 sw_reset = readl_relaxed(ctrl_io->base + DP_SW_RESET);
+
+ sw_reset |= BIT(0);
+ writel_relaxed(sw_reset, ctrl_io->base + DP_SW_RESET);
+ udelay(1000);
+ sw_reset &= ~BIT(0);
+ writel_relaxed(sw_reset, ctrl_io->base + DP_SW_RESET);
+}
+
/* reset DP Mainlink */
void mdss_dp_mainlink_reset(struct dss_io_data *ctrl_io)
{
@@ -441,6 +453,17 @@ u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp)
return config;
}
+void mdss_dp_phy_share_lane_config(struct dss_io_data *phy_io,
+ u8 orientation, u8 ln_cnt)
+{
+ u32 info = 0x0;
+
+ info |= (ln_cnt & 0x0F);
+ info |= ((orientation & 0x0F) << 4);
+ pr_debug("Shared Info = 0x%x\n", info);
+ writel_relaxed(info, phy_io->base + DP_PHY_SPARE0);
+}
+
void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io, char link_rate)
{
u32 acr_ctrl = 0;
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h
index 5eb9d092476f..80dedba33ec5 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.h
+++ b/drivers/video/fbdev/msm/mdss_dp_util.h
@@ -150,6 +150,8 @@
#define DP_PHY_AUX_INTERRUPT_MASK (0x00000044)
#define DP_PHY_AUX_INTERRUPT_CLEAR (0x00000048)
+#define DP_PHY_SPARE0 0x00A8
+
#define QSERDES_TX0_OFFSET 0x0400
#define QSERDES_TX1_OFFSET 0x0800
@@ -205,6 +207,7 @@ int dp_aux_write(void *ep, struct edp_cmd *cmd);
void mdss_dp_state_ctrl(struct dss_io_data *ctrl_io, u32 data);
u32 mdss_dp_get_ctrl_hw_version(struct dss_io_data *ctrl_io);
u32 mdss_dp_get_phy_hw_version(struct dss_io_data *phy_io);
+void mdss_dp_ctrl_reset(struct dss_io_data *ctrl_io);
void mdss_dp_aux_reset(struct dss_io_data *ctrl_io);
void mdss_dp_mainlink_reset(struct dss_io_data *ctrl_io);
void mdss_dp_phy_reset(struct dss_io_data *ctrl_io);
@@ -231,6 +234,8 @@ void mdss_dp_usbpd_ext_dp_status(struct usbpd_dp_status *dp_status);
u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp);
void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io,
struct lane_mapping l_map);
+void mdss_dp_phy_share_lane_config(struct dss_io_data *phy_io,
+ u8 orientation, u8 ln_cnt);
void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io,
char link_rate);
void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io);
diff --git a/drivers/video/fbdev/msm/msm_ext_display.c b/drivers/video/fbdev/msm/msm_ext_display.c
index e229f52057d4..4899231787f2 100644
--- a/drivers/video/fbdev/msm/msm_ext_display.c
+++ b/drivers/video/fbdev/msm/msm_ext_display.c
@@ -365,6 +365,7 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
ext_disp->ops->get_audio_edid_blk = NULL;
ext_disp->ops->cable_status = NULL;
ext_disp->ops->get_intf_id = NULL;
+ ext_disp->ops->teardown_done = NULL;
}
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
@@ -463,6 +464,20 @@ end:
return ret;
}
+static void msm_ext_disp_teardown_done(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_ext_disp_init_data *data = NULL;
+
+ ret = msm_ext_disp_get_intf_data_helper(pdev, &data);
+ if (ret || !data) {
+ pr_err("invalid input");
+ return;
+ }
+
+ data->codec_ops.teardown_done(data->pdev);
+}
+
static int msm_ext_disp_get_intf_id(struct platform_device *pdev)
{
int ret = 0;
@@ -545,6 +560,8 @@ static int msm_ext_disp_notify(struct platform_device *pdev,
msm_ext_disp_cable_status;
ext_disp->ops->get_intf_id =
msm_ext_disp_get_intf_id;
+ ext_disp->ops->teardown_done =
+ msm_ext_disp_teardown_done;
}
switch_set_state(&ext_disp->audio_sdev, (int)new_state);
@@ -614,6 +631,7 @@ static int msm_ext_disp_audio_ack(struct platform_device *pdev, u32 ack)
ext_disp->ops->get_audio_edid_blk = NULL;
ext_disp->ops->cable_status = NULL;
ext_disp->ops->get_intf_id = NULL;
+ ext_disp->ops->teardown_done = NULL;
}
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
diff --git a/include/linux/msm_ext_display.h b/include/linux/msm_ext_display.h
index 873a778d5370..59ba776b5f9b 100644
--- a/include/linux/msm_ext_display.h
+++ b/include/linux/msm_ext_display.h
@@ -108,6 +108,7 @@ struct msm_ext_disp_audio_codec_ops {
struct msm_ext_disp_audio_edid_blk *blk);
int (*cable_status)(struct platform_device *pdev, u32 vote);
int (*get_intf_id)(struct platform_device *pdev);
+ void (*teardown_done)(struct platform_device *pdev);
};
/*