mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 09:12:39 +00:00
237 lines
7.0 KiB
Diff
237 lines
7.0 KiB
Diff
|
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 */
|