xf86-video-intel: 2 commits - src/fix.5c src/i830_display.c src/scripts/clock.5c src/scripts/clock-graph.5c src/scripts/fix.5c src/scripts/tv.5c src/tv.5c

Eric Anholt anholt at kemper.freedesktop.org
Thu Oct 18 11:31:07 PDT 2007


 src/fix.5c                 |   14 ----
 src/i830_display.c         |    8 ++
 src/scripts/clock-graph.5c |  148 +++++++++++++++++++++++++++++++++++++++++++++
 src/scripts/clock.5c       |   40 ++++++++++++
 src/scripts/fix.5c         |   14 ++++
 src/scripts/tv.5c          |  128 ++++++++++++++++++++++++++++++++++++++
 src/tv.5c                  |  128 --------------------------------------
 7 files changed, 338 insertions(+), 142 deletions(-)

New commits:
commit 9f9b888525b274036d301d6e06351583d0415f9e
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 18 11:25:24 2007 -0700

    Warn in the log if we choose a PLL clock that's way out of line.

diff --git a/src/i830_display.c b/src/i830_display.c
index 92e52ed..292814c 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1025,6 +1025,14 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
     if (!ok)
 	FatalError("Couldn't find PLL settings for mode!\n");
 
+    if (fabs(adjusted_mode->Clock - clock.dot) / clock.dot > .02) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Chosen PLL clock of %.1f Mhz more than 2%% away from "
+		   "desired %.1f Mhz\n",
+		   (float)clock.dot / 1000,
+		   (float)adjusted_mode->Clock / 1000);
+    }
+
     fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 
     dpll = DPLL_VGA_MODE_DIS;
commit 1f8bf110394cc1df66aae9acf5c818145ae19b52
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 18 11:17:38 2007 -0700

    Add some nickle scripts for looking at PLL issues.
    
    While here, move similar nickle scripts under src/scripts/

diff --git a/src/fix.5c b/src/fix.5c
deleted file mode 100644
index b758a43..0000000
--- a/src/fix.5c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Convert CSC fix point values to floats
- */
-
-real fixval (int fix)
-{
-    int exp = fix >> 9;
-    int mant = fix & ((1 << 9) - 1);
-    real ret;
-    if (exp == 0x7)
-	return 1.0;
-    ret = (2 ** -exp) * mant / (1 << 9);
-    return ret;
-}
diff --git a/src/scripts/clock-graph.5c b/src/scripts/clock-graph.5c
new file mode 100644
index 0000000..98500e1
--- /dev/null
+++ b/src/scripts/clock-graph.5c
@@ -0,0 +1,148 @@
+autoload Cairo;
+import Cairo;
+library "examples/sort.5c";
+import Sort;
+
+int width = 1000, height = 200;
+
+int min = 0xffffffff;
+int max = 0;
+
+int max_clocks = 1000;
+int[4][max_clocks] clocks;
+int[4] clock_count = {0...};
+
+int[4] p2vals = {5,10,7,14};
+
+cairo_t cr = Cairo::new(width, height);
+
+void calc_p2(int p2i)
+{
+	int p2 = p2vals[p2i];
+	int min_p, max_p;
+
+	clocks[p2i] = (int [max_clocks]){0...};
+
+		if (p2 == 7 || p2 == 14) {
+		/* LVDS */
+		min_p = 7;
+		max_p = 98;
+	} else {
+		/* SDVO/DAC */
+		min_p = 5;
+		max_p = 80;
+	}
+
+	for (int m1 = 10; m1 <= 20; m1++) {
+		for (int m2 = 5; m2 <= 9; m2++) {
+			for (int n = 3; n <= 8; n++) {
+				for (int p1 = 1; p1 <= 8; p1++) {
+					int ref = 96000000;
+					int m = 5 * (m1 + 2) + (m2 + 2);
+					int p = p1 * p2;
+					int vco = floor(ref * m / (n + 2));
+					int clock = floor(vco / p);
+
+					if (p < min_p || p > max_p)
+						continue;
+					if (m < 70 || m > 120)
+						continue;
+					if (m2 > m1)
+						continue; /* won't happen */
+					if (vco < 1400000000 ||
+					    vco > 2800000000)
+						continue;
+
+/*
+					printf("clock: %d (%d,%d), %d, "
+						"(%d,%d)\n",
+						floor(clock / 1000),
+						m1, m2, n, p1, p2);
+*/
+
+					clocks[p2i][clock_count[p2i]] = clock;
+					clock_count[p2i]++;
+				}
+			}
+		}
+	}
+}
+
+bool sort_p2(poly a, poly b)
+{
+	return a > b;
+}
+
+int min_rate = 25000 * 1000;
+int max_rate = 200000 * 1000;
+
+real scale_x(real clock)
+{
+	int min_x = 75, max_x = width - 50;
+
+	real frac = (clock - min_rate) / (max_rate - min_rate);
+
+	return min_x + frac * (max_x - min_x);
+}
+
+for (p2i = 0; p2i < dim(p2vals); p2i++) {
+	int p2 = p2vals[p2i]; 
+	calc_p2(p2i);
+	/*qsort(&p2vals[p2i], sort_p2);*/
+
+	switch (p2) {
+	case 5:
+		set_source_rgb(cr, 1,0,0);
+		break;
+	case 10:
+		set_source_rgb(cr, 0,1,0);
+		break;
+	case 7:
+		set_source_rgb(cr, 0,0,1);
+		break;
+	case 14:
+		set_source_rgb(cr, 0,0,0);
+		break;
+	}
+	for (int i = 0; i < clock_count[p2i]; i++) {
+		int clock = clocks[p2i][i];
+		real xpos;
+
+		if (clock < min_rate || clock > max_rate)
+			continue;
+
+		xpos = scale_x(clock);
+		move_to(cr, xpos, p2i / (dim(p2vals) + 1) * height);
+		line_to(cr, xpos, (p2i + 1) / (dim(p2vals) + 1) * height);
+		stroke(cr);
+	}
+
+	set_source_rgb(cr, 0, 0, 0);
+	string p2label = sprintf("p2 = %d", p2);
+	move_to(cr, 5, (p2i + .5) / (dim(p2vals) + 1) * height + 4);
+	show_text(cr, p2label);
+}
+
+void label_clock(real clock) {
+	real center_x = scale_x(clock);
+	string label = sprintf("%d", floor((clock + 500) / 1000000));
+		text_extents_t e = text_extents(cr, label);
+	real left_x = center_x - e.x_advance / 2;
+	save(cr);
+	move_to(cr, left_x, height - 20);
+	show_text(cr, label);
+	restore(cr);
+}
+
+label_clock(min_rate);
+label_clock(max_rate);
+label_clock(140 * 1000 * 1000);
+label_clock(115 * 1000 * 1000);
+label_clock(100 * 1000 * 1000);
+label_clock(82 * 1000 * 1000);
+
+string xlabel = "Clock in Mhz";
+text_extents_t e = text_extents(cr, xlabel);
+move_to(cr, width / 2 - e.x_advance / 2, height - 5);
+show_text(cr, xlabel);
+sleep(10);
diff --git a/src/scripts/clock.5c b/src/scripts/clock.5c
new file mode 100644
index 0000000..8ee9d90
--- /dev/null
+++ b/src/scripts/clock.5c
@@ -0,0 +1,40 @@
+int p2 = 14;
+int min_p, max_p;
+
+if (p2 == 7 || p2 == 14) {
+	/* LVDS */
+	min_p = 7;
+	max_p = 98;
+} else {
+	/* SDVO/DAC */
+	min_p = 5;
+	max_p = 80;
+}
+
+for (int m1 = 10; m1 <= 20; m1++) {
+	for (int m2 = 5; m2 <= 9; m2++) {
+		for (int n = 3; n <= 8; n++) {
+			for (int p1 = 1; p1 <= 8; p1++) {
+				int ref = 96000000;
+				int m = 5 * (m1 + 2) + (m2 + 2);
+				int p = p1 * p2;
+				int vco = floor(ref * m / (n + 2));
+				int clock = floor(vco / p);
+
+				if (p < min_p || p > max_p)
+					continue;
+				if (m < 70 || m > 120)
+					continue;
+				if (m2 > m1)
+					continue; /* won't happen */
+				if (vco < 1400000000 ||
+				    vco > 2800000000)
+					continue;
+
+				printf("clock: %d (%d,%d),%d,(%d,%d)\n",
+					floor(clock / 1000),
+					m1, m2, n, p1, p2);
+			}
+		}
+	}
+}
diff --git a/src/scripts/fix.5c b/src/scripts/fix.5c
new file mode 100644
index 0000000..b758a43
--- /dev/null
+++ b/src/scripts/fix.5c
@@ -0,0 +1,14 @@
+/*
+ * Convert CSC fix point values to floats
+ */
+
+real fixval (int fix)
+{
+    int exp = fix >> 9;
+    int mant = fix & ((1 << 9) - 1);
+    real ret;
+    if (exp == 0x7)
+	return 1.0;
+    ret = (2 ** -exp) * mant / (1 << 9);
+    return ret;
+}
diff --git a/src/scripts/tv.5c b/src/scripts/tv.5c
new file mode 100644
index 0000000..b4a2ba6
--- /dev/null
+++ b/src/scripts/tv.5c
@@ -0,0 +1,128 @@
+/*
+ * tv.5c
+ *
+ * Compute tv encoder subcarrier dda constants
+ *
+ * The TV encoder subcarrier must be set precisely to the
+ * required frequency or the cumulative phase errors will be
+ * quite visible in the output. To accomplish this, the TV encoder
+ * has a complex circuit that takes a fixed clock, generated by the PLL
+ * and generates a precise subcarrier clock from that using the following
+ * formula:
+ *
+ *  subcarrier = pixel_clock * (S1 + (S2 + (S3/Z3)) / Z2) / 4096
+ *
+ * Careful selection of the constants will provide the necessarily
+ * precise clock.
+ *
+ * In the code below, S1 is represented by dda1, S2/Z2 by dda2 and S3/Z3
+ * by dda3.
+ */
+
+typedef struct {
+    int	step;
+    int	size;
+} term_t;
+
+/*
+ * Find the approximation closest, but no larger than 'v', where
+ * 0 <= v < 1, and the result denominator must be less than 30000.
+ */
+term_t approx (rational v)
+{
+    rational	best_dist = 1.0;
+    term_t	best;
+
+    for (int den = 20000; den < 30000; den++)
+    {
+	int num = floor (v * den);
+	term_t	    approx = { step = num, size = den };
+	rational    dist = v - approx.step/approx.size;
+	if (dist >= 0 && dist < best_dist)
+	{
+	    best_dist = dist;
+	    best = approx;
+	}
+    }
+    return best;
+}
+
+typedef struct {
+    rational	subcarrier;
+    rational	pixel;
+    rational	result;
+    term_t	dda1;
+    term_t	dda2;
+    term_t	dda3;
+} dda;
+
+/*
+ * Compute the dda constants for the given pixel clock and
+ * desired subcarrier frequency
+ */
+
+dda find_dda (rational pixel, rational subcarrier)
+{
+    dda	d;
+
+    d.subcarrier = subcarrier;
+    d.pixel = pixel;
+    
+    rational	dda1 = subcarrier / pixel * 4096;
+    d.dda1 = (term_t) { step = floor (dda1), size = 4096 };
+    
+    rational	dda2 = dda1 - d.dda1.step;
+    d.dda2 = approx (dda2);
+    
+    rational	dda3 = dda2 * d.dda2.size - d.dda2.step;
+    d.dda3 = approx (dda3);
+
+    /* Compute the resulting pixel clock to compare */
+    d.result = d.pixel * (d.dda1.step +
+			  (d.dda2.step + d.dda3.step/d.dda3.size) /
+			  d.dda2.size) / d.dda1.size;
+    return d;
+}
+
+/*
+ * Print out the computed constants
+ */
+void print_dda (dda d)
+{
+    printf ("\t/* desired %9.7f actual %9.7f clock %g */\n",
+	    d.subcarrier, d.result, d.pixel);
+    printf ("\t.dda1_inc\t= %6d,\n", d.dda1.step);
+    printf ("\t.dda2_inc\t= %6d,\t.dda2_size\t= %6d,\n",
+	    d.dda2.step, d.dda2.step != 0 ? d.dda2.size : 0);
+    printf ("\t.dda3_inc\t= %6d,\t.dda3_size\t= %6d,\n",
+	    d.dda3.step, d.dda3.step != 0 ? d.dda3.size : 0);
+}
+
+/*
+ * These are all of the required subcarrier frequencies
+ */
+rational[]    subcarriers = {
+    /* these are the values we use; for some reason, this generates
+     * a more stable image (at least for NTSC) */
+    3.580, 4.434, 3.582, 3.576, 4.430,
+    
+    /* these are the values pulled out of the various specs */
+    3.579545, 4.433618, 3.582056, 3.575611, 4.433618
+};
+
+/*
+ * We fix the pixel clock to a value which the hardware can
+ * generate exactly
+ */
+rational    pixel = 107.520;
+
+void main ()
+{
+    for (int i = 0; i < dim(subcarriers); i++)
+    {
+	dda d = find_dda (pixel, subcarriers[i]);
+	print_dda (d);
+    }
+}
+
+main ();
diff --git a/src/tv.5c b/src/tv.5c
deleted file mode 100644
index b4a2ba6..0000000
--- a/src/tv.5c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * tv.5c
- *
- * Compute tv encoder subcarrier dda constants
- *
- * The TV encoder subcarrier must be set precisely to the
- * required frequency or the cumulative phase errors will be
- * quite visible in the output. To accomplish this, the TV encoder
- * has a complex circuit that takes a fixed clock, generated by the PLL
- * and generates a precise subcarrier clock from that using the following
- * formula:
- *
- *  subcarrier = pixel_clock * (S1 + (S2 + (S3/Z3)) / Z2) / 4096
- *
- * Careful selection of the constants will provide the necessarily
- * precise clock.
- *
- * In the code below, S1 is represented by dda1, S2/Z2 by dda2 and S3/Z3
- * by dda3.
- */
-
-typedef struct {
-    int	step;
-    int	size;
-} term_t;
-
-/*
- * Find the approximation closest, but no larger than 'v', where
- * 0 <= v < 1, and the result denominator must be less than 30000.
- */
-term_t approx (rational v)
-{
-    rational	best_dist = 1.0;
-    term_t	best;
-
-    for (int den = 20000; den < 30000; den++)
-    {
-	int num = floor (v * den);
-	term_t	    approx = { step = num, size = den };
-	rational    dist = v - approx.step/approx.size;
-	if (dist >= 0 && dist < best_dist)
-	{
-	    best_dist = dist;
-	    best = approx;
-	}
-    }
-    return best;
-}
-
-typedef struct {
-    rational	subcarrier;
-    rational	pixel;
-    rational	result;
-    term_t	dda1;
-    term_t	dda2;
-    term_t	dda3;
-} dda;
-
-/*
- * Compute the dda constants for the given pixel clock and
- * desired subcarrier frequency
- */
-
-dda find_dda (rational pixel, rational subcarrier)
-{
-    dda	d;
-
-    d.subcarrier = subcarrier;
-    d.pixel = pixel;
-    
-    rational	dda1 = subcarrier / pixel * 4096;
-    d.dda1 = (term_t) { step = floor (dda1), size = 4096 };
-    
-    rational	dda2 = dda1 - d.dda1.step;
-    d.dda2 = approx (dda2);
-    
-    rational	dda3 = dda2 * d.dda2.size - d.dda2.step;
-    d.dda3 = approx (dda3);
-
-    /* Compute the resulting pixel clock to compare */
-    d.result = d.pixel * (d.dda1.step +
-			  (d.dda2.step + d.dda3.step/d.dda3.size) /
-			  d.dda2.size) / d.dda1.size;
-    return d;
-}
-
-/*
- * Print out the computed constants
- */
-void print_dda (dda d)
-{
-    printf ("\t/* desired %9.7f actual %9.7f clock %g */\n",
-	    d.subcarrier, d.result, d.pixel);
-    printf ("\t.dda1_inc\t= %6d,\n", d.dda1.step);
-    printf ("\t.dda2_inc\t= %6d,\t.dda2_size\t= %6d,\n",
-	    d.dda2.step, d.dda2.step != 0 ? d.dda2.size : 0);
-    printf ("\t.dda3_inc\t= %6d,\t.dda3_size\t= %6d,\n",
-	    d.dda3.step, d.dda3.step != 0 ? d.dda3.size : 0);
-}
-
-/*
- * These are all of the required subcarrier frequencies
- */
-rational[]    subcarriers = {
-    /* these are the values we use; for some reason, this generates
-     * a more stable image (at least for NTSC) */
-    3.580, 4.434, 3.582, 3.576, 4.430,
-    
-    /* these are the values pulled out of the various specs */
-    3.579545, 4.433618, 3.582056, 3.575611, 4.433618
-};
-
-/*
- * We fix the pixel clock to a value which the hardware can
- * generate exactly
- */
-rational    pixel = 107.520;
-
-void main ()
-{
-    for (int i = 0; i < dim(subcarriers); i++)
-    {
-	dda d = find_dda (pixel, subcarriers[i]);
-	print_dda (d);
-    }
-}
-
-main ();


More information about the xorg-commit mailing list