From 9ec9267905e8e712eba27c106c96e78c6da3e56f Mon Sep 17 00:00:00 2001 From: Chandan Uddaraju <chandanu@codeaurora.org> Date: Wed, 17 Aug 2016 11:52:41 -0700 Subject: [PATCH] mdss: display-port: fix Display-port disable sequence Fix the OFF path for display-port driver when cable is disconnected. Check for link clock status before accessing any of the mainlink registers. Use common mutex for DP_ON and DP_OFF sequence. Remove the resource vote when PLL is diabled. Change-Id: I9b81f79043b4ea7355b99ba9d8347d79bed10153 Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org> --- .../clk/msm/mdss/mdss-dp-pll-cobalt-util.c | 2 + drivers/video/fbdev/msm/mdss_dp.c | 49 +++++++++---------- drivers/video/fbdev/msm/mdss_dp.h | 2 +- drivers/video/fbdev/msm/mdss_dp_aux.c | 12 +---- 4 files changed, 28 insertions(+), 37 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 74032aba22bc..123a5ae09fa8 100644 --- a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c +++ b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c @@ -583,8 +583,10 @@ int dp_vco_prepare(struct clk *c) mdss_pll_resource_enable(dp_pll_res, false); pr_err("ndx=%d failed to enable dsi pll\n", dp_pll_res->index); + goto error; } + mdss_pll_resource_enable(dp_pll_res, false); error: return rc; } diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index f7261d4e3fa4..140836f9e89e 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -895,7 +895,7 @@ int mdss_dp_on(struct mdss_panel_data *pdata) panel_data); /* wait until link training is completed */ - mutex_lock(&dp_drv->host_mutex); + mutex_lock(&dp_drv->train_mutex); pr_debug("Enter++ cont_splash=%d\n", dp_drv->cont_splash); /* Default lane mapping */ @@ -908,7 +908,7 @@ int mdss_dp_on(struct mdss_panel_data *pdata) ret = mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, true); if (ret) { pr_err("Unabled to start core clocks\n"); - return ret; + goto exit; } mdss_dp_hpd_configure(&dp_drv->ctrl_io, true); @@ -941,7 +941,8 @@ int mdss_dp_on(struct mdss_panel_data *pdata) dp_drv->link_rate, dp_drv->dpcd.max_link_rate); if (!dp_drv->link_rate) { pr_err("Unable to configure required link rate\n"); - return -EINVAL; + ret = -EINVAL; + goto exit; } pr_debug("link_rate = 0x%x\n", dp_drv->link_rate); @@ -955,9 +956,8 @@ int mdss_dp_on(struct mdss_panel_data *pdata) ret = mdss_dp_clk_ctrl(dp_drv, DP_CTRL_PM, true); if (ret) { - mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false); pr_err("Unabled to start link clocks\n"); - return ret; + goto exit; } mdss_dp_mainlink_reset(&dp_drv->ctrl_io); @@ -985,17 +985,16 @@ int mdss_dp_on(struct mdss_panel_data *pdata) pr_debug("mainlink ready\n"); dp_drv->power_on = true; - - mutex_unlock(&dp_drv->host_mutex); pr_debug("End-\n"); +exit: + mutex_unlock(&dp_drv->train_mutex); return ret; } int mdss_dp_off(struct mdss_panel_data *pdata) { struct mdss_dp_drv_pdata *dp_drv = NULL; - int ret = 0; dp_drv = container_of(pdata, struct mdss_dp_drv_pdata, panel_data); @@ -1009,34 +1008,31 @@ 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, ST_PUSH_IDLE); - - ret = wait_for_completion_timeout(&dp_drv->idle_comp, - msecs_to_jiffies(100)); - if (ret == 0) - pr_err("idle pattern timedout\n"); mdss_dp_state_ctrl(&dp_drv->ctrl_io, 0); - mdss_dp_irq_disable(dp_drv); + if (dp_drv->link_clks_on) + mdss_dp_mainlink_ctrl(&dp_drv->ctrl_io, false); - mdss_dp_mainlink_reset(&dp_drv->ctrl_io); - mdss_dp_mainlink_ctrl(&dp_drv->ctrl_io, false); + mdss_dp_aux_ctrl(&dp_drv->ctrl_io, false); + + mdss_dp_irq_disable(dp_drv); mdss_dp_config_gpios(dp_drv, false); mdss_dp_pinctrl_set_state(dp_drv, false); - mdss_dp_aux_ctrl(&dp_drv->ctrl_io, false); + /* Make sure DP is disabled before clk disable */ + wmb(); mdss_dp_clk_ctrl(dp_drv, DP_CTRL_PM, false); mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false); mdss_dp_regulator_ctrl(dp_drv, false); - - pr_debug("End--: state_ctrl=%x\n", - dp_read(dp_drv->base + DP_STATE_CTRL)); + dp_drv->dp_initialized = false; dp_drv->power_on = false; mutex_unlock(&dp_drv->train_mutex); + pr_debug("DP off done\n"); + return 0; } @@ -1124,6 +1120,10 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata) dp_drv = container_of(pdata, struct mdss_dp_drv_pdata, panel_data); + if (dp_drv->dp_initialized) { + pr_err("%s: host init done already\n", __func__); + return 0; + } ret = mdss_dp_regulator_ctrl(dp_drv, true); if (ret) { pr_err("failed to enable regulators\n"); @@ -1170,7 +1170,7 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata) } mdss_dp_send_cable_notification(dp_drv, true); - + dp_drv->dp_initialized = true; return ret; edid_error: @@ -1781,8 +1781,8 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, if (cmd_type == SVDM_CMD_TYPE_INITIATOR) { pr_debug("Attention. cmd_type=%d\n", cmd_type); - if (!dp_drv->alt_mode.current_state - == ENTER_MODE_DONE) { + if (!(dp_drv->alt_mode.current_state + == ENTER_MODE_DONE)) { pr_debug("sending discover_mode\n"); dp_send_events(dp_drv, EV_USBPD_DISCOVER_MODES); break; @@ -1909,7 +1909,6 @@ static int mdss_dp_probe(struct platform_device *pdev) dp_drv->mask1 = EDP_INTR_MASK1; dp_drv->mask2 = EDP_INTR_MASK2; mutex_init(&dp_drv->emutex); - mutex_init(&dp_drv->host_mutex); mutex_init(&dp_drv->pd_msg_mutex); mutex_init(&dp_drv->hdcp_mutex); spin_lock_init(&dp_drv->lock); diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index d36c1e4ffce5..e29440746478 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -337,6 +337,7 @@ struct mdss_dp_drv_pdata { struct usbpd *pd; struct usbpd_svid_handler svid_handler; struct dp_alt_mode alt_mode; + bool dp_initialized; struct mutex emutex; int clk_cnt; @@ -398,7 +399,6 @@ struct mdss_dp_drv_pdata { struct completion video_comp; struct mutex aux_mutex; struct mutex train_mutex; - struct mutex host_mutex; struct mutex pd_msg_mutex; struct mutex hdcp_mutex; bool cable_connected; diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index aea342ac90db..fc24bb53a61c 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -1312,7 +1312,7 @@ static void dp_clear_training_pattern(struct mdss_dp_drv_pdata *ep) usleep_range(usleep_time, usleep_time); } -static int dp_aux_link_train(struct mdss_dp_drv_pdata *dp) +int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp) { int ret = 0; int usleep_time; @@ -1412,16 +1412,6 @@ void mdss_dp_fill_link_cfg(struct mdss_dp_drv_pdata *ep) } -int mdss_dp_link_train(struct mdss_dp_drv_pdata *ep) -{ - int ret; - - mutex_lock(&ep->train_mutex); - ret = dp_aux_link_train(ep); - mutex_unlock(&ep->train_mutex); - return ret; -} - void mdss_dp_aux_init(struct mdss_dp_drv_pdata *ep) { mutex_init(&ep->aux_mutex);