Kaynağa Gözat

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

qctecmdr 2 yıl önce
ebeveyn
işleme
76cbb717c4

+ 9 - 2
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);
 

+ 2 - 1
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

+ 6 - 3
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);

+ 19 - 0
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;

+ 7 - 0
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);
 
 /**

+ 2 - 0
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;

+ 4 - 0
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.