aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2021-04-20 10:04:09 +0200
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2021-04-20 10:04:09 +0200
commite908154d87394de9e84e900162a3035e6c398fb2 (patch)
treee3b21e6c7d1505a429744bde563a686c16ff2a71
parent4b7d16dc41fee40989911a8274fd071eccd7fb89 (diff)
edid-decode: add support for CVT RBv3
This new CVT 1.2 reduced blanking formula was published in the CVT 1.2 Errata E1 and is used by CTA-861 and DisplayID 2.0. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r--calc-gtf-cvt.cpp27
-rw-r--r--edid-decode.17
-rw-r--r--edid-decode.cpp16
-rw-r--r--edid-decode.h3
4 files changed, 38 insertions, 15 deletions
diff --git a/calc-gtf-cvt.cpp b/calc-gtf-cvt.cpp
index 78c64c3..bc32ea0 100644
--- a/calc-gtf-cvt.cpp
+++ b/calc-gtf-cvt.cpp
@@ -126,12 +126,9 @@ void edid_state::edid_gtf_mode(unsigned refresh, struct timings &t)
// If rb == RB_CVT_V2, then alt means video-optimized (i.e. 59.94 instead of 60 Hz, etc.).
// If rb == RB_CVT_V3, then alt means that rb_h_blank is 160 instead of 80.
-// Note: for RB_CVT_V3 this calculation is slightly different, but
-// since CVT 1.3 is not yet public, I cannot update the calculation yet. For now
-// it will follow V2. So RBv3 timings will be off for now.
timings edid_state::calc_cvt_mode(unsigned h_pixels, unsigned v_lines,
double ip_freq_rqd, unsigned rb, bool int_rqd,
- bool margins_rqd, bool alt)
+ bool margins_rqd, bool alt, unsigned rb_h_blank)
{
timings t = {};
@@ -159,6 +156,14 @@ timings edid_state::calc_cvt_mode(unsigned h_pixels, unsigned v_lines,
double v_blank;
double v_sync_bp;
+ if (rb == RB_CVT_V3 && rb_h_blank) {
+ h_blank = rb_h_blank & ~7;
+ if (h_blank < 80)
+ h_blank = 80;
+ else if (h_blank > 200)
+ h_blank = 200;
+ }
+
/* Determine VSync Width from aspect ratio */
if ((t.vact * 4 / 3) == t.hact)
v_sync = 4;
@@ -204,8 +209,11 @@ timings edid_state::calc_cvt_mode(unsigned h_pixels, unsigned v_lines,
else
v_sync_bp = v_sync + CVT_MIN_V_BPORCH;
double total_pixels = h_blank + total_active_pixels;
- pixel_freq = floor((v_field_rate_rqd * total_v_lines * total_pixels / 1000000.0 *
- refresh_multiplier) / clock_step) * clock_step;
+ double freq = v_field_rate_rqd * total_v_lines * total_pixels * refresh_multiplier;
+ if (rb == RB_CVT_V3)
+ pixel_freq = ceil((freq / 1000000.0) / clock_step) * clock_step;
+ else
+ pixel_freq = floor((freq / 1000000.0) / clock_step) * clock_step;
}
t.vbp = v_sync_bp - v_sync;
@@ -213,8 +221,11 @@ timings edid_state::calc_cvt_mode(unsigned h_pixels, unsigned v_lines,
t.vfp = v_blank - t.vbp - t.vsync;
t.pixclk_khz = round(1000.0 * pixel_freq);
t.hsync = h_sync;
- t.hfp = (h_blank / 2.0) - t.hsync;
- t.hbp = t.hfp + t.hsync;
+ if (rb == RB_CVT_V3)
+ t.hfp = 8;
+ else
+ t.hfp = (h_blank / 2.0) - t.hsync;
+ t.hbp = h_blank - t.hfp - t.hsync;
t.hborder = hor_margin;
t.vborder = vert_margin;
t.rb = rb;
diff --git a/edid-decode.1 b/edid-decode.1
index e87570f..ecd7fe3 100644
--- a/edid-decode.1
+++ b/edid-decode.1
@@ -148,6 +148,8 @@ DMT 1.3: VESA and Industry Standards and Guidelines for Computer Display Monitor
.TP
CVT 1.2: VESA Coordinated Video Timings (CVT) Standard, Version 1.2
.TP
+CVT 1.2: VESA CVT v1.2 Errata E1
+.TP
GTF 1.1: VESA Generalized Timing Formula Standard, Version: 1.1
.RE
@@ -253,7 +255,7 @@ Show the timings for this VIC.
\fB\-\-hdmi\-vic\fR \fI<hdmivic>\fR
Show the timings for this HDMI VIC.
.TP
-\fB\-\-cvt\fR \fBw\fR=\fI<width>\fR,\fBh\fR=\fI<height>\fR,\fBfps\fR=\fI<fps>\fR[,\fBrb\fR=\fI<rb>\fR][,\fBinterlaced\fR][,\fBoverscan\fR][,\fBalt\fR]
+\fB\-\-cvt\fR \fBw\fR=\fI<width>\fR,\fBh\fR=\fI<height>\fR,\fBfps\fR=\fI<fps>\fR[,\fBrb\fR=\fI<rb>\fR][,\fBinterlaced\fR][,\fBoverscan\fR][,\fBalt\fR][,\fBhblank\fR=\fI<hblank>\fR]
.br
Calculate the CVT timings for the given format.
@@ -272,6 +274,9 @@ optimized for video: 1000 / 1001 * \fI<fps>\fR.
.br
If \fBalt\fR is given and \fI<rb>\fR=3, then the horizontal blanking
is 160 instead of 80 pixels.
+.br
+If \fBhblank\fR is given and \fI<rb>\fR=3, then the horizontal blanking
+is \fI<hblank>\fR pixels (range of 80-200 and divisible by 8), overriding \fBalt\fR.
.TP
\fB\-\-gtf\fR \fBw\fR=\fI<width>\fR,\fBh\fR=\fI<height>\fR[,\fBfps\fR=\fI<fps>\fR][,\fBhorfreq\fR=\fI<horfreq>\fR][,\fBpixclk\fR=\fI<pixclk>\fR]
[,\fBinterlaced\fR][,\fBoverscan\fR][,\fBsecondary\fR][,\fBC\fR=\fI<c>\fR][,\fBM\fR=\fI<m>\fR][,\fBK\fR=\fI<k>\fR][,\fBJ\fR=\fI<j>\fR]
diff --git a/edid-decode.cpp b/edid-decode.cpp
index e28a3a3..de70242 100644
--- a/edid-decode.cpp
+++ b/edid-decode.cpp
@@ -139,7 +139,7 @@ static void usage(void)
" --dmt <dmt> Show the timings for the DMT with the given DMT ID.\n"
" --vic <vic> Show the timings for this VIC.\n"
" --hdmi-vic <hdmivic> Show the timings for this HDMI VIC.\n"
- " --cvt w=<width>,h=<height>,fps=<fps>[,rb=<rb>][,interlaced][,overscan][,alt]\n"
+ " --cvt w=<width>,h=<height>,fps=<fps>[,rb=<rb>][,interlaced][,overscan][,alt][,hblank=<hblank]\n"
" Calculate the CVT timings for the given format.\n"
" <fps> is frames per second for progressive timings,\n"
" or fields per second for interlaced timings.\n"
@@ -151,6 +151,8 @@ static void usage(void)
" optimized for video: 1000 / 1001 * <fps>.\n"
" If 'alt' is given and <rb>=3, then the horizontal blanking\n"
" is 160 instead of 80 pixels.\n"
+ " If 'hblank' is given and <rb>=3, then the horizontal blanking\n"
+ " is <hblank> pixels (range of 80-200), overriding 'alt'.\n"
" --gtf w=<width>,h=<height>[,fps=<fps>][,horfreq=<horfreq>][,pixclk=<pixclk>][,interlaced]\n"
" [,overscan][,secondary][,C=<c>][,M=<m>][,K=<k>][,J=<j>]\n"
" Calculate the GTF timings for the given format.\n"
@@ -540,12 +542,10 @@ bool edid_state::print_timings(const char *prefix, const struct timings *t,
if (rb) {
bool alt = t->rb & RB_ALT;
s = "RB";
- // Mark RB_CVT_V3 as preliminary since CVT 1.3 has not been
- // released yet.
if (rb == RB_CVT_V2)
s += std::string("v2") + (alt ? ",video-optimized" : "");
else if (rb == RB_CVT_V3)
- s += std::string("v3-is-preliminary") + (alt ? ",h-blank-160" : "");
+ s += std::string("v3") + (alt ? ",h-blank-160" : "");
}
add_str(s, flags);
if (t->hsize_mm || t->vsize_mm)
@@ -1334,6 +1334,7 @@ enum cvt_opts {
CVT_OVERSCAN,
CVT_RB,
CVT_ALT,
+ CVT_RB_H_BLANK,
};
static int parse_cvt_subopt(char **subopt_str, double *value)
@@ -1349,6 +1350,7 @@ static int parse_cvt_subopt(char **subopt_str, double *value)
"overscan",
"rb",
"alt",
+ "hblank",
nullptr
};
@@ -1377,6 +1379,7 @@ static void parse_cvt(char *optarg)
unsigned w = 0, h = 0;
double fps = 0;
unsigned rb = RB_NONE;
+ unsigned rb_h_blank = 0;
bool interlaced = false;
bool alt = false;
bool overscan = false;
@@ -1409,6 +1412,9 @@ static void parse_cvt(char *optarg)
case CVT_ALT:
alt = opt_val;
break;
+ case CVT_RB_H_BLANK:
+ rb_h_blank = opt_val;
+ break;
default:
break;
}
@@ -1421,7 +1427,7 @@ static void parse_cvt(char *optarg)
}
if (interlaced)
fps /= 2;
- timings t = state.calc_cvt_mode(w, h, fps, rb, interlaced, overscan, alt);
+ timings t = state.calc_cvt_mode(w, h, fps, rb, interlaced, overscan, alt, rb_h_blank);
state.print_timings("", &t, "CVT", "", true, false);
}
diff --git a/edid-decode.h b/edid-decode.h
index 4b73fd4..f3fdfd0 100644
--- a/edid-decode.h
+++ b/edid-decode.h
@@ -313,7 +313,8 @@ struct edid_state {
void edid_gtf_mode(unsigned refresh, struct timings &t);
timings calc_cvt_mode(unsigned h_pixels, unsigned v_lines,
double ip_freq_rqd, unsigned rb, bool int_rqd = false,
- bool margins_rqd = false, bool alt = false);
+ bool margins_rqd = false, bool alt = false,
+ unsigned rb_h_blank = 0);
void edid_cvt_mode(unsigned refresh, struct timings &t);
void detailed_cvt_descriptor(const char *prefix, const unsigned char *x, bool first);
void print_standard_timing(const char *prefix, unsigned char b1, unsigned char b2,

Privacy Policy