Merge "disp: msm: dsi: optimize wait time in DSI timing DB update"

This commit is contained in:
qctecmdr
2023-01-29 22:32:25 -08:00
committed by Gerrit - the friendly Code Review server
7 changed files with 49 additions and 6 deletions

View File

@@ -2516,13 +2516,14 @@ exit:
* dsi_ctrl_timing_db_update() - update only controller Timing DB * dsi_ctrl_timing_db_update() - update only controller Timing DB
* @dsi_ctrl: DSI controller handle. * @dsi_ctrl: DSI controller handle.
* @enable: Enable/disable Timing DB register * @enable: Enable/disable Timing DB register
* @pf_time_in_us: Programmable fetch time in micro-seconds
* *
* Update timing db register value during dfps usecases * Update timing db register value during dfps usecases
* *
* Return: error code. * Return: error code.
*/ */
int dsi_ctrl_timing_db_update(struct dsi_ctrl *dsi_ctrl, int dsi_ctrl_timing_db_update(struct dsi_ctrl *dsi_ctrl,
bool enable) bool enable, u32 pf_time_in_us)
{ {
int rc = 0; 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 * flush is after panel_vsync. So, added the recommended
* delays after dfps update. * 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); dsi_ctrl->hw.ops.set_timing_db(&dsi_ctrl->hw, enable);

View File

@@ -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_timing_db_update() - update only controller Timing DB
* @dsi_ctrl: DSI controller handle. * @dsi_ctrl: DSI controller handle.
* @enable: Enable/disable Timing DB register * @enable: Enable/disable Timing DB register
* @pf_time_in_us: Programmable fetch time in micro-seconds
* *
* Update timing db register value during dfps usecases * Update timing db register value during dfps usecases
* *
* Return: error code. * Return: error code.
*/ */
int dsi_ctrl_timing_db_update(struct dsi_ctrl *dsi_ctrl, 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 * dsi_ctrl_async_timing_update() - update only controller timing

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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. * 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 *display;
struct dsi_display_ctrl *m_ctrl, *ctrl; struct dsi_display_ctrl *m_ctrl, *ctrl;
int i, rc = 0, ctrl_version; int i, rc = 0, ctrl_version;
u32 pf_time_in_us = 0;
bool enable; bool enable;
struct dsi_dyn_clk_caps *dyn_clk_caps; 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; display = c_bridge->display;
dyn_clk_caps = &(display->panel->dyn_clk_caps); 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) { if (adj_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR) {
m_ctrl = &display->ctrl[display->clk_master_idx]; m_ctrl = &display->ctrl[display->clk_master_idx];
ctrl_version = m_ctrl->ctrl->version; 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) { if (rc) {
DSI_ERR("[%s] failed to dfps update rc=%d\n", DSI_ERR("[%s] failed to dfps update rc=%d\n",
display->name, rc); display->name, rc);
@@ -1354,7 +1357,7 @@ int dsi_conn_post_kickoff(struct drm_connector *connector,
if (!ctrl->ctrl || (ctrl == m_ctrl)) if (!ctrl->ctrl || (ctrl == m_ctrl))
continue; 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) { if (rc) {
DSI_ERR("[%s] failed to dfps update rc=%d\n", DSI_ERR("[%s] failed to dfps update rc=%d\n",
display->name, rc); display->name, rc);

View File

@@ -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) ktime_t sde_encoder_calc_last_vsync_timestamp(struct drm_encoder *drm_enc)
{ {
struct sde_encoder_virt *sde_enc; struct sde_encoder_virt *sde_enc;

View File

@@ -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); 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); void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc);
/** /**

View File

@@ -335,6 +335,7 @@ struct sde_encoder_irq {
* @in_clone_mode Indicates if encoder is in clone mode ref@CWB * @in_clone_mode Indicates if encoder is in clone mode ref@CWB
* @vfp_cached: cached vertical front porch to be used for * @vfp_cached: cached vertical front porch to be used for
* programming ROT and MDP fetch start * 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 * @frame_trigger_mode: frame trigger mode indication for command
* mode display * mode display
* @recovered: flag set to true when recovered from pp timeout * @recovered: flag set to true when recovered from pp timeout
@@ -385,6 +386,7 @@ struct sde_encoder_phys {
bool cont_splash_enabled; bool cont_splash_enabled;
bool in_clone_mode; bool in_clone_mode;
int vfp_cached; int vfp_cached;
u32 pf_time_in_us;
enum frame_trigger_mode_type frame_trigger_mode; enum frame_trigger_mode_type frame_trigger_mode;
bool recovered; bool recovered;
bool autorefresh_disable_trans; bool autorefresh_disable_trans;

View File

@@ -283,6 +283,7 @@ static void programmable_fetch_config(struct sde_encoder_phys *phys_enc,
m = phys_enc->sde_kms->catalog; m = phys_enc->sde_kms->catalog;
phys_enc->pf_time_in_us = 0;
vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, timing); vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, timing);
if (vfp_fetch_lines) { if (vfp_fetch_lines) {
vert_total = get_vertical_total(timing); 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 = vfp_fetch_start_vsync_counter =
(vert_total - vfp_fetch_lines) * horiz_total + 1; (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 * Check if we need to throttle the fetch to start
* from second line after the active region. * from second line after the active region.