Pi Firmware: Added pllh control (623-627 lines)

Change-Id: If1efa170a547aa2afbc5a2e108331b2f479f4092
soft_delitch
David Banks 2018-07-23 14:19:29 +01:00
rodzic fad4c55e76
commit ee07893a3d
4 zmienionych plików z 97 dodań i 48 usunięć

Wyświetl plik

@ -84,6 +84,15 @@ static const char *machine_names[] = {
"Elk"
};
static const char *pllh_names[] = {
"Original",
"623",
"624",
"625",
"626",
"627",
};
// =============================================================
// Feature definitions for OSD
// =============================================================
@ -95,6 +104,7 @@ enum {
F_MUX,
F_ELK,
F_VSYNC,
F_PLLH,
F_DEBUG
};
@ -105,6 +115,7 @@ static param_t features[] = {
{ "Input Mux", 0, 1 },
{ "Elk", 0, 1 },
{ "Vsync", 0, 1 },
{ "PLLH", 0, 5 },
{ "Debug", 0, 1 },
{ NULL, 0, 0 },
};
@ -234,7 +245,7 @@ static int get_feature(int num) {
return info;
case F_PALETTE:
return palette;
case F_SCANLINES:
case F_SCANLINES:
return scanlines;
case F_MUX:
return mux;
@ -242,6 +253,8 @@ static int get_feature(int num) {
return get_elk();
case F_VSYNC:
return get_vsync();
case F_PLLH:
return get_pllh();
case F_DEBUG:
return debug;
}
@ -271,6 +284,9 @@ static void set_feature(int num, int value) {
case F_VSYNC:
set_vsync(value);
break;
case F_PLLH:
set_pllh(value);
break;
case F_DEBUG:
debug = value;
update_palette();
@ -286,6 +302,7 @@ static void show_feature(int num) {
const char *valstr =
(num == F_INFO) ? info_names[value] :
(num == F_PALETTE) ? palette_names[value] :
(num == F_PLLH) ? pllh_names[value] :
value ? "On" : "Off";
// Clear lines 2 onwards
memset(buffer + 2 * LINELEN, 0, (NLINES - 2) * LINELEN);
@ -535,6 +552,12 @@ void osd_init() {
set_feature(F_ELK, val);
log_info("config.txt: elk = %d", val);
}
prop = get_cmdline_prop("pllh");
if (prop) {
int val = atoi(prop);
set_feature(F_PLLH, val);
log_info("config.txt: pllh = %d", val);
}
prop = get_cmdline_prop("vsync");
if (prop) {
int val = atoi(prop);

Wyświetl plik

@ -26,5 +26,7 @@ void set_elk(int on);
int get_elk();
void set_vsync(int on);
int get_vsync();
void set_pllh(int mode);
int get_pllh();
#endif

Wyświetl plik

@ -51,6 +51,8 @@ static int height = 0;
static uint32_t cpld_version_id;
static volatile int delay;
static int vsync;
static int pllh;
static double pllh_clock = 0;
static int elk;
static int mode7;
static int clear;
@ -328,57 +330,14 @@ static int calibrate_clock() {
gpioreg[PLLH_STS]);
// Dump the original PLLH frequency
double f1 = 19.2 * ((double)(gpioreg[PLLH_CTRL] & 0x3ff) + ((double)gpioreg[PLLH_FRAC]) / ((double)(1 << 20)));
log_info("Original PLLH: %lf MHz", f1);
pllh_clock = 19.2 * ((double)(gpioreg[PLLH_CTRL] & 0x3ff) + ((double)gpioreg[PLLH_FRAC]) / ((double)(1 << 20)));
// Correct for the Beeb's clock
double f2 = f1 / error;
// Correct for non-interlaced mode
if (!(frame_time & INTERLACED_FLAG)) {
f2 *= 626.0 / 624.0;
}
// Dump the target PLL frequency
log_info(" Target PLLH: %lf MHz", f2);
// Calculate the new fraction
double div = gpioreg[PLLH_CTRL] & 0x3ff;
int fract = (int) ((double)(1<<20) * (f2 / 19.2 - div));
if (fract < 0) {
log_warn("PLLH fraction < 0");
fract = 0;
}
if (fract > (1<<20) - 1) {
log_warn("PLLH fraction > 1");
fract = (1<<20) - 1;
}
// Update the PLL
int old_fract = gpioreg[PLLH_FRAC];
gpioreg[PLLH_FRAC] = 0x5A000000 | fract;
int new_fract = gpioreg[PLLH_FRAC];
log_info("Old fract = %d (when read back)", old_fract);
log_info("New fract = %d", fract);
log_info("New fract = %d (when read back)", new_fract);
log_info("PLLH: PDIV=%d NDIV=%d FRAC=%d AUX=%d RCAL=%d PIX=%d STS=%d",
(gpioreg[PLLH_CTRL] >> 12) & 0x7,
gpioreg[PLLH_CTRL] & 0x3ff,
gpioreg[PLLH_FRAC],
gpioreg[PLLH_AUX],
gpioreg[PLLH_RCAL],
gpioreg[PLLH_PIX],
gpioreg[PLLH_STS]);
// Dump the the actual PLL frequency
double f3 = 19.2 * ((double)(gpioreg[PLLH_CTRL] & 0x3ff) + ((double)gpioreg[PLLH_FRAC]) / ((double)(1 << 20)));
log_info(" Actual PLLH: %lf MHz", f3);
log_info("Original PLLH: %lf MHz", pllh_clock);
return a;
}
static void init_hardware() {
int i;
for (i = 0; i < 12; i++) {
@ -768,6 +727,63 @@ int get_vsync() {
return vsync;
}
int get_pllh() {
return pllh;
}
void set_pllh(int mode) {
pllh = mode;
double error = 1.0 + (clock_error_ppm / 1e6);
double f2 = pllh_clock;
if (mode > 0) {
// Correct for clock error
f2 /= error;
// Correct for specified number of lines (mode 1..5)
f2 *= 625.0 / (622.0 + mode);
}
// Dump the target PLL frequency
log_info(" Target PLLH: %lf MHz", f2);
// Calculate the new fraction
double div = gpioreg[PLLH_CTRL] & 0x3ff;
int fract = (int) ((double)(1<<20) * (f2 / 19.2 - div));
if (fract < 0) {
log_warn("PLLH fraction < 0");
fract = 0;
}
if (fract > (1<<20) - 1) {
log_warn("PLLH fraction > 1");
fract = (1<<20) - 1;
}
// Update the PLL
int old_fract = gpioreg[PLLH_FRAC];
gpioreg[PLLH_FRAC] = 0x5A000000 | fract;
int new_fract = gpioreg[PLLH_FRAC];
log_info("Old fract = %d (when read back)", old_fract);
log_info("New fract = %d", fract);
log_info("New fract = %d (when read back)", new_fract);
log_info("PLLH: PDIV=%d NDIV=%d FRAC=%d AUX=%d RCAL=%d PIX=%d STS=%d",
(gpioreg[PLLH_CTRL] >> 12) & 0x7,
gpioreg[PLLH_CTRL] & 0x3ff,
gpioreg[PLLH_FRAC],
gpioreg[PLLH_AUX],
gpioreg[PLLH_RCAL],
gpioreg[PLLH_PIX],
gpioreg[PLLH_STS]);
// Dump the the actual PLL frequency
double f3 = 19.2 * ((double)(gpioreg[PLLH_CTRL] & 0x3ff) + ((double)gpioreg[PLLH_FRAC]) / ((double)(1 << 20)));
log_info(" Actual PLLH: %lf MHz", f3);
}
void action_scanlines(int on) {
if (on) {
scanlines = BIT_SCANLINES;

Wyświetl plik

@ -58,10 +58,18 @@
# - 0 is vsync off
# - 1 is vsync on
#
# pllh: controls the HDMI clock correction mode
# - 0 is no correction
# - 1 is correct for 623 lines
# - 2 is correct for 623 lines
# - 3 is correct for 625 lines
# - 4 is correct for 626 lines
# - 5 is correct for 627 lines
#
# debug: enables debug mode
# - 0 is debug off
# - 1 is debug on
#
# Important: All the properties must be on a single line, and no blank lines!
#
sampling06=3 sampling7=0,2,2,2,2,2,2,0 info=1 palette=0 scanlines=0 mux=0 elk=0 vsync=0 debug=0
sampling06=3 sampling7=0,2,2,2,2,2,2,0 info=1 palette=0 scanlines=0 mux=0 elk=0 vsync=0 pllh=0 debug=0