mirror of
https://github.com/X11Libre/xf86-video-intel.git
synced 2026-04-14 10:54:23 +00:00
Add some nickle scripts for looking at PLL issues.
While here, move similar nickle scripts under src/scripts/
This commit is contained in:
148
src/scripts/clock-graph.5c
Normal file
148
src/scripts/clock-graph.5c
Normal file
@@ -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);
|
||||
40
src/scripts/clock.5c
Normal file
40
src/scripts/clock.5c
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/scripts/fix.5c
Normal file
14
src/scripts/fix.5c
Normal file
@@ -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;
|
||||
}
|
||||
128
src/scripts/tv.5c
Normal file
128
src/scripts/tv.5c
Normal file
@@ -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 ();
|
||||
Reference in New Issue
Block a user