From cc54970685fe40a997a5d25bc4830ec56a9b63ed Mon Sep 17 00:00:00 2001 From: Ajay Singh Parmar Date: Tue, 31 Jan 2017 16:53:18 -0800 Subject: [PATCH 1/8] msm: ext_disp: do not check flags for connection request Do not check flags for connection requests as it may result in not processing any subsequent requests that have new flags added incrementally from the previous connection. CRs-Fixed: 2007353 Change-Id: Ie867d13d25267962315444797cf21bf57850f088 Signed-off-by: Ajay Singh Parmar --- drivers/platform/msm/msm_ext_display.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/platform/msm/msm_ext_display.c b/drivers/platform/msm/msm_ext_display.c index bb1259e3cfa1..a35ed1afc720 100644 --- a/drivers/platform/msm/msm_ext_display.c +++ b/drivers/platform/msm/msm_ext_display.c @@ -285,11 +285,6 @@ static bool msm_ext_disp_validate_connect(struct msm_ext_disp *ext_disp, /* if already connected, block a new connection */ if (ext_disp->current_disp != type) return false; - - /* if same display connected, block same connection type */ - if (ext_disp->flags & flags) - return false; - end: ext_disp->flags |= flags; ext_disp->current_disp = type; From 2367aa4dc1cbdb850a7b7f2f2e2bd75a33fe73d7 Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Mon, 30 Jan 2017 15:52:56 -0800 Subject: [PATCH 2/8] msm: mdss: dp: set failsafe link parameters on EDID failure Set the link parameters that correspond to the failsafe resolution if there is a failure in reading or parsing the EDID data. This will allow the display to be configured with the failsafe resolution and prevent the driver from going into a bad state. CRs-Fixed: 2002794 Change-Id: I5882e66eee6073da6484903956abdcb3db05a5ea Signed-off-by: Tatenda Chipeperekwa --- drivers/video/fbdev/msm/mdss_dp.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index bd8e710870f7..e0e24e238d94 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -1673,6 +1673,19 @@ static void mdss_dp_set_default_resolution(struct mdss_dp_drv_pdata *dp) DEFAULT_VIDEO_RESOLUTION, true); } +static void mdss_dp_set_default_link_parameters(struct mdss_dp_drv_pdata *dp) +{ + const int default_max_link_rate = 0x6; + const int default_max_lane_count = 1; + + dp->dpcd.max_lane_count = default_max_lane_count; + dp->dpcd.max_link_rate = default_max_link_rate; + + pr_debug("max_link_rate = 0x%x, max_lane_count= 0x%x\n", + dp->dpcd.max_link_rate, + dp->dpcd.max_lane_count); +} + static int mdss_dp_edid_init(struct mdss_panel_data *pdata) { struct mdss_dp_drv_pdata *dp_drv = NULL; @@ -1878,12 +1891,16 @@ static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp) pr_debug("edid read error, setting default resolution\n"); mdss_dp_set_default_resolution(dp); + mdss_dp_set_default_link_parameters(dp); goto notify; } ret = hdmi_edid_parser(dp->panel_data.panel_info.edid_data); if (ret) { - pr_err("edid parse failed\n"); + pr_err("edid parse failed, setting default resolution\n"); + + mdss_dp_set_default_resolution(dp); + mdss_dp_set_default_link_parameters(dp); goto notify; } From 950f7db38480c00bcf263f476b1c9b083e905bbc Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Mon, 13 Feb 2017 18:12:48 -0800 Subject: [PATCH 3/8] msm: mdss: dp: separate audio and video notifications Separate the audio and video notifications while processing the display hotplug events to ensure that the audio subsystem is notified only when the display is in the correct state. In particular, the audio subsystem should only be notified once the mainlink is ready and the DP controller is in SEND_VIDEO state. This will ensure that the DP audio engine is able to acknowledge the audio unmute request, which will result in the AFE port being configured correctly. CRs-Fixed: 2007534 Change-Id: I702c1de6d4eb10e001d97e1d7e7c545ff481a401 Signed-off-by: Tatenda Chipeperekwa --- drivers/video/fbdev/msm/mdss_dp.c | 57 ++++++++++++++++++++------ drivers/video/fbdev/msm/mdss_dp_util.c | 13 +++--- drivers/video/fbdev/msm/mdss_dp_util.h | 2 +- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index e0e24e238d94..5a9e060c533b 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -64,6 +64,8 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp, enum notification_status status); static int mdss_dp_process_phy_test_pattern_request( struct mdss_dp_drv_pdata *dp); +static int mdss_dp_send_audio_notification( + struct mdss_dp_drv_pdata *dp, int val); static inline void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp) { @@ -961,6 +963,14 @@ static int mdss_dp_wait4video_ready(struct mdss_dp_drv_pdata *dp_drv) ret = -EINVAL; } else { ret = 0; + /* + * The audio subsystem should only be notified once the DP + * controller is in SEND_VIDEO state. This will ensure that + * the DP audio engine is able to acknowledge the audio unmute + * request, which will result in the AFE port being configured + * correctly. + */ + mdss_dp_send_audio_notification(dp_drv, true); } pr_debug("End--\n"); @@ -1347,7 +1357,7 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp, static int mdss_dp_setup_main_link(struct mdss_dp_drv_pdata *dp, bool train) { int ret = 0; - int ready = 0; + bool mainlink_ready = false; pr_debug("enter\n"); mdss_dp_mainlink_ctrl(&dp->ctrl_io, true); @@ -1380,8 +1390,8 @@ send_video: mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO); mdss_dp_wait4video_ready(dp); - ready = mdss_dp_mainlink_ready(dp, BIT(0)); - pr_debug("main link %s\n", ready ? "READY" : "NOT READY"); + mainlink_ready = mdss_dp_mainlink_ready(dp); + pr_debug("mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); end: return ret; @@ -1639,26 +1649,46 @@ int mdss_dp_off(struct mdss_panel_data *pdata) return mdss_dp_off_hpd(dp); } -static int mdss_dp_send_cable_notification( +static int mdss_dp_send_audio_notification( struct mdss_dp_drv_pdata *dp, int val) { int ret = 0; u32 flags = 0; if (!dp) { - DEV_ERR("%s: invalid input\n", __func__); + pr_err("invalid input\n"); ret = -EINVAL; goto end; } - flags |= MSM_EXT_DISP_HPD_VIDEO; - if (!mdss_dp_is_dvi_mode(dp) || dp->audio_test_req) { dp->audio_test_req = false; flags |= MSM_EXT_DISP_HPD_AUDIO; + + if (dp->ext_audio_data.intf_ops.hpd) + ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev, + dp->ext_audio_data.type, val, flags); } +end: + return ret; +} + +static int mdss_dp_send_video_notification( + struct mdss_dp_drv_pdata *dp, int val) +{ + int ret = 0; + u32 flags = 0; + + if (!dp) { + pr_err("invalid input\n"); + ret = -EINVAL; + goto end; + } + + flags |= MSM_EXT_DISP_HPD_VIDEO; + if (dp->ext_audio_data.intf_ops.hpd) ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev, dp->ext_audio_data.type, val, flags); @@ -1817,7 +1847,7 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp, goto invalid_request; /* Follow the same programming as for NOTIFY_CONNECT */ mdss_dp_host_init(&dp->panel_data); - mdss_dp_send_cable_notification(dp, true); + mdss_dp_send_video_notification(dp, true); break; case NOTIFY_CONNECT: if ((dp->hpd_notification_status == NOTIFY_CONNECT_IRQ_HPD) || @@ -1825,16 +1855,18 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp, NOTIFY_DISCONNECT_IRQ_HPD)) goto invalid_request; mdss_dp_host_init(&dp->panel_data); - mdss_dp_send_cable_notification(dp, true); + mdss_dp_send_video_notification(dp, true); break; case NOTIFY_DISCONNECT: - mdss_dp_send_cable_notification(dp, false); + mdss_dp_send_audio_notification(dp, false); + mdss_dp_send_video_notification(dp, false); break; case NOTIFY_DISCONNECT_IRQ_HPD: if (dp->hpd_notification_status == NOTIFY_DISCONNECT) goto invalid_request; - mdss_dp_send_cable_notification(dp, false); + mdss_dp_send_audio_notification(dp, false); + mdss_dp_send_video_notification(dp, false); if (!IS_ERR_VALUE(ret) && ret) { reinit_completion(&dp->irq_comp); ret = wait_for_completion_timeout(&dp->irq_comp, @@ -2722,11 +2754,10 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata, switch (event) { case MDSS_EVENT_UNBLANK: + mdss_dp_ack_state(dp, true); rc = mdss_dp_on(pdata); break; case MDSS_EVENT_PANEL_ON: - mdss_dp_ack_state(dp, true); - mdss_dp_update_hdcp_info(dp); if (dp_is_hdcp_enabled(dp)) { diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c index 3b9242448198..ea492f54054c 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.c +++ b/drivers/video/fbdev/msm/mdss_dp_util.c @@ -177,23 +177,22 @@ void mdss_dp_mainlink_ctrl(struct dss_io_data *ctrl_io, bool enable) writel_relaxed(mainlink_ctrl, ctrl_io->base + DP_MAINLINK_CTRL); } -int mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp, u32 which) +bool mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp) { u32 data; int cnt = 10; + int const mainlink_ready_bit = BIT(0); while (--cnt) { /* DP_MAINLINK_READY */ data = readl_relaxed(dp->base + DP_MAINLINK_READY); - if (data & which) { - pr_debug("which=%x ready\n", which); - return 1; - } + if (data & mainlink_ready_bit) + return true; udelay(1000); } - pr_err("which=%x NOT ready\n", which); + pr_err("mainlink not ready\n"); - return 0; + return false; } /* DP Configuration controller*/ diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h index b3b15a3579fa..8f19e7cdf3cf 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.h +++ b/drivers/video/fbdev/msm/mdss_dp_util.h @@ -291,7 +291,7 @@ void mdss_dp_hpd_configure(struct dss_io_data *ctrl_io, bool enable); void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable); void mdss_dp_mainlink_ctrl(struct dss_io_data *ctrl_io, bool enable); void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, char *l_map); -int mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp, u32 which); +bool mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp); void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io, struct mdss_panel_info *pinfo); void mdss_dp_configuration_ctrl(struct dss_io_data *ctrl_io, u32 data); From 75b4841b5e70cae8492870068c9b96e33b151376 Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Thu, 16 Feb 2017 16:00:37 -0800 Subject: [PATCH 4/8] msm: hdmi: edid: update incorrect interlaced field Update the interlaced field for the 1920x1080i60 resolution to show that the mode is in fact interlaced. This will provide external display clients with the correct information regarding this resolution. CRs-Fixed: 2006873 Change-Id: I30f5da1e49e35a81f65508f2766118a58d12ceb4 Signed-off-by: Tatenda Chipeperekwa --- include/uapi/video/msm_hdmi_modes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/video/msm_hdmi_modes.h b/include/uapi/video/msm_hdmi_modes.h index 43ca6bab4c62..5b4b2b492be4 100644 --- a/include/uapi/video/msm_hdmi_modes.h +++ b/include/uapi/video/msm_hdmi_modes.h @@ -271,7 +271,7 @@ struct msm_hdmi_mode_timing_info { 720, 5, 5, 20, false, 74250, 60000, false, true, HDMI_RES_AR_16_9, 0} #define HDMI_VFRMT_1920x1080i60_16_9_TIMING \ {HDMI_VFRMT_1920x1080i60_16_9, 1920, 88, 44, 148, false, \ - 540, 2, 5, 5, false, 74250, 60000, false, true, HDMI_RES_AR_16_9, 0} + 540, 2, 5, 5, false, 74250, 60000, true, true, HDMI_RES_AR_16_9, 0} #define HDMI_VFRMT_1440x480i60_4_3_TIMING \ {HDMI_VFRMT_1440x480i60_4_3, 1440, 38, 124, 114, true, \ 240, 4, 3, 15, true, 27000, 60000, true, true, HDMI_RES_AR_4_3, 0} From 49237b208defaff82af3a7f1cdfaf082570562d4 Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Thu, 16 Feb 2017 18:01:19 -0800 Subject: [PATCH 5/8] msm: mdss: dp: disable audio engine on teardown_done Disable the DP audio engine on receiving the teardown_done callback from the audio codec. This ensures that the DP engine is in the disabled (MUTE) state in preparation for the next audio session. CRs-Fixed: 2006127 Change-Id: I7c984531d308501690ede36ea959391ebef7599f Signed-off-by: Tatenda Chipeperekwa --- drivers/video/fbdev/msm/mdss_dp.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 5a9e060c533b..0c6ad8b0d92f 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -1048,6 +1048,22 @@ static int dp_get_audio_edid_blk(struct platform_device *pdev, return rc; } /* dp_get_audio_edid_blk */ +static void dp_audio_teardown_done(struct platform_device *pdev) +{ + struct mdss_dp_drv_pdata *dp = platform_get_drvdata(pdev); + + if (!dp) { + pr_err("invalid input\n"); + return; + } + + mdss_dp_audio_enable(&dp->ctrl_io, false); + /* Make sure the DP audio engine is disabled */ + wmb(); + + pr_debug("audio engine disabled\n"); +} /* dp_audio_teardown_done */ + static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp) { int ret = 0; @@ -1069,6 +1085,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_teardown_done; if (!dp->pdev->dev.of_node) { pr_err("%s cannot find dp dev.of_node\n", __func__); From 5dd2911526b7af0c162cc7958b2039163c70ac73 Mon Sep 17 00:00:00 2001 From: Ajay Singh Parmar Date: Wed, 8 Feb 2017 14:04:51 -0800 Subject: [PATCH 6/8] msm: mdss: dp: fix link training routine for VGA monitors Fix the link training routine by removing the updates to the state control register and the corresponding memory barrier to complete the register write. This changes fixes the link training failures seen with VGA monitors over the Type-C/VGA dongle interface. CRs-Fixed: 2008753 Change-Id: I501833e02d24d6aa12351eb0bd067a08ad597ed0 Signed-off-by: Ajay Singh Parmar --- drivers/video/fbdev/msm/mdss_dp_aux.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index ca07e80d6613..479c367fdc92 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -2247,12 +2247,8 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep) else pattern = 0x02; - dp_write(ep->base + DP_STATE_CTRL, 0x0); - /* Make sure to clear the current pattern before starting a new one */ - wmb(); - - dp_host_train_set(ep, pattern); mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(ep); + dp_host_train_set(ep, pattern); dp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */ do { From 4e8e859bf00509a15f88b315544a0eacf2143e85 Mon Sep 17 00:00:00 2001 From: Chandan Uddaraju Date: Tue, 17 Jan 2017 17:06:28 -0800 Subject: [PATCH 7/8] mdss: display-port: add support for suspend and resume events Add support for suspend and resume events that are triggered by the run time system. In particular, transition the clock (link and core) and regulators state depending on whether the suspend or resume is being processed. CRs-Fixed: 1103664 Change-Id: I4e3de9b32963c71dfded0f695dc7734b8121e19a Signed-off-by: Chandan Uddaraju --- drivers/video/fbdev/msm/mdss_dp.c | 164 ++++++++++++++++++++++++++---- drivers/video/fbdev/msm/mdss_dp.h | 1 + 2 files changed, 146 insertions(+), 19 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 0c6ad8b0d92f..f5ca8dce2ad3 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -54,6 +54,8 @@ struct mdss_dp_attention_node { #define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3 +static int mdss_dp_host_init(struct mdss_panel_data *pdata); +static int mdss_dp_host_deinit(struct mdss_dp_drv_pdata *dp); static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv); static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata); static inline void mdss_dp_link_maintenance(struct mdss_dp_drv_pdata *dp, @@ -476,6 +478,12 @@ static int mdss_dp_clk_ctrl(struct mdss_dp_drv_pdata *dp_drv, else dp_drv->link_clks_on = enable; + pr_debug("%s clocks for %s\n", + enable ? "enable" : "disable", + __mdss_dp_pm_name(pm_type)); + pr_debug("link_clks:%s core_clks:%s\n", + dp_drv->link_clks_on ? "on" : "off", + dp_drv->core_clks_on ? "on" : "off"); error: return ret; } @@ -1312,6 +1320,11 @@ static int mdss_dp_enable_mainlink_clocks(struct mdss_dp_drv_pdata *dp) if (dp->pixel_clk_rcg && dp->pixel_parent) clk_set_parent(dp->pixel_clk_rcg, dp->pixel_parent); + if (dp->link_clks_on) { + pr_debug("link clocks already on\n"); + return ret; + } + mdss_dp_set_clock_rate(dp, "ctrl_link_clk", (dp->link_rate * DP_LINK_RATE_MULTIPLIER) / DP_KHZ_TO_HZ); @@ -1336,6 +1349,11 @@ static int mdss_dp_enable_mainlink_clocks(struct mdss_dp_drv_pdata *dp) */ static void mdss_dp_disable_mainlink_clocks(struct mdss_dp_drv_pdata *dp_drv) { + if (!dp_drv->link_clks_on) { + pr_debug("link clocks already off\n"); + return; + } + mdss_dp_clk_ctrl(dp_drv, DP_CTRL_PM, false); } @@ -1571,6 +1589,16 @@ int mdss_dp_on(struct mdss_panel_data *pdata) return 0; } + /* + * During device suspend, host_deinit() is called + * to release DP resources. PM_RESUME can be + * called for any module wake-up. To avoid multiple host + * init/deinit during unrelated resume/suspend events, + * add host initialization call before DP power-on. + */ + if (!dp_drv->dp_initialized) + mdss_dp_host_init(pdata); + return mdss_dp_on_hpd(dp_drv); } @@ -1618,25 +1646,7 @@ static int mdss_dp_off_hpd(struct mdss_dp_drv_pdata *dp_drv) mdss_dp_audio_enable(&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); - - /* - * The global reset will need DP link ralated clocks to be - * running. Add the global reset just before disabling the - * link clocks and core clocks. - */ - mdss_dp_ctrl_reset(&dp_drv->ctrl_io); - - /* Make sure DP is disabled before clk disable */ - wmb(); - mdss_dp_disable_mainlink_clocks(dp_drv); - mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false); - - mdss_dp_regulator_ctrl(dp_drv, false); - dp_drv->dp_initialized = false; + mdss_dp_host_deinit(dp_drv); dp_drv->power_on = false; dp_drv->sink_info_read = false; @@ -1836,6 +1846,49 @@ vreg_error: return ret; } +/** + * mdss_dp_host_deinit() - Uninitialize DP controller + * @dp: Display Port Driver data + * + * Perform required steps to uninitialize DP controller + * and its resources. + */ +static int mdss_dp_host_deinit(struct mdss_dp_drv_pdata *dp) +{ + if (!dp) { + pr_err("Invalid input data\n"); + return -EINVAL; + } + + if (!dp->dp_initialized) { + pr_debug("%s: host deinit done already\n", __func__); + return 0; + } + + mdss_dp_irq_disable(dp); + + mdss_dp_config_gpios(dp, false); + mdss_dp_pinctrl_set_state(dp, false); + + /* + * The global reset will need DP link ralated clocks to be + * running. Add the global reset just before disabling the + * link clocks and core clocks. + */ + mdss_dp_ctrl_reset(&dp->ctrl_io); + + /* Make sure DP is disabled before clk disable */ + wmb(); + mdss_dp_disable_mainlink_clocks(dp); + mdss_dp_clk_ctrl(dp, DP_CORE_PM, false); + + mdss_dp_regulator_ctrl(dp, false); + dp->dp_initialized = false; + pr_debug("Host deinitialized successfully\n"); + + return 0; +} + /** * mdss_dp_notify_clients() - notifies DP clients of cable connection * @dp: Display Port Driver data @@ -2753,6 +2806,22 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp) } } +/** + * mdss_dp_reset_panel_info() - reset the panel_info data + * @dp: Display Port Driver data + * + * This function will reset the panel resolution to + * HDMI_VFRMT_UNKNOWN if the sink device is not connected. This will help + * to reconfigure the panel resolution during cable connect event. + */ +static void mdss_dp_reset_panel_info(struct mdss_dp_drv_pdata *dp) +{ + if (dp->suspend_vic != HDMI_VFRMT_UNKNOWN) { + dp->suspend_vic = HDMI_VFRMT_UNKNOWN; + dp_init_panel_info(dp, dp->suspend_vic); + } +} + static int mdss_dp_event_handler(struct mdss_panel_data *pdata, int event, void *arg) { @@ -2820,6 +2889,31 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata, case MDSS_EVENT_CHECK_PARAMS: rc = mdss_dp_check_params(dp, arg); break; + case MDSS_EVENT_SUSPEND: + /* + * Make sure DP host_deinit is called + * when DP host is initialized but not + * powered ON. + * For example, this scenerio happens + * when you connect DP sink while the + * device is in suspend state. + */ + if ((!dp->power_on) && (dp->dp_initialized)) + rc = mdss_dp_host_deinit(dp); + + /* + * For DP suspend/resume use case, CHECK_PARAMS is + * not called if the cable status is not changed. + * Store the sink resolution in suspend and configure + * the resolution during DP resume path. + */ + if (dp->power_on) + dp->suspend_vic = dp->vic; + break; + case MDSS_EVENT_RESUME: + if (dp->suspend_vic != HDMI_VFRMT_UNKNOWN) + dp_init_panel_info(dp, dp->suspend_vic); + break; default: pr_debug("unhandled event=%d\n", event); break; @@ -3174,6 +3268,27 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr) } else { mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT); } + + /* + * If cable is disconnected during device suspend, + * reset the panel resolution to HDMI_VFRMT_UNKNOWN + * so that new resolution is configured during + * cable connect event + */ + if ((!dp_drv->power_on) && (!dp_drv->dp_initialized)) + mdss_dp_reset_panel_info(dp_drv); + + /* + * If a cable/dongle is connected to the TX device but + * no sink device is connected, we call host + * initialization where orientation settings are + * configured. When the cable/dongle is disconnect, + * call host de-initialization to make sure + * we re-configure the orientation settings during + * the next connect event. + */ + if ((!dp_drv->power_on) && (dp_drv->dp_initialized)) + mdss_dp_host_deinit(dp_drv); } static int mdss_dp_validate_callback(u8 cmd, @@ -3670,6 +3785,16 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv) mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT); pr_debug("Attention: Notified clients\n"); + /* + * When a DP adaptor is connected and if sink is + * disconnected during device suspend, + * reset the panel resolution to HDMI_VFRMT_UNKNOWN + * so that new resolution is configured during + * connect event. + */ + if ((!dp_drv->power_on) && (!dp_drv->dp_initialized)) + mdss_dp_reset_panel_info(dp_drv); + /** * Manually turn off the DP controller if we are in PHY * testing mode. @@ -3892,6 +4017,7 @@ static int mdss_dp_probe(struct platform_device *pdev) dp_drv->hpd_irq_on = false; mdss_dp_reset_test_data(dp_drv); init_completion(&dp_drv->irq_comp); + dp_drv->suspend_vic = HDMI_VFRMT_UNKNOWN; pr_debug("done\n"); diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index d6f5d160aef2..34b652d843aa 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -450,6 +450,7 @@ struct mdss_dp_drv_pdata { bool link_clks_on; bool power_on; bool sink_info_read; + u32 suspend_vic; bool hpd; bool psm_enabled; bool audio_test_req; From 0c193ad038356941c68968de10556bec4a121fb6 Mon Sep 17 00:00:00 2001 From: Chandan Uddaraju Date: Thu, 9 Feb 2017 12:58:06 -0800 Subject: [PATCH 8/8] mdss: display-port: fix DP issue when framework reboots When framework reboot happens, HPD node is toggled by the display framework. Make sure to send cable disconnect event to framework when HPD is set to 'low' state. CRs-Fixed: 1116934 Change-Id: If59ec7c81264ff76b661cdfd8e6b70356a6e1544 Signed-off-by: Chandan Uddaraju --- drivers/video/fbdev/msm/mdss_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index f5ca8dce2ad3..ff5398030d17 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -2427,7 +2427,7 @@ static ssize_t mdss_dp_wta_hpd(struct device *dev, } else { dp_send_events(dp, EV_USBPD_DISCOVER_MODES); } - } else if (!dp->hpd && dp->power_on) { + } else if (!dp->hpd) { mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT); } end: