diff mbox series

[09/12] drm/mgag200: Split PLL computation for G200SE

Message ID 20210705124515.27253-10-tzimmermann@suse.de (mailing list archive)
State New, archived
Headers show
Series mgag200: Refactor PLL setup | expand

Commit Message

Thomas Zimmermann July 5, 2021, 12:45 p.m. UTC
The compute function for G200SE pixle PLLs handles two revisions with
different algorithms. Split it accordingly to make it readable.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/mgag200/mgag200_mode.c | 165 +++++++++++++++----------
 1 file changed, 97 insertions(+), 68 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 72fdf242cac7..99b35e4f9353 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -184,100 +184,118 @@  static int mgag200_compute_pixpll_values_g200(struct mga_device *mdev, long cloc
 	return 0;
 }
 
-static int mgag200_compute_pixpll_values_g200se(struct mga_device *mdev, long clock,
-						struct mgag200_pll_values *pixpllc)
+static int mgag200_compute_pixpll_values_g200se_00(struct mga_device *mdev, long clock,
+						   struct mgag200_pll_values *pixpllc)
 {
-	static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
-
-	u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
 	unsigned int vcomax, vcomin, pllreffreq;
 	unsigned int delta, tmpdelta, permitteddelta;
 	unsigned int testp, testm, testn;
 	unsigned int p, m, n, s;
 	unsigned int computed;
-	unsigned int fvv;
-	unsigned int i;
 
 	m = n = p = s = 0;
 	delta = 0xffffffff;
 
-	if (unique_rev_id <= 0x03) {
-		vcomax = 320000;
-		vcomin = 160000;
-		pllreffreq = 25000;
-		permitteddelta = clock * 5 / 1000;
+	vcomax = 320000;
+	vcomin = 160000;
+	pllreffreq = 25000;
+	permitteddelta = clock * 5 / 1000;
 
-		for (testp = 8; testp > 0; testp /= 2) {
-			if (clock * testp > vcomax)
-				continue;
-			if (clock * testp < vcomin)
-				continue;
+	for (testp = 8; testp > 0; testp /= 2) {
+		if (clock * testp > vcomax)
+			continue;
+		if (clock * testp < vcomin)
+			continue;
 
-			for (testn = 17; testn < 256; testn++) {
-				for (testm = 1; testm < 32; testm++) {
-					computed = (pllreffreq * testn) /
-						(testm * testp);
-					if (computed > clock)
-						tmpdelta = computed - clock;
-					else
-						tmpdelta = clock - computed;
-					if (tmpdelta < delta) {
-						delta = tmpdelta;
-						m = testm;
-						n = testn;
-						p = testp;
-					}
+		for (testn = 17; testn < 256; testn++) {
+			for (testm = 1; testm < 32; testm++) {
+				computed = (pllreffreq * testn) / (testm * testp);
+				if (computed > clock)
+					tmpdelta = computed - clock;
+				else
+					tmpdelta = clock - computed;
+				if (tmpdelta < delta) {
+					delta = tmpdelta;
+					m = testm;
+					n = testn;
+					p = testp;
 				}
 			}
 		}
-	} else {
-		vcomax        = 1600000;
-		vcomin        = 800000;
-		pllreffreq    = 25000;
+	}
 
-		if (clock < 25000)
-			clock = 25000;
-		clock = clock * 2;
+	if (delta > permitteddelta) {
+		pr_warn("PLL delta too large\n");
+		return -EINVAL;
+	}
 
-		/* Permited delta is 0.5% as VESA Specification */
-		permitteddelta = clock * 5 / 1000;
+	pixpllc->m = m;
+	pixpllc->n = n;
+	pixpllc->p = p;
+	pixpllc->s = s;
 
-		for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
-			testp = pvalues_e4[i];
+	return 0;
+}
 
-			if ((clock * testp) > vcomax)
-				continue;
-			if ((clock * testp) < vcomin)
-				continue;
+static int mgag200_compute_pixpll_values_g200se_04(struct mga_device *mdev, long clock,
+						   struct mgag200_pll_values *pixpllc)
+{
+	static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
 
-			for (testn = 50; testn <= 256; testn++) {
-				for (testm = 1; testm <= 32; testm++) {
-					computed = (pllreffreq * testn) /
-						(testm * testp);
-					if (computed > clock)
-						tmpdelta = computed - clock;
-					else
-						tmpdelta = clock - computed;
+	unsigned int vcomax, vcomin, pllreffreq;
+	unsigned int delta, tmpdelta, permitteddelta;
+	unsigned int testp, testm, testn;
+	unsigned int p, m, n, s;
+	unsigned int computed;
+	unsigned int fvv;
+	unsigned int i;
 
-					if (tmpdelta < delta) {
-						delta = tmpdelta;
-						m = testm;
-						n = testn;
-						p = testp;
-					}
+	m = n = p = s = 0;
+	delta = 0xffffffff;
+
+	vcomax        = 1600000;
+	vcomin        = 800000;
+	pllreffreq    = 25000;
+
+	if (clock < 25000)
+		clock = 25000;
+	clock = clock * 2;
+
+	/* Permited delta is 0.5% as VESA Specification */
+	permitteddelta = clock * 5 / 1000;
+
+	for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
+		testp = pvalues_e4[i];
+
+		if ((clock * testp) > vcomax)
+			continue;
+		if ((clock * testp) < vcomin)
+			continue;
+
+		for (testn = 50; testn <= 256; testn++) {
+			for (testm = 1; testm <= 32; testm++) {
+				computed = (pllreffreq * testn) / (testm * testp);
+				if (computed > clock)
+					tmpdelta = computed - clock;
+				else
+					tmpdelta = clock - computed;
+
+				if (tmpdelta < delta) {
+					delta = tmpdelta;
+					m = testm;
+					n = testn;
+					p = testp;
 				}
 			}
 		}
-
-		fvv = pllreffreq * n / m;
-		fvv = (fvv - 800000) / 50000;
-		if (fvv > 15)
-			fvv = 15;
-		s = fvv << 1;
-
-		clock = clock / 2;
 	}
 
+	fvv = pllreffreq * n / m;
+	fvv = (fvv - 800000) / 50000;
+	if (fvv > 15)
+		fvv = 15;
+	s = fvv << 1;
+
 	if (delta > permitteddelta) {
 		pr_warn("PLL delta too large\n");
 		return -EINVAL;
@@ -291,6 +309,17 @@  static int mgag200_compute_pixpll_values_g200se(struct mga_device *mdev, long cl
 	return 0;
 }
 
+static int mgag200_compute_pixpll_values_g200se(struct mga_device *mdev, long clock,
+						struct mgag200_pll_values *pixpllc)
+{
+	u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
+
+	if (unique_rev_id >= 0x04)
+		return mgag200_compute_pixpll_values_g200se_04(mdev, clock, pixpllc);
+	else
+		return mgag200_compute_pixpll_values_g200se_00(mdev, clock, pixpllc);
+}
+
 static int mgag200_compute_pixpll_values_g200wb(struct mga_device *mdev, long clock,
 						struct mgag200_pll_values *pixpllc)
 {