From fd70e6d353b10dd5818b49a9e09fec6f56ce0658 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 14 Dec 2021 09:14:58 +0800 Subject: [PATCH] drm/rockchip: dw-dp: Fix connectors changed in clone mode When a new connector is added to current routing in clone mode, the new connector doesn't have mode_changed=true set. This incorrect programming sequence causes .mode_set call mismatches to occur in the new stream. So move the mode_set code to other callback. Signed-off-by: Wyon Bi Change-Id: I90f50882057c63f702cf390fb7bfeed088575324 --- drivers/gpu/drm/rockchip/dw-dp.c | 40 ++++++++++++++------------------ 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index b36be6ab710b..2db48619d972 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -1533,6 +1533,9 @@ static void dw_dp_encoder_disable(struct drm_encoder *encoder) struct drm_crtc *crtc = encoder->crtc; struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); + if (!crtc->state->active_changed) + return; + if (dp->split_mode) s->output_if &= ~(VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1); else @@ -1562,6 +1565,15 @@ static int dw_dp_encoder_atomic_check(struct drm_encoder *encoder, break; } + if (dp->split_mode) { + s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE; + s->output_flags |= dp->id ? ROCKCHIP_OUTPUT_DATA_SWAP : 0; + s->output_if |= VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1; + } else { + s->output_if |= dp->id ? VOP_OUTPUT_IF_DP1 : VOP_OUTPUT_IF_DP0; + } + + s->output_type = DRM_MODE_CONNECTOR_DisplayPort; s->bus_format = video->bus_format; s->bus_flags = di->bus_flags; s->tv_state = &conn_state->tv; @@ -1571,27 +1583,9 @@ static int dw_dp_encoder_atomic_check(struct drm_encoder *encoder, return 0; } -static void dw_dp_encoder_atomic_mode_set(struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - struct dw_dp *dp = encoder_to_dp(encoder); - struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); - - s->output_type = DRM_MODE_CONNECTOR_DisplayPort; - if (dp->split_mode) { - s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE; - s->output_flags |= dp->id ? ROCKCHIP_OUTPUT_DATA_SWAP : 0; - s->output_if |= VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1; - } else { - s->output_if |= dp->id ? VOP_OUTPUT_IF_DP1 : VOP_OUTPUT_IF_DP0; - } -} - static const struct drm_encoder_helper_funcs dw_dp_encoder_helper_funcs = { .enable = dw_dp_encoder_enable, .disable = dw_dp_encoder_disable, - .atomic_mode_set = dw_dp_encoder_atomic_mode_set, .atomic_check = dw_dp_encoder_atomic_check, }; @@ -1763,15 +1757,15 @@ static void dw_dp_bridge_detach(struct drm_bridge *bridge) drm_connector_cleanup(&dp->connector); } -static void dw_dp_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adjusted_mode) +static void dw_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state) { struct dw_dp *dp = bridge_to_dp(bridge); struct dw_dp_video *video = &dp->video; + struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state; struct drm_display_mode *m = &video->mode; - drm_mode_copy(m, adjusted_mode); + drm_mode_copy(m, &crtc_state->adjusted_mode); if (dp->split_mode) drm_mode_convert_to_origin_mode(m); @@ -1975,9 +1969,9 @@ static const struct drm_bridge_funcs dw_dp_bridge_funcs = { .atomic_get_output_bus_fmts = dw_dp_bridge_atomic_get_output_bus_fmts, .attach = dw_dp_bridge_attach, .detach = dw_dp_bridge_detach, - .mode_set = dw_dp_bridge_mode_set, .mode_valid = dw_dp_bridge_mode_valid, .atomic_check = dw_dp_bridge_atomic_check, + .atomic_pre_enable = dw_dp_bridge_atomic_pre_enable, .atomic_enable = dw_dp_bridge_atomic_enable, .atomic_disable = dw_dp_bridge_atomic_disable, .detect = dw_dp_bridge_detect,