Forráskód Böngészése

disp: msm: sde: fix mixer count calculation for 4LM topologies

Currently mixer calculation does not take the number of LMs into
consideration when it is greater than 2. This changes adjusts mixer
count for 4LM use cases based on maximum clock and pipe width.

Change-Id: I05631dee3beadaa0d50548282a539835bcb548c0
Signed-off-by: Amine Najahi <[email protected]>
Amine Najahi 5 éve
szülő
commit
c9eb6c1102
1 módosított fájl, 48 hozzáadás és 22 törlés
  1. 48 22
      msm/sde/sde_kms.c

+ 48 - 22
msm/sde/sde_kms.c

@@ -2413,17 +2413,23 @@ static int sde_kms_get_mixer_count(const struct msm_kms *kms,
 	struct sde_kms *sde_kms;
 	s64 mode_clock_hz = 0;
 	s64 max_mdp_clock_hz = 0;
-	s64 mdp_fudge_factor = 0;
-	s64 temp = 0;
+	s64 max_lm_width = 0;
+	s64 hdisplay_fp = 0;
 	s64 htotal_fp = 0;
 	s64 vtotal_fp = 0;
 	s64 vrefresh_fp = 0;
+	s64 mdp_fudge_factor = 0;
+	s64 num_lm_fp = 0;
+	s64 lm_clk_fp = 0;
+	s64 lm_width_fp = 0;
+	int rc = 0;
 
 	if (!num_lm) {
 		SDE_ERROR("invalid num_lm pointer\n");
 		return -EINVAL;
 	}
 
+	/* default to 1 layer mixer */
 	*num_lm = 1;
 	if (!kms || !mode || !res) {
 		SDE_ERROR("invalid input args\n");
@@ -2432,31 +2438,51 @@ static int sde_kms_get_mixer_count(const struct msm_kms *kms,
 
 	sde_kms = to_sde_kms(kms);
 
-	max_mdp_clock_hz = drm_fixp_from_fraction(
-			sde_kms->perf.max_core_clk_rate, 1);
-	mdp_fudge_factor = drm_fixp_from_fraction(105, 100); /* 1.05 */
-	htotal_fp = drm_fixp_from_fraction(mode->htotal, 1);
-	vtotal_fp = drm_fixp_from_fraction(mode->vtotal, 1);
-	vrefresh_fp = drm_fixp_from_fraction(mode->vrefresh, 1);
+	max_mdp_clock_hz = drm_int2fixp(sde_kms->perf.max_core_clk_rate);
+	max_lm_width = drm_int2fixp(res->max_mixer_width);
+	hdisplay_fp = drm_int2fixp(mode->hdisplay);
+	htotal_fp = drm_int2fixp(mode->htotal);
+	vtotal_fp = drm_int2fixp(mode->vtotal);
+	vrefresh_fp = drm_int2fixp(mode->vrefresh);
+	mdp_fudge_factor = drm_fixp_from_fraction(105, 100);
+
+	/* mode clock = [(h * v * fps * 1.05) / (num_lm)] */
+	mode_clock_hz = drm_fixp_mul(htotal_fp, vtotal_fp);
+	mode_clock_hz = drm_fixp_mul(mode_clock_hz, vrefresh_fp);
+	mode_clock_hz = drm_fixp_mul(mode_clock_hz, mdp_fudge_factor);
 
-	temp = drm_fixp_mul(htotal_fp, vtotal_fp);
-	temp = drm_fixp_mul(temp, vrefresh_fp);
-	mode_clock_hz = drm_fixp_mul(temp, mdp_fudge_factor);
 	if (mode_clock_hz > max_mdp_clock_hz ||
-			mode->hdisplay > res->max_mixer_width) {
-		*num_lm = 2;
-		if ((mode_clock_hz >> 1) > max_mdp_clock_hz) {
-			SDE_DEBUG("[%s] clock %d exceeds max_mdp_clk %d\n",
-					mode->name, mode_clock_hz,
-					max_mdp_clock_hz);
-			return -EINVAL;
-		}
+			hdisplay_fp > max_lm_width) {
+		*num_lm = 0;
+		do {
+			*num_lm += 2;
+			num_lm_fp = drm_int2fixp(*num_lm);
+			lm_clk_fp = drm_fixp_div(mode_clock_hz, num_lm_fp);
+			lm_width_fp = drm_fixp_div(hdisplay_fp, num_lm_fp);
+
+			if (*num_lm > 4) {
+				rc = -EINVAL;
+				goto error;
+			}
+
+		} while (lm_clk_fp > max_mdp_clock_hz ||
+				lm_width_fp > max_lm_width);
+
+		mode_clock_hz = lm_clk_fp;
 	}
-	SDE_DEBUG("[%s] h=%d, v=%d, fps=%d, max_mdp_clk_hz=%llu, num_lm=%d\n",
+	SDE_DEBUG("[%s] h=%d v=%d fps=%d lm=%d mode_clk=%llu max_clk=%llu\n",
 			mode->name, mode->htotal, mode->vtotal, mode->vrefresh,
-			sde_kms->perf.max_core_clk_rate, *num_lm);
-
+			*num_lm, drm_fixp2int(mode_clock_hz),
+			sde_kms->perf.max_core_clk_rate);
 	return 0;
+
+error:
+	SDE_ERROR("required mode clk exceeds max mdp clk\n");
+	SDE_ERROR("[%s] h=%d v=%d fps=%d lm=%d mode_clk=%llu max_clk=%llu\n",
+			mode->name, mode->htotal, mode->vtotal, mode->vrefresh,
+			*num_lm, drm_fixp2int(mode_clock_hz),
+			sde_kms->perf.max_core_clk_rate);
+	return rc;
 }
 
 static void _sde_kms_null_commit(struct drm_device *dev,