diff options
Diffstat (limited to 'target/linux/layerscape/patches-5.4/805-display-0023-drm-mhdp-reset-video-mode-after-hdmi-dp-cable-plugin.patch')
-rw-r--r-- | target/linux/layerscape/patches-5.4/805-display-0023-drm-mhdp-reset-video-mode-after-hdmi-dp-cable-plugin.patch | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/805-display-0023-drm-mhdp-reset-video-mode-after-hdmi-dp-cable-plugin.patch b/target/linux/layerscape/patches-5.4/805-display-0023-drm-mhdp-reset-video-mode-after-hdmi-dp-cable-plugin.patch new file mode 100644 index 0000000000..9e90f7d73c --- /dev/null +++ b/target/linux/layerscape/patches-5.4/805-display-0023-drm-mhdp-reset-video-mode-after-hdmi-dp-cable-plugin.patch @@ -0,0 +1,236 @@ +From 9ff3c9d6063c6464e243b85bbbbd03e2096a57c0 Mon Sep 17 00:00:00 2001 +From: Sandor Yu <Sandor.yu@nxp.com> +Date: Mon, 28 Oct 2019 17:07:06 +0800 +Subject: [PATCH] drm: mhdp: reset video mode after hdmi/dp cable plugin + +DP need setup link training, and HDMI need reset hdmi sink SCDC +status after cable reconnected. +Add video mode_set function when cable plugin. +Add 20ms/50ms delay for hdmi/dp to waite FW stable. + +Signed-off-by: Sandor Yu <Sandor.yu@nxp.com> +--- + drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 20 ++++---- + drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 63 ++++++++++++------------- + 2 files changed, 43 insertions(+), 40 deletions(-) + +--- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c ++++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c +@@ -108,19 +108,19 @@ static void dp_pixel_clk_reset(struct cd + cdns_mhdp_reg_write(mhdp, SOURCE_HDTX_CAR, val); + } + +-static void cdns_dp_mode_set(struct cdns_mhdp_device *mhdp, +- const struct drm_display_mode *mode) ++static void cdns_dp_mode_set(struct cdns_mhdp_device *mhdp) + { + u32 lane_mapping = mhdp->lane_mapping; + struct drm_dp_link *link = &mhdp->dp.link; + char linkid[6]; + int ret; + +- memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode)); ++ cdns_mhdp_plat_call(mhdp, pclk_rate); + +- dp_pixel_clk_reset(mhdp); ++ /* delay for DP FW stable after pixel clock relock */ ++ msleep(50); + +- cdns_mhdp_plat_call(mhdp, pclk_rate); ++ dp_pixel_clk_reset(mhdp); + + ret = drm_dp_downstream_id(&mhdp->dp.aux, linkid); + if (ret < 0) { +@@ -330,11 +330,10 @@ static void cdns_dp_bridge_mode_set(stru + video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); + + DRM_INFO("Mode: %dx%dp%d\n", mode->hdisplay, mode->vdisplay, mode->clock); ++ memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode)); + + mutex_lock(&mhdp->lock); +- +- cdns_dp_mode_set(mhdp, mode); +- ++ cdns_dp_mode_set(mhdp); + mutex_unlock(&mhdp->lock); + } + +@@ -367,6 +366,11 @@ static void hotplug_work_func(struct wor + drm_helper_hpd_irq_event(connector->dev); + + if (connector->status == connector_status_connected) { ++ /* reset video mode after cable plugin */ ++ mutex_lock(&mhdp->lock); ++ cdns_dp_mode_set(mhdp); ++ mutex_unlock(&mhdp->lock); ++ + DRM_INFO("HDMI/DP Cable Plug In\n"); + enable_irq(mhdp->irq[IRQ_OUT]); + } else if (connector->status == connector_status_disconnected) { +--- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c ++++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c +@@ -11,11 +11,11 @@ + */ + #include <drm/bridge/cdns-mhdp-common.h> + #include <drm/drm_atomic_helper.h> +-#include <drm/drm_crtc_helper.h> + #include <drm/drm_edid.h> + #include <drm/drm_encoder_slave.h> + #include <drm/drm_of.h> + #include <drm/drm_probe_helper.h> ++#include <drm/drm_scdc_helper.h> + #include <drm/drmP.h> + #include <linux/delay.h> + #include <linux/err.h> +@@ -26,25 +26,30 @@ + #include <linux/mutex.h> + #include <linux/of_device.h> + +-static int hdmi_sink_config(struct cdns_mhdp_device *mhdp) ++static void hdmi_sink_config(struct cdns_mhdp_device *mhdp) + { + struct drm_scdc *scdc = &mhdp->connector.base.display_info.hdmi.scdc; + u8 buff; +- int ret; ++ ++ /* check sink support SCDC or not */ ++ if (scdc->supported != true) { ++ DRM_INFO("Sink Not Support SCDC\n"); ++ return; ++ } + + if (mhdp->hdmi.char_rate > 340000) { + /* + * TMDS Character Rate above 340MHz should working in HDMI2.0 + * Enable scrambling and TMDS_Bit_Clock_Ratio + */ +- buff = 3; ++ buff = SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE; + mhdp->hdmi.hdmi_type = MODE_HDMI_2_0; + } else if (scdc->scrambling.low_rates) { + /* + * Enable scrambling and HDMI2.0 when scrambling capability of sink + * be indicated in the HF-VSDB LTE_340Mcsc_scramble bit + */ +- buff = 1; ++ buff = SCDC_SCRAMBLING_ENABLE; + mhdp->hdmi.hdmi_type = MODE_HDMI_2_0; + } else { + /* Default work in HDMI1.4 */ +@@ -53,8 +58,7 @@ static int hdmi_sink_config(struct cdns_ + } + + /* TMDS config */ +- ret = cdns_hdmi_scdc_write(mhdp, 0x20, buff); +- return ret; ++ cdns_hdmi_scdc_write(mhdp, 0x20, buff); + } + + static void hdmi_lanes_config(struct cdns_mhdp_device *mhdp) +@@ -142,7 +146,7 @@ static int hdmi_avi_info_set(struct cdns + return 0; + } + +-static int hdmi_vendor_info_set(struct cdns_mhdp_device *mhdp, ++static void hdmi_vendor_info_set(struct cdns_mhdp_device *mhdp, + struct drm_display_mode *mode) + { + struct hdmi_vendor_infoframe frame; +@@ -152,19 +156,18 @@ static int hdmi_vendor_info_set(struct c + /* Initialise vendor frame from DRM mode */ + ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame, &mhdp->connector.base, mode); + if (ret < 0) { +- DRM_WARN("Unable to init vendor infoframe: %d\n", ret); +- return -1; ++ DRM_INFO("No vendor infoframe\n"); ++ return; + } + + ret = hdmi_vendor_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1); + if (ret < 0) { + DRM_WARN("Unable to pack vendor infoframe: %d\n", ret); +- return -1; ++ return; + } + + buf[0] = 0; + cdns_mhdp_infoframe_set(mhdp, 3, sizeof(buf), buf, HDMI_INFOFRAME_TYPE_VENDOR); +- return 0; + } + + void cdns_hdmi_mode_set(struct cdns_mhdp_device *mhdp) +@@ -172,9 +175,16 @@ void cdns_hdmi_mode_set(struct cdns_mhdp + struct drm_display_mode *mode = &mhdp->mode; + int ret; + +- ret = hdmi_sink_config(mhdp); +- if (ret < 0) +- DRM_DEBUG("%s failed\n", __func__); ++ hdmi_lanes_config(mhdp); ++ ++ cdns_mhdp_plat_call(mhdp, pclk_rate); ++ ++ /* delay for HDMI FW stable after pixel clock relock */ ++ msleep(20); ++ ++ cdns_mhdp_plat_call(mhdp, phy_set); ++ ++ hdmi_sink_config(mhdp); + + ret = cdns_hdmi_ctrl_init(mhdp, mhdp->hdmi.hdmi_type, mhdp->hdmi.char_rate); + if (ret < 0) { +@@ -195,18 +205,13 @@ void cdns_hdmi_mode_set(struct cdns_mhdp + } + + /* vendor info frame is enable only when HDMI1.4 4K mode */ +- ret = hdmi_vendor_info_set(mhdp, mode); +- if (ret < 0) +- DRM_WARN("Unable to configure Vendor infoframe\n"); ++ hdmi_vendor_info_set(mhdp, mode); + + ret = cdns_hdmi_mode_config(mhdp, mode, &mhdp->video_info); + if (ret < 0) { + DRM_ERROR("CDN_API_HDMITX_SetVic_blocking ret = %d\n", ret); + return; + } +- +- /* wait HDMI PHY pixel clock stable */ +- msleep(50); + } + + static enum drm_connector_status +@@ -335,20 +340,11 @@ static void cdns_hdmi_bridge_mode_set(st + video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); + video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); + +- mutex_lock(&mhdp->lock); +- + DRM_INFO("Mode: %dx%dp%d\n", mode->hdisplay, mode->vdisplay, mode->clock); +- + memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode)); + +- hdmi_lanes_config(mhdp); +- +- cdns_mhdp_plat_call(mhdp, pclk_rate); +- +- cdns_mhdp_plat_call(mhdp, phy_set); +- ++ mutex_lock(&mhdp->lock); + cdns_hdmi_mode_set(mhdp); +- + mutex_unlock(&mhdp->lock); + } + +@@ -367,8 +363,11 @@ static void hotplug_work_func(struct wor + drm_helper_hpd_irq_event(connector->dev); + + if (connector->status == connector_status_connected) { +- /* Cable Connected */ + DRM_INFO("HDMI Cable Plug In\n"); ++ /* reset video mode after cable plugin */ ++ mutex_lock(&mhdp->lock); ++ cdns_hdmi_mode_set(mhdp); ++ mutex_unlock(&mhdp->lock); + enable_irq(mhdp->irq[IRQ_OUT]); + } else if (connector->status == connector_status_disconnected) { + /* Cable Disconnedted */ |