From 9ff3c9d6063c6464e243b85bbbbd03e2096a57c0 Mon Sep 17 00:00:00 2001 From: Sandor Yu 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 --- 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 #include -#include #include #include #include #include +#include #include #include #include @@ -26,25 +26,30 @@ #include #include -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 */