| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From d13b544c949e85e39f6c1c20485d8f37f5127e59 Mon Sep 17 00:00:00 2001 |
| 2 | From: Sandor Yu <Sandor.yu@nxp.com> |
| 3 | Date: Fri, 20 Dec 2019 17:31:52 +0800 |
| 4 | Subject: [PATCH] LF-568-2: drm: gpu: bridge: cdns: Add force mode set flag |
| 5 | |
| 6 | In DRM framework, when hdmi/dp cable plugout/plugin in the same HDMI |
| 7 | sink, because the video mode is same, DRM will not call mode_set. |
| 8 | But for HDMI 2.0 sink the SCDC configurate will lost, and DP sink |
| 9 | linktraning status will lost too after cable plugout then plugin. |
| 10 | |
| 11 | Currently, hdmi/dp driver will call mode_set function in HPD thread, |
| 12 | But the mode_set function is called out of DRM framework, and it have |
| 13 | chance to fail. |
| 14 | In the patch add force_mode_set flag, set the crtc_state->mode_changed |
| 15 | to force drm call mode_set when cable plugin. |
| 16 | |
| 17 | Signed-off-by: Sandor Yu <Sandor.yu@nxp.com> |
| 18 | --- |
| 19 | drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 5 +++++ |
| 20 | drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 12 ++++++++---- |
| 21 | drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c | 4 ++++ |
| 22 | include/drm/bridge/cdns-mhdp-common.h | 1 + |
| 23 | 4 files changed, 18 insertions(+), 4 deletions(-) |
| 24 | |
| 25 | --- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c |
| 26 | +++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c |
| 27 | @@ -322,6 +322,9 @@ static void cdns_dp_bridge_mode_set(stru |
| 28 | mutex_lock(&mhdp->lock); |
| 29 | cdns_dp_mode_set(mhdp); |
| 30 | mutex_unlock(&mhdp->lock); |
| 31 | + |
| 32 | + /* reset force mode set flag */ |
| 33 | + mhdp->force_mode_set = false; |
| 34 | } |
| 35 | |
| 36 | static void cdn_dp_bridge_enable(struct drm_bridge *bridge) |
| 37 | @@ -375,6 +378,8 @@ static void hotplug_work_func(struct wor |
| 38 | } else if (connector->status == connector_status_disconnected) { |
| 39 | /* Cable Disconnedted */ |
| 40 | DRM_INFO("HDMI/DP Cable Plug Out\n"); |
| 41 | + /* force mode set for cable replugin to recovery DP video modes */ |
| 42 | + mhdp->force_mode_set = true; |
| 43 | enable_irq(mhdp->irq[IRQ_IN]); |
| 44 | } |
| 45 | } |
| 46 | --- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c |
| 47 | +++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c |
| 48 | @@ -178,6 +178,10 @@ void cdns_hdmi_mode_set(struct cdns_mhdp |
| 49 | struct drm_display_mode *mode = &mhdp->mode; |
| 50 | int ret; |
| 51 | |
| 52 | + /* video mode valid check */ |
| 53 | + if (mode->clock == 0 || mode->hdisplay == 0 || mode->vdisplay == 0) |
| 54 | + return; |
| 55 | + |
| 56 | hdmi_lanes_config(mhdp); |
| 57 | |
| 58 | cdns_mhdp_plat_call(mhdp, pclk_rate); |
| 59 | @@ -393,6 +397,8 @@ static void cdns_hdmi_bridge_mode_set(st |
| 60 | mutex_lock(&mhdp->lock); |
| 61 | cdns_hdmi_mode_set(mhdp); |
| 62 | mutex_unlock(&mhdp->lock); |
| 63 | + /* reset force mode set flag */ |
| 64 | + mhdp->force_mode_set = false; |
| 65 | } |
| 66 | |
| 67 | bool cdns_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, |
| 68 | @@ -467,14 +473,12 @@ static void hotplug_work_func(struct wor |
| 69 | |
| 70 | if (connector->status == connector_status_connected) { |
| 71 | DRM_INFO("HDMI Cable Plug In\n"); |
| 72 | - /* reset video mode after cable plugin */ |
| 73 | - mutex_lock(&mhdp->lock); |
| 74 | - cdns_hdmi_mode_set(mhdp); |
| 75 | - mutex_unlock(&mhdp->lock); |
| 76 | enable_irq(mhdp->irq[IRQ_OUT]); |
| 77 | } else if (connector->status == connector_status_disconnected) { |
| 78 | /* Cable Disconnedted */ |
| 79 | DRM_INFO("HDMI Cable Plug Out\n"); |
| 80 | + /* force mode set for cable replugin to recovery HDMI2.0 video modes */ |
| 81 | + mhdp->force_mode_set = true; |
| 82 | enable_irq(mhdp->irq[IRQ_IN]); |
| 83 | } |
| 84 | } |
| 85 | --- a/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c |
| 86 | +++ b/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c |
| 87 | @@ -40,6 +40,10 @@ static int cdns_mhdp_imx_encoder_atomic_ |
| 88 | |
| 89 | if (mhdp->plat_data->video_format != 0) |
| 90 | imx_crtc_state->bus_format = mhdp->plat_data->video_format; |
| 91 | + |
| 92 | + if (mhdp->force_mode_set) |
| 93 | + crtc_state->mode_changed = true; |
| 94 | + |
| 95 | return 0; |
| 96 | } |
| 97 | |
| 98 | --- a/include/drm/bridge/cdns-mhdp-common.h |
| 99 | +++ b/include/drm/bridge/cdns-mhdp-common.h |
| 100 | @@ -684,6 +684,7 @@ struct cdns_mhdp_device { |
| 101 | bool link_up; |
| 102 | bool power_up; |
| 103 | bool plugged; |
| 104 | + bool force_mode_set; |
| 105 | bool is_hpd; |
| 106 | bool is_ls1028a; |
| 107 | struct mutex lock; |