Przeglądaj źródła

disp: msm: check max FPS of DFPS to update UIDLE configurations

It is not applicable for all DFPS cases to update UIDLE state
according to current frame rate. If DFPS changes frame rate
through vertical front porch values, the SDE clocks and transfer
time will not get changed accordingly, and it always get fixed
at max frame rate configuration of DFPS.
Add this change to check max FPS of DFPS instead of current
frame rate for UIDLE update, if DFPS is enabled with VFP.

Change-Id: I7634bce6a9eb1af212ba19a267735be08b20ae1f
Signed-off-by: Lei Chen <[email protected]>
Lei Chen 4 lat temu
rodzic
commit
c44e0b42df
6 zmienionych plików z 78 dodań i 1 usunięć
  1. 23 0
      msm/dsi/dsi_drm.c
  2. 2 0
      msm/msm_drv.h
  3. 10 1
      msm/sde/sde_core_perf.c
  4. 18 0
      msm/sde/sde_crtc.c
  5. 6 0
      msm/sde/sde_crtc.h
  6. 19 0
      msm/sde/sde_encoder.h

+ 23 - 0
msm/dsi/dsi_drm.c

@@ -439,6 +439,28 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
 	return true;
 }
 
+u32 dsi_drm_get_dfps_maxfps(void *display)
+{
+	u32 dfps_maxfps = 0;
+	struct dsi_display *dsi_display = display;
+
+	/*
+	 * The time of SDE transmitting one frame active data
+	 * will not be changed, if frame rate is adjusted with
+	 * VFP method.
+	 * So only return max fps of DFPS for UIDLE update, if DFPS
+	 * is enabled with VFP.
+	 */
+	if (dsi_display && dsi_display->panel &&
+		dsi_display->panel->panel_mode == DSI_OP_VIDEO_MODE &&
+		dsi_display->panel->dfps_caps.type ==
+					DSI_DFPS_IMMEDIATE_VFP)
+		dfps_maxfps =
+			dsi_display->panel->dfps_caps.max_refresh_rate;
+
+	return dfps_maxfps;
+}
+
 u64 dsi_drm_find_bit_clk_rate(void *display,
 			      const struct drm_display_mode *drm_mode)
 {
@@ -492,6 +514,7 @@ int dsi_conn_get_mode_info(struct drm_connector *connector,
 	mode_info->jitter_numer = dsi_mode.priv_info->panel_jitter_numer;
 	mode_info->jitter_denom = dsi_mode.priv_info->panel_jitter_denom;
 	mode_info->clk_rate = dsi_drm_find_bit_clk_rate(display, drm_mode);
+	mode_info->dfps_maxfps = dsi_drm_get_dfps_maxfps(display);
 	mode_info->mdp_transfer_time_us =
 		dsi_mode.priv_info->mdp_transfer_time_us;
 

+ 2 - 0
msm/msm_drv.h

@@ -675,6 +675,7 @@ struct msm_display_topology {
  * @jitter_numer:	display panel jitter numerator configuration
  * @jitter_denom:	display panel jitter denominator configuration
  * @clk_rate:	     DSI bit clock per lane in HZ.
+ * @dfps_maxfps:     max FPS of dynamic FPS
  * @topology:        supported topology for the mode
  * @comp_info:       compression info supported
  * @roi_caps:        panel roi capabilities
@@ -689,6 +690,7 @@ struct msm_mode_info {
 	uint32_t jitter_numer;
 	uint32_t jitter_denom;
 	uint64_t clk_rate;
+	uint32_t dfps_maxfps;
 	struct msm_display_topology topology;
 	struct msm_compression_info comp_info;
 	struct msm_roi_caps roi_caps;

+ 10 - 1
msm/sde/sde_core_perf.c

@@ -603,7 +603,16 @@ void sde_core_perf_crtc_update_uidle(struct drm_crtc *crtc,
 	drm_for_each_crtc(tmp_crtc, crtc->dev) {
 		if (_sde_core_perf_crtc_is_power_on(tmp_crtc)) {
 
-			fps = sde_crtc_get_fps_mode(tmp_crtc);
+			/*
+			 * If DFPS is enabled with VFP, SDE clock and
+			 * transfer time will get fixed at max FPS
+			 * configuration of DFPS.
+			 * So get the max FPS of DFPS firstly for
+			 * UIDLE update, if DFPS is enabled with VFP.
+			 */
+			fps = sde_crtc_get_dfps_maxfps(tmp_crtc);
+			if (!fps)
+				fps = sde_crtc_get_fps_mode(tmp_crtc);
 
 			SDE_DEBUG("crtc=%d fps:%d wb:%d cwb:%d dis:%d en:%d\n",
 				tmp_crtc->base.id, fps,

+ 18 - 0
msm/sde/sde_crtc.c

@@ -2375,6 +2375,24 @@ u32 sde_crtc_get_fps_mode(struct drm_crtc *crtc)
 	return 0;
 }
 
+u32 sde_crtc_get_dfps_maxfps(struct drm_crtc *crtc)
+{
+	struct drm_encoder *encoder;
+
+	if (!crtc || !crtc->dev) {
+		SDE_ERROR("invalid crtc\n");
+		return 0;
+	}
+
+	drm_for_each_encoder_mask(encoder, crtc->dev,
+			crtc->state->encoder_mask) {
+		if (!sde_encoder_in_cont_splash(encoder))
+			return sde_encoder_get_dfps_maxfps(encoder);
+	}
+
+	return 0;
+}
+
 static void sde_crtc_vblank_cb(void *data)
 {
 	struct drm_crtc *crtc = (struct drm_crtc *)data;

+ 6 - 0
msm/sde/sde_crtc.h

@@ -652,6 +652,12 @@ enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc,
  */
 u32 sde_crtc_get_fps_mode(struct drm_crtc *crtc);
 
+/**
+ * sde_crtc_get_dfps_maxfps - get DFPS max fps of the given crtc
+ * @crtc: Pointert to crtc
+ */
+u32 sde_crtc_get_dfps_maxfps(struct drm_crtc *crtc);
+
 /**
  * sde_crtc_get_client_type - check the crtc type- rt, rsc_rt, etc.
  * @crtc: Pointer to crtc

+ 19 - 0
msm/sde/sde_encoder.h

@@ -545,6 +545,25 @@ void sde_encoder_uidle_enable(struct drm_encoder *drm_enc, bool enable);
  */
 void sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable);
 
+/*
+ * sde_encoder_get_dfps_maxfps - get dynamic FPS max frame rate of
+				the given encoder
+ * @encoder: Pointer to drm encoder object
+ */
+static inline u32 sde_encoder_get_dfps_maxfps(struct drm_encoder *drm_enc)
+{
+	struct sde_encoder_virt *sde_enc;
+
+	if (!drm_enc) {
+		SDE_ERROR("invalid encoder\n");
+		return 0;
+	}
+
+	sde_enc = to_sde_encoder_virt(drm_enc);
+
+	return sde_enc->mode_info.dfps_maxfps;
+}
+
 /**
  * sde_encoder_get_kms - retrieve the kms from encoder
  * @drm_enc:    Pointer to drm encoder structure