diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index a92f05eaac..6316f1fe3a 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -2516,13 +2516,14 @@ exit: * dsi_ctrl_timing_db_update() - update only controller Timing DB * @dsi_ctrl: DSI controller handle. * @enable: Enable/disable Timing DB register + * @pf_time_in_us: Programmable fetch time in micro-seconds * * Update timing db register value during dfps usecases * * Return: error code. */ int dsi_ctrl_timing_db_update(struct dsi_ctrl *dsi_ctrl, - bool enable) + bool enable, u32 pf_time_in_us) { int rc = 0; @@ -2550,7 +2551,13 @@ int dsi_ctrl_timing_db_update(struct dsi_ctrl *dsi_ctrl, * flush is after panel_vsync. So, added the recommended * delays after dfps update. */ - usleep_range(2000, 2010); + if (pf_time_in_us > 2000) { + DSI_CTRL_ERR(dsi_ctrl, "Programmable fetch time check failed, pf_time_in_us=%u\n", + pf_time_in_us); + pf_time_in_us = 2000; + } + + usleep_range(pf_time_in_us, pf_time_in_us + 10); dsi_ctrl->hw.ops.set_timing_db(&dsi_ctrl->hw, enable); diff --git a/msm/dsi/dsi_ctrl.h b/msm/dsi/dsi_ctrl.h index 2100b8ecf8..d7061e8710 100644 --- a/msm/dsi/dsi_ctrl.h +++ b/msm/dsi/dsi_ctrl.h @@ -414,13 +414,14 @@ int dsi_ctrl_update_host_config(struct dsi_ctrl *dsi_ctrl, * dsi_ctrl_timing_db_update() - update only controller Timing DB * @dsi_ctrl: DSI controller handle. * @enable: Enable/disable Timing DB register + * @pf_time_in_us: Programmable fetch time in micro-seconds * * Update timing db register value during dfps usecases * * Return: error code. */ int dsi_ctrl_timing_db_update(struct dsi_ctrl *dsi_ctrl, - bool enable); + bool enable, u32 pf_time_in_us); /** * dsi_ctrl_async_timing_update() - update only controller timing diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index 25db59db0b..4314d12928 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -1292,6 +1292,7 @@ int dsi_conn_post_kickoff(struct drm_connector *connector, struct dsi_display *display; struct dsi_display_ctrl *m_ctrl, *ctrl; int i, rc = 0, ctrl_version; + u32 pf_time_in_us = 0; bool enable; struct dsi_dyn_clk_caps *dyn_clk_caps; @@ -1316,10 +1317,12 @@ int dsi_conn_post_kickoff(struct drm_connector *connector, display = c_bridge->display; dyn_clk_caps = &(display->panel->dyn_clk_caps); + pf_time_in_us = sde_encoder_get_programmed_fetch_time(encoder); + if (adj_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR) { m_ctrl = &display->ctrl[display->clk_master_idx]; ctrl_version = m_ctrl->ctrl->version; - rc = dsi_ctrl_timing_db_update(m_ctrl->ctrl, false); + rc = dsi_ctrl_timing_db_update(m_ctrl->ctrl, false, pf_time_in_us); if (rc) { DSI_ERR("[%s] failed to dfps update rc=%d\n", display->name, rc); @@ -1354,7 +1357,7 @@ int dsi_conn_post_kickoff(struct drm_connector *connector, if (!ctrl->ctrl || (ctrl == m_ctrl)) continue; - rc = dsi_ctrl_timing_db_update(ctrl->ctrl, false); + rc = dsi_ctrl_timing_db_update(ctrl->ctrl, false, pf_time_in_us); if (rc) { DSI_ERR("[%s] failed to dfps update rc=%d\n", display->name, rc); diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 48655a7088..e121d5c7bf 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -155,6 +155,25 @@ void sde_encoder_uidle_enable(struct drm_encoder *drm_enc, bool enable) } } +u32 sde_encoder_get_programmed_fetch_time(struct drm_encoder *drm_enc) +{ + struct sde_encoder_virt *sde_enc; + struct sde_encoder_phys *phys; + bool is_vid; + + sde_enc = to_sde_encoder_virt(drm_enc); + + if (!sde_enc || !sde_enc->phys_encs[0]) { + SDE_ERROR("invalid params\n"); + return U32_MAX; + } + + phys = sde_enc->phys_encs[0]; + is_vid = sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE); + + return is_vid ? phys->pf_time_in_us : 0; +} + ktime_t sde_encoder_calc_last_vsync_timestamp(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc; diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index 0a401e5eaf..849be30a02 100644 --- a/msm/sde/sde_encoder.h +++ b/msm/sde/sde_encoder.h @@ -716,6 +716,13 @@ bool sde_encoder_is_line_insertion_supported(struct drm_encoder *drm_enc); */ struct sde_hw_ctl *sde_encoder_get_hw_ctl(struct sde_connector *c_conn); +/* + * sde_encoder_get_programmed_fetch_time - gets the programmable fetch time for video encoders + * @drm_enc: Pointer to drm encoder structure + * @Return: programmable fetch time in microseconds + */ +u32 sde_encoder_get_programmed_fetch_time(struct drm_encoder *encoder); + void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc); /** diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 9ea1e8037d..a043254568 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -335,6 +335,7 @@ struct sde_encoder_irq { * @in_clone_mode Indicates if encoder is in clone mode ref@CWB * @vfp_cached: cached vertical front porch to be used for * programming ROT and MDP fetch start + * @pf_time_in_us: Programmable fetch time in micro-seconds * @frame_trigger_mode: frame trigger mode indication for command * mode display * @recovered: flag set to true when recovered from pp timeout @@ -385,6 +386,7 @@ struct sde_encoder_phys { bool cont_splash_enabled; bool in_clone_mode; int vfp_cached; + u32 pf_time_in_us; enum frame_trigger_mode_type frame_trigger_mode; bool recovered; bool autorefresh_disable_trans; diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index fd541000cb..ccba77683a 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -283,6 +283,7 @@ static void programmable_fetch_config(struct sde_encoder_phys *phys_enc, m = phys_enc->sde_kms->catalog; + phys_enc->pf_time_in_us = 0; vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, timing); if (vfp_fetch_lines) { vert_total = get_vertical_total(timing); @@ -290,6 +291,9 @@ static void programmable_fetch_config(struct sde_encoder_phys *phys_enc, vfp_fetch_start_vsync_counter = (vert_total - vfp_fetch_lines) * horiz_total + 1; + phys_enc->pf_time_in_us = DIV_ROUND_UP(1000000 * vfp_fetch_lines, + vert_total * timing->vrefresh); + /** * Check if we need to throttle the fetch to start * from second line after the active region.