layerscape: add patches-5.4
[openwrt/staging/wigyori.git] / target / linux / layerscape / patches-5.4 / 805-display-0023-drm-mhdp-reset-video-mode-after-hdmi-dp-cable-plugin.patch
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 (file)
index 0000000..9e90f7d
--- /dev/null
@@ -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  */