Browse Source

disp: msm: sde: calculate line_time once during modeset

Calculate line_time once during modeset and allow
each plane to use it instead of calculating for each frame.
It also simplifies the line_time calculation for
command mode display.

Change-Id: I94ce29eec94bfdbee9016fbf93378661ebf79c03
Signed-off-by: Dhaval Patel <[email protected]>
Dhaval Patel 4 years ago
parent
commit
b5cde14bca

+ 28 - 0
msm/sde/sde_crtc.c

@@ -5875,6 +5875,33 @@ exit:
 	return ret;
 	return ret;
 }
 }
 
 
+static void sde_crtc_update_line_time(struct drm_crtc *crtc)
+{
+	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
+	struct drm_encoder *encoder;
+	u32 min_transfer_time = 0, updated_fps = 0;
+
+	drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) {
+		if (sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_CMD_MODE))
+			sde_encoder_get_transfer_time(encoder, &min_transfer_time);
+	}
+
+	if (min_transfer_time) {
+		/* get fps by doing 1000 ms / transfer_time */
+		updated_fps = DIV_ROUND_UP(1000000, min_transfer_time);
+		/* get line time by doing 1000ns / (fps * vactive) */
+		sde_crtc->line_time_in_ns = DIV_ROUND_UP(1000000000,
+				updated_fps * crtc->mode.vdisplay);
+	} else {
+		/* get line time by doing 1000ns / (fps * vtotal) */
+		sde_crtc->line_time_in_ns = DIV_ROUND_UP(1000000000,
+				drm_mode_vrefresh(&crtc->mode) * crtc->mode.vtotal);
+	}
+
+	SDE_EVT32(min_transfer_time, updated_fps, crtc->mode.vdisplay, crtc->mode.vtotal,
+		drm_mode_vrefresh(&crtc->mode), sde_crtc->line_time_in_ns);
+}
+
 void sde_crtc_set_qos_dirty(struct drm_crtc *crtc)
 void sde_crtc_set_qos_dirty(struct drm_crtc *crtc)
 {
 {
 	struct drm_plane *plane;
 	struct drm_plane *plane;
@@ -5890,6 +5917,7 @@ void sde_crtc_set_qos_dirty(struct drm_crtc *crtc)
 
 
 		pstate->dirty |= SDE_PLANE_DIRTY_QOS;
 		pstate->dirty |= SDE_PLANE_DIRTY_QOS;
 	}
 	}
+	sde_crtc_update_line_time(crtc);
 }
 }
 
 
 /**
 /**

+ 12 - 1
msm/sde/sde_crtc.h

@@ -300,7 +300,7 @@ struct sde_crtc_misr_info {
  * @skip_blend_plane: enabled plane that has skip blending
  * @skip_blend_plane: enabled plane that has skip blending
  * @skip_blend_plane_w: skip blend plane width
  * @skip_blend_plane_w: skip blend plane width
  * @skip_blend_plane_h: skip blend plane height
  * @skip_blend_plane_h: skip blend plane height
- *
+ * @line_time_in_ns : current mode line time in nano sec is needed for QOS update
  */
  */
 struct sde_crtc {
 struct sde_crtc {
 	struct drm_crtc base;
 	struct drm_crtc base;
@@ -397,6 +397,7 @@ struct sde_crtc {
 	enum sde_sspp skip_blend_plane;
 	enum sde_sspp skip_blend_plane;
 	u32 skip_blend_plane_w;
 	u32 skip_blend_plane_w;
 	u32 skip_blend_plane_h;
 	u32 skip_blend_plane_h;
+	u32 line_time_in_ns;
 };
 };
 
 
 enum sde_crtc_dirty_flags {
 enum sde_crtc_dirty_flags {
@@ -741,6 +742,16 @@ static inline bool sde_crtc_is_enabled(struct drm_crtc *crtc)
 	return crtc ? crtc->enabled : false;
 	return crtc ? crtc->enabled : false;
 }
 }
 
 
+static inline u32 sde_crtc_get_line_time(struct drm_crtc *crtc)
+{
+	struct sde_crtc *sde_crtc;
+
+	if (!crtc)
+		return 0;
+	sde_crtc = to_sde_crtc(crtc);
+	return sde_crtc->line_time_in_ns;
+}
+
 /**
 /**
  * sde_crtc_is_reset_required - validate the reset request based on the
  * sde_crtc_is_reset_required - validate the reset request based on the
  *	pm_suspend and crtc's active status. crtc's are left active
  *	pm_suspend and crtc's active status. crtc's are left active

+ 1 - 1
msm/sde/sde_encoder.c

@@ -4336,7 +4336,7 @@ void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc,
 	}
 	}
 }
 }
 
 
-void sde_encoder_helper_get_transfer_time(struct drm_encoder *drm_enc,
+void sde_encoder_get_transfer_time(struct drm_encoder *drm_enc,
 			u32 *transfer_time_us)
 			u32 *transfer_time_us)
 {
 {
 	struct sde_encoder_virt *sde_enc;
 	struct sde_encoder_virt *sde_enc;

+ 8 - 0
msm/sde/sde_encoder.h

@@ -581,6 +581,14 @@ void sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable);
 struct drm_connector *sde_encoder_get_connector(struct drm_device *dev,
 struct drm_connector *sde_encoder_get_connector(struct drm_device *dev,
 			struct drm_encoder *drm_enc);
 			struct drm_encoder *drm_enc);
 
 
+/**
+ * sde_encoder_get_transfer_time - get the mdp transfer time in usecs
+ * @drm_enc: Pointer to drm encoder structure
+ * @transfer_time_us: Pointer to store the output value
+ */
+void sde_encoder_get_transfer_time(struct drm_encoder *drm_enc,
+		u32 *transfer_time_us);
+
 /*
 /*
  * sde_encoder_get_dfps_maxfps - get dynamic FPS max frame rate of
  * sde_encoder_get_dfps_maxfps - get dynamic FPS max frame rate of
 				the given encoder
 				the given encoder

+ 0 - 8
msm/sde/sde_encoder_phys.h

@@ -542,14 +542,6 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
 void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc,
 void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc,
 		struct sde_hw_pp_vsync_info *info);
 		struct sde_hw_pp_vsync_info *info);
 
 
-/**
- * sde_encoder_helper_get_transfer_time - get the mdp transfer time in usecs
- * @drm_enc: Pointer to drm encoder structure
- * @transfer_time_us: Pointer to store the output value
- */
-void sde_encoder_helper_get_transfer_time(struct drm_encoder *drm_enc,
-		u32 *transfer_time_us);
-
 /**
 /**
  * sde_encoder_helper_trigger_flush - control flush helper function
  * sde_encoder_helper_trigger_flush - control flush helper function
  *	This helper function may be optionally specified by physical
  *	This helper function may be optionally specified by physical

+ 5 - 5
msm/sde/sde_encoder_phys_cmd.c

@@ -975,18 +975,18 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc)
 		}
 		}
 
 
 		/* Calculate the number of extra lines*/
 		/* Calculate the number of extra lines*/
-		slow_time_ns = (1 * 1000000000) / qsync_min_fps;
-		default_time_ns = (1 * 1000000000) / default_fps;
-		sde_encoder_helper_get_transfer_time(phys_enc->parent,
+		slow_time_ns = DIV_ROUND_UP(1000000000, qsync_min_fps);
+		default_time_ns = DIV_ROUND_UP(1000000000, default_fps);
+		sde_encoder_get_transfer_time(phys_enc->parent,
 				&transfer_time_us);
 				&transfer_time_us);
 		if (transfer_time_us)
 		if (transfer_time_us)
 			idle_time_ns = default_time_ns -
 			idle_time_ns = default_time_ns -
 					(1000 * transfer_time_us);
 					(1000 * transfer_time_us);
 
 
 		extra_time_ns = slow_time_ns - default_time_ns + idle_time_ns;
 		extra_time_ns = slow_time_ns - default_time_ns + idle_time_ns;
-		default_line_time_ns = (1 * 1000000000) / (default_fps * yres);
+		default_line_time_ns = DIV_ROUND_UP(1000000000, default_fps * yres);
 
 
-		threshold_lines = extra_time_ns / default_line_time_ns;
+		threshold_lines = DIV_ROUND_UP(extra_time_ns, default_line_time_ns);
 
 
 		SDE_DEBUG_CMDENC(cmd_enc, "slow:%d default:%d extra:%d(ns)\n",
 		SDE_DEBUG_CMDENC(cmd_enc, "slow:%d default:%d extra:%d(ns)\n",
 			slow_time_ns, default_time_ns, extra_time_ns);
 			slow_time_ns, default_time_ns, extra_time_ns);

+ 1 - 45
msm/sde/sde_hw_util.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
  */
 #define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
 #define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
 
 
@@ -540,47 +540,3 @@ uint32_t sde_copy_formats(
 
 
 	return i;
 	return i;
 }
 }
-
-/**
- * sde_get_linetime   - returns the line time for a given mode
- * @mode:          pointer to drm mode to calculate the line time
- * @src_bpp:       source bpp
- * @target_bpp:    target bpp
- * Return:         line time of display mode in nS
- */
-uint32_t sde_get_linetime(struct drm_display_mode *mode,
-		int src_bpp, int target_bpp)
-{
-	u64 pclk_rate;
-	u32 pclk_period;
-	u32 line_time;
-
-	pclk_rate = mode->clock; /* pixel clock in kHz */
-	if (pclk_rate == 0) {
-		SDE_ERROR("pclk is 0, cannot calculate line time\n");
-		return 0;
-	}
-
-	pclk_period = DIV_ROUND_UP_ULL(1000000000ull, pclk_rate);
-	if (pclk_period == 0) {
-		SDE_ERROR("pclk period is 0\n");
-		return 0;
-	}
-
-	/*
-	 * Line time calculation based on Pixel clock, HTOTAL, and comp_ratio.
-	 * Compression ratio found by src_bpp/target_bpp. Final unit is in ns.
-	 */
-	line_time = pclk_period * mode->htotal;
-	line_time = DIV_ROUND_UP(mult_frac(line_time, target_bpp,
-			src_bpp), 1000);
-	if (line_time == 0) {
-		SDE_ERROR("line time calculation is 0\n");
-		return 0;
-	}
-
-	pr_debug("clk_rate=%lldkHz, clk_period=%d, linetime=%dns, htotal=%d\n",
-			pclk_rate, pclk_period, line_time, mode->htotal);
-
-	return line_time;
-}

+ 1 - 4
msm/sde/sde_hw_util.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
- * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #ifndef _SDE_HW_UTIL_H
 #ifndef _SDE_HW_UTIL_H
@@ -212,9 +212,6 @@ uint32_t sde_copy_formats(
 		const struct sde_format_extended *src_list,
 		const struct sde_format_extended *src_list,
 		uint32_t src_list_size);
 		uint32_t src_list_size);
 
 
-uint32_t sde_get_linetime(struct drm_display_mode *mode,
-		int src_bpp, int target_bpp);
-
 static inline bool is_qseed3_rev_qseed3lite(struct sde_mdss_cfg *sde_cfg)
 static inline bool is_qseed3_rev_qseed3lite(struct sde_mdss_cfg *sde_cfg)
 {
 {
 	return ((sde_cfg->qseed_sw_lib_rev == SDE_SSPP_SCALER_QSEED3LITE) ?
 	return ((sde_cfg->qseed_sw_lib_rev == SDE_SSPP_SCALER_QSEED3LITE) ?

+ 1 - 3
msm/sde/sde_plane.c

@@ -2909,11 +2909,9 @@ static void _sde_plane_setup_uidle(struct drm_crtc *crtc,
 	struct sde_rect *src, struct sde_rect *dst)
 	struct sde_rect *src, struct sde_rect *dst)
 {
 {
 	struct sde_hw_pipe_uidle_cfg cfg;
 	struct sde_hw_pipe_uidle_cfg cfg;
-	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
 	u32 fal1_threshold_max = 15;
 	u32 fal1_threshold_max = 15;
 
 
-	u32 line_time = sde_get_linetime(&crtc->mode,
-			sde_crtc->src_bpp, sde_crtc->target_bpp); /* nS */
+	u32 line_time = sde_crtc_get_line_time(crtc);
 	u32 fal1_target_idle_time_ns =
 	u32 fal1_target_idle_time_ns =
 		psde->catalog->uidle_cfg.fal1_target_idle_time * 1000; /* nS */
 		psde->catalog->uidle_cfg.fal1_target_idle_time * 1000; /* nS */
 	u32 fal10_target_idle_time_ns =
 	u32 fal10_target_idle_time_ns =