aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2020-11-22 13:44:19 +0100
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2020-12-30 11:34:26 +0100
commitfa87c71f11a17400def68dad20dc26fd0c447dcd (patch)
treec46ca9fc302df67b623e0a7c01f5683c24d0a43c
parentccef07e720792bd99e9a7db7f59ac76ea21ab984 (diff)
edid-decode: add support for CVT RBv2 and RBv3
CVT Reduced Blanking version 2 was never implemented, do this now. Also add support for the new version 3. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r--edid-decode.h9
-rw-r--r--parse-base-block.cpp35
-rw-r--r--parse-displayid-block.cpp18
3 files changed, 42 insertions, 20 deletions
diff --git a/edid-decode.h b/edid-decode.h
index 7e02615..20390a6 100644
--- a/edid-decode.h
+++ b/edid-decode.h
@@ -21,6 +21,8 @@
#define EDID_PAGE_SIZE 128U
#define EDID_MAX_BLOCKS 256U
+#define RB_FLAG (1U << 7)
+
// Video Timings
// If interlaced is true, then the vertical blanking
// for each field is (vfp + vsync + vbp + 0.5), except for
@@ -32,7 +34,12 @@ struct timings {
unsigned hact, vact;
unsigned hratio, vratio;
unsigned pixclk_khz;
- unsigned rb; // 1 if CVT with reduced blanking, 2 if CVT with reduced blanking v2
+ // 0: no reduced blanking
+ // 1: reduced blanking version 1
+ // 2: reduced blanking version 2
+ // 3: reduced blanking version 3 with a horizontal blank of 80
+ // 3 | RB_FLAG: reduced blanking version 3 with a horizontal blank of 160
+ unsigned rb;
bool interlaced;
// The horizontal frontporch may be negative in GTF calculations,
// so use int instead of unsigned for hfp. Example: 292x176@76.
diff --git a/parse-base-block.cpp b/parse-base-block.cpp
index 4976e3f..37da226 100644
--- a/parse-base-block.cpp
+++ b/parse-base-block.cpp
@@ -640,7 +640,7 @@ void edid_state::edid_cvt_mode(unsigned refresh, struct timings &t)
VSyncStart = VDisplayRnd + CVT_MIN_V_PORCH;
VSyncEnd = VSyncStart + VSync;
- /* 15/13. Find pixel clock frequency (kHz for xf86) */
+ /* 15/13. Find pixel clock frequency (kHz) */
Clock = ((double)HTotal / HPeriod) * 1000.0;
Clock -= Clock % CVT_CLOCK_STEP;
}
@@ -652,12 +652,22 @@ void edid_state::edid_cvt_mode(unsigned refresh, struct timings &t)
#define CVT_RB_H_SYNC 32.0
/* Fixed number of clocks for horizontal blanking */
-#define CVT_RB_H_BLANK 160.0
+#define CVT_RB1_H_BLANK 160.0 // RB1 & RB3 with RB_FLAG set
+#define CVT_RB2_H_BLANK 80.0 // RB2 & RB3 with RB_FLAG cleared
/* Fixed number of lines for vertical front porch - default 3 */
-#define CVT_RB_VFPORCH 3
+#define CVT_RB1_V_FPORCH 3
+#define CVT_RB2_V_FPORCH 1
+#define CVT_RB3_V_FIELD_RATE_PPM_ADJ 350.0
+#define CVT_RB2_CLOCK_STEP 1
int VBILines;
+ double h_blank = (t.rb & ~RB_FLAG) == 1 ? CVT_RB1_H_BLANK : CVT_RB2_H_BLANK;
+ int v_fporch = t.rb == 1 ? CVT_RB1_V_FPORCH : CVT_RB2_V_FPORCH;
+ unsigned clock_step = t.rb == 1 ? CVT_CLOCK_STEP : CVT_RB2_CLOCK_STEP;
+
+ if (t.rb == 3)
+ VFieldRate += VFieldRate * (CVT_RB3_V_FIELD_RATE_PPM_ADJ / 1000000.0);
/* 8. Estimate Horizontal period. */
HPeriod = ((double) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) / VDisplayRnd;
@@ -667,26 +677,29 @@ void edid_state::edid_cvt_mode(unsigned refresh, struct timings &t)
VBILines++;
/* 10. Check if vertical blanking is sufficient */
- if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
- VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
+ if (VBILines < (v_fporch + VSync + CVT_MIN_V_BPORCH))
+ VBILines = v_fporch + VSync + CVT_MIN_V_BPORCH;
/* 11. Find total number of lines in vertical field */
VTotal = VDisplayRnd + VBILines;
/* 12. Find total number of pixels in a line */
- HTotal = HDisplay + CVT_RB_H_BLANK;
+ HTotal = HDisplay + h_blank;
/* Fill in HSync values */
- HSyncEnd = HDisplay + CVT_RB_H_BLANK / 2;
+ HSyncEnd = HDisplay + h_blank / 2;
HSyncStart = HSyncEnd - CVT_RB_H_SYNC;
/* Fill in VSync values */
- VSyncStart = VDisplay + CVT_RB_VFPORCH;
+ VSyncStart = VDisplay + v_fporch;
VSyncEnd = VSyncStart + VSync;
- /* 15/13. Find pixel clock frequency (kHz for xf86) */
- Clock = ((double)VFieldRate * VTotal * HTotal) / 1000.0;
- Clock -= Clock % CVT_CLOCK_STEP;
+ /* 15/13. Find pixel clock frequency (kHz) */
+ double clk_khz = ((double)VFieldRate * VTotal * HTotal) / 1000.0;
+ if (t.rb < 3)
+ Clock = clock_step * floor(clk_khz / clock_step);
+ else
+ Clock = clock_step * ceil(clk_khz / clock_step);
}
t.pixclk_khz = Clock;
diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp
index 6736987..44b8bec 100644
--- a/parse-displayid-block.cpp
+++ b/parse-displayid-block.cpp
@@ -896,11 +896,11 @@ void edid_state::parse_displayid_type_5_timing(const unsigned char *x)
if (x[0] & 0x10)
s += ", refresh rate * (1000/1001) supported";
- switch (x[0] & 0x03) {
- case 0: t.rb = 2; break;
- case 1: t.rb = 1; break;
- default: break;
- }
+ t.rb = 2;
+ if ((x[0] & 0x03) == 1)
+ warn("Unexpected use of 'custom reduced blanking'.\n");
+ else if ((x[0] & 0x03) > 1)
+ fail("Invalid Timing Formula.\n");
edid_cvt_mode(1 + x[6], t);
@@ -1350,12 +1350,14 @@ void edid_state::parse_displayid_type_10_timing(const unsigned char *x, bool is_
}
if (x[0] & 0x10) {
- if (t.rb == 2)
+ if (t.rb == 2) {
s += ", refresh rate * (1000/1001) supported";
- else if (t.rb == 3)
+ } else if (t.rb == 3) {
s += ", hblank is 160 pixels";
- else
+ t.rb |= RB_FLAG;
+ } else {
fail("VR_HB must be 0.\n");
+ }
}
if (x[0] & 0x80)
s += ", YCbCr 4:2:0";

Privacy Policy