[coreboot-gerrit] Change in coreboot[master]: rockchip/rk3399: mipi: correct Feedback divider setting

Lin Huang (Code Review) gerrit at coreboot.org
Wed Nov 15 04:28:16 CET 2017


Lin Huang has uploaded this change for review. ( https://review.coreboot.org/22468


Change subject: rockchip/rk3399: mipi: correct Feedback divider setting
......................................................................

rockchip/rk3399: mipi: correct Feedback divider setting

This patch correct Feedback divider setting:
1. Set Feedback divider [8:5] when HIGH_PROGRAM_EN
2. Due to the use of a "by 2 pre-scaler," the range of the
   feedback multiplication Feedback divider is limited to even
   division numbers, and Feedback divider must be greater than
   12, less than 1000.
3. Make the previously configured Feedback divider(LSB)
   factors effective

Change-Id: Ic7c5c59be1d00c65c3b17cb3c4bfba8d7459e960
Signed-off-by: Lin Huang <hl at rock-chips.com>
---
M src/soc/rockchip/rk3399/include/soc/mipi.h
M src/soc/rockchip/rk3399/mipi.c
2 files changed, 68 insertions(+), 23 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/68/22468/1

diff --git a/src/soc/rockchip/rk3399/include/soc/mipi.h b/src/soc/rockchip/rk3399/include/soc/mipi.h
index 7dc6b14..d716717 100644
--- a/src/soc/rockchip/rk3399/include/soc/mipi.h
+++ b/src/soc/rockchip/rk3399/include/soc/mipi.h
@@ -209,7 +209,7 @@
 #define LOW_PROGRAM_EN		0
 #define HIGH_PROGRAM_EN		BIT(7)
 #define LOOP_DIV_LOW_SEL(val)	((val - 1) & 0x1f)
-#define LOOP_DIV_HIGH_SEL(val)	(((val - 1) >> 5) & 0x1f)
+#define LOOP_DIV_HIGH_SEL(val)	(((val - 1) >> 5) & 0xf)
 #define PLL_LOOP_DIV_EN		BIT(5)
 #define PLL_INPUT_DIV_EN	BIT(4)
 
diff --git a/src/soc/rockchip/rk3399/mipi.c b/src/soc/rockchip/rk3399/mipi.c
index 1f07491..12e6608 100644
--- a/src/soc/rockchip/rk3399/mipi.c
+++ b/src/soc/rockchip/rk3399/mipi.c
@@ -162,6 +162,15 @@
 	rk_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
 			      LOOP_DIV_LOW_SEL(dsi->feedback_div) |
 			      LOW_PROGRAM_EN);
+
+	/*
+	 * we need set divider control register immediately to make
+	 * the configrued LSB effective according to IP simulation
+	 * and lab test results. Only in this way can we get correct
+	 * mipi phy pll frequency.
+	 */
+	rk_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL,
+			      PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
 	rk_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
 			      LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
 			      HIGH_PROGRAM_EN);
@@ -209,11 +218,15 @@
 static int rk_mipi_dsi_get_lane_bps(struct rk_mipi_dsi *dsi,
 				    const struct edid *edid)
 {
-	u32 i, pre;
-	u64 pclk, pllref, tmp, target_bps;
-	u32 m = 1, n = 1;
+	u64 pclk, target_bps;
 	u32 max_bps = dppa_map[ARRAY_SIZE(dppa_map) - 1].max_mbps * MHz;
 	int bpp;
+	u64 best_freq = 0;
+	u64 fvco_min, fvco_max, fref;
+	u32 min_prediv, max_prediv;
+	u32 prediv, best_prediv;
+	u64 fbdiv, best_fbdiv;
+	u32 min_delta;
 
 	bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
 	if (bpp < 0) {
@@ -222,32 +235,64 @@
 		return bpp;
 	}
 	pclk = edid->mode.pixel_clock * MSECS_PER_SEC;
+
 	/* take 1 / 0.8, since mbps must bigger than bandwidth of RGB */
 	target_bps = pclk / dsi->lanes * bpp / 8 * 10;
 	if (target_bps >= max_bps) {
 		printk(BIOS_DEBUG, "DPHY clock frequency is out of range\n");
 		return -1;
 	}
-	pllref = OSC_HZ;
-	tmp = pllref;
-	/*
-	 * The limits on the PLL divisor are:
-	 *
-	 *	5MHz <= (pllref / n) <= 40MHz
-	 */
-	for (i = pllref / (5 * MHz); i > div_round_up(pllref, 40 * MHz); i--) {
-		pre = pllref / i;
-		if ((tmp > (target_bps % pre)) && (target_bps / pre < 512)) {
-			tmp = target_bps % pre;
-			n = i;
-			m = target_bps / pre;
-		}
-		if (tmp == 0)
-			break;
+
+	fref = OSC_HZ;
+
+	/* constraint: 5Mhz <= Fref / N <= 40MHz */
+	min_prediv = div_round_up(fref, 40 * MHz);
+	max_prediv = fref / (5 * MHz);
+
+	/* constraint: 80MHz <= Fvco <= 1500Mhz */
+	fvco_min = 80 * MHz;
+	fvco_max = 1500 * MHz;
+	min_delta = 1500 * MHz;
+
+	for (prediv = min_prediv; prediv <= max_prediv; prediv++) {
+		u64 freq;
+		int delta;
+
+		/* Fvco = Fref * M / N */
+		fbdiv = target_bps * prediv / fref;
+
+		/*
+		 * Due to the use of a "by 2 pre-scaler", the range of the
+		 * feedback multiplication value M is limited to even division
+		 * numbers, and m must be greater than 12, less than 1000.
+		 */
+		fbdiv += fbdiv % 2;
+		if (fbdiv <= 12 || fbdiv >= 1000)
+			continue;
+
+		freq = (u64)fbdiv * fref / prediv;
+		if (freq < fvco_min || freq > fvco_max)
+			continue;
+
+		delta = target_bps - freq;
+		delta = ABS(delta);
+		if (delta >= min_delta)
+			continue;
+
+		best_prediv = prediv;
+		best_fbdiv = fbdiv;
+		min_delta = delta;
+		best_freq = freq;
 	}
-	dsi->lane_bps = pllref / n * m;
-	dsi->input_div = n;
-	dsi->feedback_div = m;
+
+	if (best_freq) {
+		dsi->lane_bps = best_freq;
+		dsi->input_div = best_prediv;
+		dsi->feedback_div = best_fbdiv;
+	} else {
+		printk(BIOS_ERR, "Can not find best_freq for DPHY\n");
+		return -1;
+	}
 
 	return 0;
 }

-- 
To view, visit https://review.coreboot.org/22468
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic7c5c59be1d00c65c3b17cb3c4bfba8d7459e960
Gerrit-Change-Number: 22468
Gerrit-PatchSet: 1
Gerrit-Owner: Lin Huang <hl at rock-chips.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20171115/0c076628/attachment-0001.html>


More information about the coreboot-gerrit mailing list