diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 7ddd040093..231378d9d3 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -2428,17 +2428,37 @@ static void _sde_encoder_virt_populate_hw_res(struct drm_encoder *drm_enc) } static int sde_encoder_virt_modeset_rc(struct drm_encoder *drm_enc, - struct msm_display_mode *msm_mode, bool pre_modeset) + struct drm_display_mode *adj_mode, struct msm_display_mode *msm_mode, bool pre_modeset) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); enum sde_intf_mode intf_mode; + struct drm_display_mode *old_adj_mode = NULL; int ret; - bool is_cmd_mode = false; + bool is_cmd_mode = false, res_switch = false; if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) is_cmd_mode = true; if (pre_modeset) { + if (sde_enc->cur_master) + old_adj_mode = &sde_enc->cur_master->cached_mode; + if (old_adj_mode && is_cmd_mode) + res_switch = !drm_mode_match(old_adj_mode, adj_mode, + DRM_MODE_MATCH_TIMINGS); + + if (res_switch && sde_enc->disp_info.is_te_using_watchdog_timer) { + /* + * add tx wait for sim panel to avoid wd timer getting + * updated in middle of frame to avoid early vsync + */ + ret = sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); + if (ret && ret != -EWOULDBLOCK) { + SDE_ERROR_ENC(sde_enc, "wait for idle failed %d\n", ret); + SDE_EVT32(DRMID(drm_enc), ret, SDE_EVTLOG_ERROR); + return ret; + } + } + intf_mode = sde_encoder_get_intf_mode(drm_enc); if (msm_is_mode_seamless_dms(msm_mode) || (msm_is_mode_seamless_dyn_clk(msm_mode) && @@ -2545,7 +2565,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, /* release resources before seamless mode change */ msm_mode = &c_state->msm_mode; - ret = sde_encoder_virt_modeset_rc(drm_enc, msm_mode, true); + ret = sde_encoder_virt_modeset_rc(drm_enc, adj_mode, msm_mode, true); if (ret) return; @@ -2585,7 +2605,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, } /* update resources after seamless mode change */ - sde_encoder_virt_modeset_rc(drm_enc, msm_mode, false); + sde_encoder_virt_modeset_rc(drm_enc, adj_mode, msm_mode, false); } void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable)