summaryrefslogtreecommitdiff
path: root/tests/lib
diff options
context:
space:
mode:
authorJakub Czapiga <jacz@semihalf.com>2020-10-09 16:02:46 +0200
committerPatrick Georgi <pgeorgi@google.com>2020-11-10 06:19:10 +0000
commite0af9fcb2d526ffd654d0bb573dd5333d0d76269 (patch)
tree436bdda53dedf62ec6c3ca52aa01c3e6dfdab4f7 /tests/lib
parenteaaa549e4a176637198f50570b81ecd3a7cf9549 (diff)
downloadcoreboot-e0af9fcb2d526ffd654d0bb573dd5333d0d76269.tar.xz
tests: Add lib/edid-test test case
Signed-off-by: Jakub Czapiga <jacz@semihalf.com> Change-Id: I796e660eebc4d2c3c32207bd3a6ee44aaffeb325 Reviewed-on: https://review.coreboot.org/c/coreboot/+/46817 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Paul Fagerburg <pfagerburg@chromium.org>
Diffstat (limited to 'tests/lib')
-rw-r--r--tests/lib/Makefile.inc6
-rw-r--r--tests/lib/edid-test.c1272
2 files changed, 1278 insertions, 0 deletions
diff --git a/tests/lib/Makefile.inc b/tests/lib/Makefile.inc
index 27773b7f39..219f7e7634 100644
--- a/tests/lib/Makefile.inc
+++ b/tests/lib/Makefile.inc
@@ -5,6 +5,7 @@ tests-y += b64_decode-test
tests-y += hexstrtobin-test
tests-y += imd-test
tests-y += timestamp-test
+tests-y += edid-test
string-test-srcs += tests/lib/string-test.c
string-test-srcs += src/lib/string.c
@@ -24,3 +25,8 @@ timestamp-test-srcs += tests/lib/timestamp-test.c
timestamp-test-srcs += tests/stubs/timestamp.c
timestamp-test-srcs += tests/stubs/console.c
timestamp-test-stage := romstage
+
+edid-test-srcs += tests/lib/edid-test.c
+edid-test-srcs += src/lib/edid.c
+edid-test-srcs += tests/stubs/console.c
+
diff --git a/tests/lib/edid-test.c b/tests/lib/edid-test.c
new file mode 100644
index 0000000000..0da7c61853
--- /dev/null
+++ b/tests/lib/edid-test.c
@@ -0,0 +1,1272 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <stdlib.h>
+#include <tests/test.h>
+#include <edid.h>
+#include <assert.h>
+#include <string.h>
+#include <lib/edid-test.h>
+
+struct test_state {
+ int data_size;
+ void *data;
+};
+
+static uint8_t get_raw_edid_checksum(const unsigned char *x)
+{
+ unsigned char sum = 0;
+ int i;
+ for (i = 0; i < 127; ++i)
+ sum += x[i];
+
+ return 256 - sum;
+}
+
+static void edid_raw_calc_checksum(struct edid_raw *raw)
+{
+ raw->checksum = get_raw_edid_checksum((const unsigned char *)raw);
+}
+
+static void test_decode_edid_no_edid(void **state)
+{
+ assert_int_equal(EDID_ABSENT, decode_edid(NULL, 0, NULL));
+}
+
+static void test_decode_edid_invalid_header(void **state)
+{
+ struct edid_raw raw = {
+ .header = EDID_HEADER_INVALID_RAW
+ };
+ raw.checksum = get_raw_edid_checksum((const unsigned char *)&raw);
+
+ assert_int_equal(EDID_ABSENT, decode_edid((unsigned char *)&raw, sizeof(raw), NULL));
+}
+
+/* Frame is modified example of an LCD Desktop IT display
+ * from VESA E-EDID Standard Release A2.
+ */
+static int setup_decode_edid_basic_frame(void **state)
+{
+ struct edid_raw raw = {
+ EDID_RAW_DEFAULT_PARAMS,
+ .video_input_type = EDID_ANALOG_VSI
+ | EDID_SIGNAL_LEVEL_0
+ | EDID_VIDEO_SETUP_BLANK_EQ_BLACK
+ | EDID_SEPARATE_SYNC_H_AND_V(1)
+ | EDID_COMPOSITE_SYNC_H(1)
+ | EDID_COMPOSITE_SYNC_ON_GREEN(1)
+ | EDID_SERRATION_VSYNC(1),
+ .horizontal_size = 43, /* [cm] */
+ .vertical_size = 32, /* [cm] */
+ .display_gamma = 120, /* 220% */
+ .supported_features = EDID_STANDBY_MODE(0)
+ | EDID_SUSPEND_MODE(0)
+ | EDID_ACTIVE_OFF(1)
+ | EDID_COLOR_FORMAT_RGB444
+ | EDID_SRGB_SUPPORTED(0)
+ | EDID_PREFERRED_TIMING_EXTENDED_INFO
+ | EDID_DISPLAY_FREQUENCY_CONTINUOUS,
+ .established_supported_timings = {
+ [0] = EDID_ESTABLISHED_TIMINGS_1_720x400_70Hz
+ | EDID_ESTABLISHED_TIMINGS_1_720x400_88Hz
+ | EDID_ESTABLISHED_TIMINGS_1_640x480_60Hz
+ | EDID_ESTABLISHED_TIMINGS_1_640x480_67Hz
+ | EDID_ESTABLISHED_TIMINGS_1_640x480_72Hz
+ | EDID_ESTABLISHED_TIMINGS_1_640x480_75Hz
+ | EDID_ESTABLISHED_TIMINGS_1_800x600_56Hz
+ | EDID_ESTABLISHED_TIMINGS_1_800x600_60Hz,
+ [1] = EDID_ESTABLISHED_TIMINGS_2_800x600_72Hz
+ | EDID_ESTABLISHED_TIMINGS_2_800x600_75Hz
+ | EDID_ESTABLISHED_TIMINGS_2_832x624_75Hz
+ | EDID_ESTABLISHED_TIMINGS_2_1024x768_80HzI
+ | EDID_ESTABLISHED_TIMINGS_2_1024x768_60Hz
+ | EDID_ESTABLISHED_TIMINGS_2_1024x768_70Hz
+ | EDID_ESTABLISHED_TIMINGS_2_1024x768_75Hz
+ | EDID_ESTABLISHED_TIMINGS_2_1280x1024_75Hz,
+ },
+ .manufacturers_reserved_timing = EDID_MANUFACTURERS_TIMINGS_1152x870_75Hz,
+ .standard_timings_supported = {
+ [0] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1600),
+ [1] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(85),
+
+ [2] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1600),
+ [3] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(75),
+
+ [4] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1600),
+ [5] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(70),
+
+ [6] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1600),
+ [7] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(65),
+
+ [8] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1280),
+ [9] = EDID_ASPECT_RATIO_5_4 | EDID_FIELD_REFRESH_RATE(85),
+
+ [10] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1280),
+ [11] = EDID_ASPECT_RATIO_5_4 | EDID_FIELD_REFRESH_RATE(60),
+
+ [12] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1024),
+ [13] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(85),
+
+ [14] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(800),
+ [15] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(85),
+ },
+ .descriptor_block_1 = {
+ [0] = EDID_PIXEL_CLOCK(162000000u) & 0xFF,
+ [1] = (EDID_PIXEL_CLOCK(162000000u) >> 8) & 0xFF,
+
+ /*
+ * Horizontal Addressable Video is 1600px
+ * Horizontal Blanking is 560px
+ */
+ [2] = 0x40, [3] = 0x30, [4] = 0x62,
+
+ /*
+ * Vertical Addressable Video is 1200 lines
+ * Vertical Blanking is 50 lines
+ */
+ [5] = 0xB0, [6] = 0x32, [7] = 0x40,
+
+ [8] = 64u, /* Horizontal Front Porch in pixels */
+ [9] = 192u, /* Horizontal Pulse Sync Width in pixels */
+ [10] = 0x13, /* Vertical Front Porch is 1 line */
+ [11] = 0x00, /* Vertical Sync Pulse Width is 3 lines */
+
+ /*
+ * Horizontal Addressable Image Size is 427mm
+ * Vertical Addressable Image Size is 320mm
+ */
+ [12] = 0xAB, [13] = 0x40, [14] = 0x11,
+
+ [15] = 0x00, /* Horizontal border size is 0px*/
+ [16] = 0x00, /* Vertical Border Size is 0px */
+
+ /*
+ * Timing is Non-Interlaced Video,
+ * Stereo Video is not supported,
+ * Digital separate syncs are requires.
+ * */
+ [17] = 0x1E,
+ },
+ .descriptor_block_2 = {
+ /* Display Range Limits Block Tag */
+ [0] = 0, [1] = 0, [2] = 0, [3] = 0xFD,
+
+ [4] = 0, /* Horizontal and Vertical Rate Offsets are zero */
+ [5] = 50u, /* Minimum Vertical Freq is 50Hz */
+ [6] = 90u, /* Maximum Vertical Freq is 90Hz */
+
+ [7] = 30u, /* Minimum Horizontal Freq is 30kHz */
+ [8] = 110u, /* Maximum Horizontal Freq is 110kHz */
+ [9] = 23u, /* Maximum Pixel Clock Freq i 230MHz */
+ [10] = 0x4, /* Begin CVT Support Info */
+ [11] = 0x11, /* Compatible with CVT Version 1.1 */
+ [12] = 0, /* Maimum Pixel Clock Freq remains at 230MHz */
+ [13] = 200, /* Maximum Active Pixels per Pile is 1600 */
+ [14] = 0x90, /* Supported aspect ratios: 4:3, 5:4 */
+
+ /* Preferred Aspect Ratio is 4:3, Standard CVT Blanking is supported */
+ [15] = 0,
+ [16] = 0x50, /* H. & V. Stretch are supported and Shrinks are not */
+ [17] = 60u, /* Preferred Refresh Rate is 60Hz */
+ },
+ .descriptor_block_3 = {
+ /* Established Timings III Block Tag */
+ [0] = 0, [1] = 0, [2] = 0, [3] = 0xF7, [4] = 0,
+
+ [5] = 10u, /* VESA DMT Standard Version #10 */
+ /*
+ * 640x350@85Hz,
+ * 640x400@85Hz,
+ * 720x400@85Hz,
+ * 640x480@85Hz,
+ * 800x600@85Hz,
+ * 1024x768@85Hz,
+ * 1152x864@75Hz
+ */
+ [6] = 0x7F,
+
+ /*
+ * 1280x960@60Hz,
+ * 1280x960@85Hz,
+ * 1280x1024@60Hz,
+ * 1280x1024@85Hz
+ */
+ [7] = 0x0F,
+
+ /*
+ * 1400x1050@60Hz (Normal Blanking),
+ * 1400x1050@75Hz are supported.
+ */
+ [8] = 0x03,
+
+ /*
+ * 1400x1050@85Hz,
+ * 1600x1200@60Hz,
+ * 1600x1200@65Hz,
+ * 1600x1200@70Hz are supported.
+ */
+ [9] = 0x87,
+
+ /*
+ * 1600x1200@75Hz,
+ * 1600x1200@85Hz are supported.
+ */
+ [10] = 0xC0,
+
+ /* 1920 timings not supported */
+ [11] = 0x0,
+
+ [12 ... 17] = 0,
+ },
+ .descriptor_block_4 = {
+ /* Display Product Name Block Tag */
+ [0] = 0, [1] = 0, [2] = 0, [3] = 0xFC, [4] = 0,
+
+ /* Product name */
+ [5] = 'A',
+ [6] = 'B',
+ [7] = 'C',
+ [8] = ' ',
+ [9] = 'L',
+ [10] = 'C',
+ [11] = 'D',
+ [12] = '2',
+ [13] = '1',
+ [14] = '\n',
+ [15] = ' ',
+ [16] = ' ',
+ [17] = ' ',
+ },
+ .extension_flag = 0x0, /* No extensions */
+ };
+
+ edid_raw_calc_checksum(&raw);
+
+ *state = malloc(sizeof(struct test_state));
+
+ struct test_state ts = {
+ .data_size = sizeof(struct edid_raw),
+ .data = malloc(sizeof(struct edid_raw))
+ };
+
+ memcpy(ts.data, &raw, sizeof(raw));
+ memcpy(*state, &ts, sizeof(ts));
+
+ return 0;
+}
+
+/* Test decoding of EDID frame without extensions.
+ */
+static void test_decode_edid_basic_frame(void **state)
+{
+ struct edid out;
+ struct test_state *ts = *state;
+
+ /* In real-life situations frames often are not 100% conformant,
+ * but are at least correct when it comes to key data fields.
+ */
+ assert_int_equal(EDID_CONFORMANT,
+ decode_edid((unsigned char *)ts->data, ts->data_size, &out));
+
+ assert_int_equal(32, out.framebuffer_bits_per_pixel);
+ assert_int_equal(0, out.panel_bits_per_color);
+ assert_int_equal(0, out.panel_bits_per_pixel);
+ assert_int_equal(0, out.link_clock);
+ assert_int_equal(1600, out.x_resolution);
+ assert_int_equal(1200, out.y_resolution);
+ assert_int_equal(6400, out.bytes_per_line);
+ assert_int_equal(0, out.hdmi_monitor_detected);
+ assert_int_equal(0, strnlen(out.ascii_string, ARRAY_SIZE(out.ascii_string)));
+ assert_string_equal(out.manufacturer_name, EDID_MANUFACTURER_NAME);
+
+ /* Mode */
+ assert_null(out.mode.name);
+ assert_int_equal(162000, out.mode.pixel_clock);
+ assert_int_equal(1, out.mode.lvds_dual_channel);
+ assert_int_equal(0, out.mode.refresh);
+ assert_int_equal(1600, out.mode.ha);
+ assert_int_equal(560, out.mode.hbl);
+ assert_int_equal(64, out.mode.hso);
+ assert_int_equal(192, out.mode.hspw);
+ assert_int_equal(0, out.mode.hborder);
+ assert_int_equal(1200, out.mode.va);
+ assert_int_equal(50, out.mode.vbl);
+ assert_int_equal(1, out.mode.vso);
+ assert_int_equal(0, out.mode.vborder);
+ assert_int_equal(43, out.mode.phsync);
+ assert_int_equal(43, out.mode.pvsync);
+ assert_int_equal(0, out.mode.x_mm);
+ assert_int_equal(0, out.mode.y_mm);
+
+ assert_int_equal(1, out.mode_is_supported[EDID_MODE_640x480_60Hz]);
+ assert_int_equal(0, out.mode_is_supported[EDID_MODE_720x480_60Hz]);
+ assert_int_equal(0, out.mode_is_supported[EDID_MODE_1280x720_60Hz]);
+ assert_int_equal(0, out.mode_is_supported[EDID_MODE_1920x1080_60Hz]);
+}
+
+/* Frame is modified example of base EDID frame with CEA861 extension
+ * for DTV Display from VESA E-EDID Standard Release A2.
+ */
+static int setup_decode_edid_dtv_frame_with_extension(void **state)
+{
+ struct edid_raw raw = {
+ EDID_RAW_DEFAULT_PARAMS,
+ .video_input_type = EDID_DIGITAL_VSI
+ | EDID_INTERFACE_HDMI_A
+ | EDID_COLOR_BIT_DEPTH_8B,
+ .horizontal_size = 16, /* Aspect ratio 16:9 in landscape */
+ .vertical_size = 0, /* Landscape flag */
+ .display_gamma = 120, /* 220% */
+ .supported_features = EDID_STANDBY_MODE(0)
+ | EDID_SUSPEND_MODE(0)
+ | EDID_ACTIVE_OFF(0)
+ | EDID_COLOR_FORMAT_RGB444_YCRCB422_YCRCB422
+ | EDID_SRGB_SUPPORTED(1)
+ | EDID_PREFERRED_TIMING_EXTENDED_INFO
+ | EDID_DISPLAY_FREQUENCY_NON_CONTINUOUS,
+
+ .established_supported_timings = {
+ [0] = EDID_ESTABLISHED_TIMINGS_1_640x480_60Hz,
+ [1] = 0,
+ },
+ .manufacturers_reserved_timing = 0,
+ .standard_timings_supported = { [0 ... 15] = 0, },
+ .descriptor_block_1 = {
+ [0] = EDID_PIXEL_CLOCK(148500000u) & 0xFF,
+ [1] = (EDID_PIXEL_CLOCK(148500000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1920px
+ * Horizontal Blanking is 280px
+ */
+ [2] = 0x80, [3] = 0x18, [4] = 0x71,
+
+ /* Vertical Addressable Video is 1080 lines
+ * Vertical Blanking is 45 lines
+ */
+ [5] = 0x38, [6] = 0x2D, [7] = 0x40,
+
+ [8] = 88u, /* Horizontal Front Porch in pixels */
+ [9] = 44u, /* Horizontal Pulse Sync Width in pixels */
+ [10] = 4u, /* Vertical Front Porch is 4 lines */
+ [11] = 5u, /* Vertical Sync Pulse Width is 5 lines */
+
+ /* Horizontal Addressable Image Size is 1039mm
+ * Vertical Addressable Image Size is 584mm
+ */
+ [12] = 0x0F, [13] = 0x48, [14] = 0x42,
+
+ [15] = 0x00, /* Horizontal border size is 0px*/
+ [16] = 0x00, /* Vertical Border Size is 0px */
+
+ /* Timing is Non-Interlaced Video,
+ * Stereo Video is not supported,
+ * Digital separate and syncs are requires.
+ */
+ [17] = 0x1E,
+ },
+ .descriptor_block_2 = {
+ [0] = EDID_PIXEL_CLOCK(74250000u) & 0xFF,
+ [1] = (EDID_PIXEL_CLOCK(74250000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1920px
+ * Horizontal Blanking is 280px
+ */
+ [2] = 0x80, [3] = 0x18, [4] = 0x71,
+
+ /* Vertical Addressable Video is 540 lines
+ * Vertical Blanking is 22 lines
+ */
+ [5] = 0x1C, [6] = 0x16, [7] = 0x20,
+
+ [8] = 88u, /* Horizontal Front Porch in pixels */
+ [9] = 44u, /* Horizontal Pulse Sync Width in pixels */
+ [10] = 0x25, /* Vertical Front Porch is 2 lines */
+ [11] = 0x00, /* Vertical Sync Pulse Width is 5 lines */
+
+ /* Horizontal Addressable Image Size is 1039mm
+ * Vertical Addressable Image Size is 584mm
+ */
+ [12] = 0x0F, [13] = 0x48, [14] = 0x42,
+
+ [15] = 0x00, /* Horizontal border size is 0px*/
+ [16] = 0x00, /* Vertical Border Size is 0px */
+
+ /* Timing is Interlaced Video,
+ * Stereo Video is not supported,
+ * Digital separate and syncs are requires.
+ */
+ [17] = 0x9E,
+ },
+ .descriptor_block_3 = {
+ [0] = EDID_PIXEL_CLOCK(74250000u) & 0xFF,
+ [1] = (EDID_PIXEL_CLOCK(74250000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1280px
+ * Horizontal Blanking is 370px
+ */
+ [2] = 0x00, [3] = 0x72, [4] = 0x51,
+
+ /* Vertical Addressable Video is 720 lines
+ * Vertical Blanking is 30 lines
+ */
+ [5] = 0xD0, [6] = 0x1E, [7] = 0x20,
+
+ [8] = 110u, /* Horizontal Front Porch in pixels */
+ [9] = 40u, /* Horizontal Pulse Sync Width in pixels */
+ [10] = 0x55u, /* Vertical Front Porch is 5 lines */
+ [11] = 0x00, /* Vertical Sync Pulse Width is 5 lines */
+
+ /* Horizontal Addressable Image Size is 1039mm
+ * Vertical Addressable Image Size is 584mm
+ */
+ [12] = 0x0F, [13] = 0x48, [14] = 0x42,
+
+ [15] = 0x00, /* Horizontal border size is 0px*/
+ [16] = 0x00, /* Vertical Border Size is 0px */
+
+ /* Timing is Non-Interlaced Video,
+ * Stereo Video is not supported,
+ * Digital separate syncs are requires.
+ */
+ [17] = 0x1E,
+ },
+ .descriptor_block_4 = {
+ /* Display Product Name Block Tag */
+ [0] = 0, [1] = 0, [2] = 0, [3] = 0xFC, [4] = 0,
+
+ /* Product name */
+ [5] = 'A',
+ [6] = 'B',
+ [7] = 'C',
+ [8] = ' ',
+ [9] = 'L',
+ [10] = 'C',
+ [11] = 'D',
+ [12] = '4',
+ [13] = '7',
+ [14] = 'w',
+ [15] = '\n',
+ [16] = ' ',
+ [17] = ' ',
+ },
+ .extension_flag = 0x0, /* No extensions */
+ };
+
+ edid_raw_calc_checksum(&raw);
+
+ unsigned char ext[128] = {
+ [0] = 0x02, /* CEA 861 Extension Block Tag Code */
+ [1] = 0x03, /* CEA 861 Block Version */
+
+ [2] = 0x18, /* Detail Timing Descriptors start 0x18 bytes from here */
+
+ /* Underscan is not supported
+ * Basic Audio is supported
+ * YCbCr 4:4:4 & YCbCr 4:2:2 are supported
+ * Number of native formats: 2
+ */
+ [3] = 0x72,
+
+ /* Video Data Block Tag Code is 2
+ * Number of Short Video Descriptor Bytes i 7
+ */
+ [4] = 0x47,
+
+ /* 1920x1080p 59.94/60 Hz 16 : 9 AR (CEA Format #16)
+ * is a supported Native Format. */
+ [5] = 0x90,
+
+ /* 1920x1080i 59.94/60 Hz 16 : 9 AR (CEA Format #5)
+ * is a supported Native Format. */
+ [6] = 0x85,
+
+ /* 1280x720p 59.94/60 Hz 16 : 9 AR (CEA Format #4) is a supported format. */
+ [7] = 0x04,
+
+ /* 720x480p 59.94/60 Hz 16 : 9 AR (CEA Format #3) is a supported format. */
+ [8] = 0x03,
+
+ /* 720x480p 59.94/60 Hz 4 : 3 AR (CEA Format #2) is a supported format. */
+ [9] = 0x02,
+
+ /* 720x480i 59.94/60 Hz 16 : 9 AR (CEA Format #7) is a supported format. */
+ [10] = 0x07,
+
+ /* 720x480i 59.94/60 Hz 4 : 3 AR (CEA Format #6) is a supported format. */
+ [11] = 0x06,
+
+ /* Audio Data Block Tag Code is 1.
+ * Number of Short Audio Descriptor Bytes is 3.
+ */
+ [12] = 0x23,
+
+ /* Audio Format Tag Code is 1 --- LPCM is supported.
+ * Maximum number of audio channels is 2
+ */
+ [13] = 0x09,
+
+ /* Supported Sampling Frequencies include: 48kHz; 44.1kHz & 32kHz. */
+ [14] = 0x07,
+
+ /* Supported Sampling Bit Rates include: 24 bit; 20 bit & 16 bit. */
+ [15] = 0x07,
+
+ /* Speaker Allocation Block Tag Code is 4.
+ * Number of Speaker Allocation
+ * Descriptor Bytes is 3.
+ */
+ [16] = 0x83,
+
+ /* Speaker Allocation is Front-Left & Front-Right */
+ [17] = 0x01,
+
+ /* Reserved */
+ [18 ... 19] = 0,
+
+ /* Vendor Specific Data Block Tag Code is 3.
+ * Number of Vendor Specific Data Bytes is 5.
+ */
+ [20] = 0x65,
+
+ /* 24bit IEEE registration Identifier is 0x000C03 */
+ [21] = 0x03, [22] = 0x0C, [23] = 0x00,
+
+ /* Vendor Specific Data is 0x10000 */
+ [24] = 0x01, [25] = 0x00,
+
+ /* Descriptor Block 5 [18 Bytes] */
+
+ [26] = EDID_PIXEL_CLOCK(27027000u) & 0xFF,
+ [27] = (EDID_PIXEL_CLOCK(27027000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 720px.
+ * Horizontal Blanking is 138 px.
+ */
+ [28] = 0xD0, [29] = 0x8A, [30] = 0x20,
+
+ /* Vertical Addressable Video is 480 lines.
+ * Vertical Blanking is 45 lines.
+ */
+ [31] = 0xE0, [32] = 0x2D, [33] = 0x10,
+
+ [34] = 16u, /* Horizontal Front Porch in pixels */
+ [35] = 62u, /* Horizontal Sync Pulse Width in pixels */
+ [36] = 0x96, /* Vertical Front Porch is 9 lines */
+ [37] = 0x00, /* Vertical Sync Pulse Width is 6 lines */
+
+ /* Displayed Image Aspect Ratio is 16:9 */
+ [38] = 16u, [39] = 9u, [40] = 0u,
+
+ /* Horizontal and Vertical Border Size is 0 px */
+ [41] = 0u, [42] = 0u,
+
+ /* Timing is Interlaced Video
+ * Stereo Video is not supported
+ * Digital Separate Syncs are required
+ */
+ [43] = 0x18,
+
+ /* Descriptor Block 6 [18 Bytes] */
+
+ [44] = EDID_PIXEL_CLOCK(27027000u) & 0xFF,
+ [45] = (EDID_PIXEL_CLOCK(27027000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 720px.
+ * Horizontal Blanking is 138 px.
+ */
+ [46] = 0xD0, [47] = 0x8A, [48] = 0x20,
+
+ /* Vertical Addressable Video is 480 lines.
+ * Vertical Blanking is 45 lines.
+ */
+ [49] = 0xE0, [50] = 0x2D, [51] = 0x10,
+
+ [52] = 16u, /* Horizontal Front Porch in pixels */
+ [53] = 62u, /* Horizontal Sync Pulse Width in pixels */
+ [54] = 0x96, /* Vertical Front Porch is 9 lines */
+ [55] = 0x00, /* Vertical Sync Pulse Width is 6 lines */
+
+ /* Displayed Image Aspect Ratio is 4:3 */
+ [56] = 4u, [57] = 3u, [58] = 0u,
+
+ /* Horizontal and Vertical Border Size is 0 px */
+ [59] = 0u, [60] = 0u,
+
+ /* Timing is Interlaced Video
+ * Stereo Video is not supported
+ * Digital Separate Syncs are required
+ */
+ [61] = 0x18,
+
+ /* Descriptor Block 7 [18 Bytes] */
+
+ [62] = EDID_PIXEL_CLOCK(27027000u) & 0xFF,
+ [63] = (EDID_PIXEL_CLOCK(27027000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1440px.
+ * Horizontal Blanking is 276 px.
+ */
+ [64] = 0xA0, [65] = 0x14, [66] = 0x51,
+
+ /* Vertical Addressable Video is 240 lines.
+ * Vertical Blanking is 23 lines.
+ */
+ [67] = 0xF0, [68] = 0x16, [69] = 0x00,
+
+ [70] = 38u, /* Horizontal Front Porch in pixels */
+ [71] = 124u, /* Horizontal Sync Pulse Width in pixels */
+ [72] = 0x43, /* Vertical Front Porch is 9 lines */
+ [73] = 0x00, /* Vertical Sync Pulse Width is 6 lines */
+
+ /* Displayed Image Aspect Ratio is 16:9 */
+ [74] = 16u, [75] = 9u, [76] = 0u,
+
+ /* Horizontal and Vertical Border Size is 0 px */
+ [77] = 0u, [78] = 0u,
+
+ /* Timing is Interlaced Video
+ * Stereo Video is not supported
+ * Digital Separate Syncs are required
+ */
+ [79] = 0x98,
+
+ /* Descriptor Block 8 [18 Bytes] */
+
+ [80] = EDID_PIXEL_CLOCK(27027000u) & 0xFF,
+ [81] = (EDID_PIXEL_CLOCK(27027000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1440px.
+ * Horizontal Blanking is 276 px.
+ */
+ [82] = 0xA0, [83] = 0x14, [84] = 0x51,
+
+ /* Vertical Addressable Video is 240 lines.
+ * Vertical Blanking is 23 lines.
+ */
+ [85] = 0xF0, [86] = 0x16, [87] = 0x00,
+
+ [88] = 38u, /* Horizontal Front Porch in pixels */
+ [89] = 124u, /* Horizontal Sync Pulse Width in pixels */
+ [90] = 0x43, /* Vertical Front Porch is 9 lines */
+ [91] = 0x00, /* Vertical Sync Pulse Width is 6 lines */
+
+ /* Displayed Image Aspect Ratio is 4:3 */
+ [92] = 4u, [93] = 3u, [94] = 0u,
+
+ /* Horizontal and Vertical Border Size is 0 px */
+ [95] = 0u, [96] = 0u,
+
+ /* Timing is Interlaced Video
+ * Stereo Video is not supported
+ * Digital Separate Syncs are required
+ */
+ [97] = 0x98,
+
+ [99 ... 126] = 0
+ };
+
+ ext[127] = get_raw_edid_checksum(ext);
+
+ *state = malloc(sizeof(struct test_state));
+
+ struct test_state ts = {
+ .data_size = sizeof(raw) + sizeof(ext),
+ .data = malloc(sizeof(raw) + sizeof(ext))
+ };
+
+ memcpy(ts.data, &raw, sizeof(raw));
+ memcpy(ts.data + sizeof(raw), &ext[0], sizeof(ext));
+
+ memcpy(*state, &ts, sizeof(ts));
+
+ return 0;
+}
+
+/* Test decoding of EDID frame with one extension.
+ */
+static void test_decode_edid_dtv_frame_with_extension(void **state)
+{
+ struct edid out;
+ struct test_state *ts = *state;
+
+ /* In real-life situations frames often are not 100% conformant,
+ * but are at least correct when it comes to key data fields.
+ */
+ assert_int_equal(EDID_CONFORMANT,
+ decode_edid((unsigned char *)ts->data, ts->data_size, &out));
+
+ assert_int_equal(32, out.framebuffer_bits_per_pixel);
+ assert_int_equal(8, out.panel_bits_per_color);
+ assert_int_equal(24, out.panel_bits_per_pixel);
+ assert_int_equal(0, out.link_clock);
+ assert_int_equal(1920, out.x_resolution);
+ assert_int_equal(1080, out.y_resolution);
+ assert_int_equal(7680, out.bytes_per_line);
+ assert_int_equal(1, out.hdmi_monitor_detected);
+ assert_int_equal(0, strnlen(out.ascii_string, ARRAY_SIZE(out.ascii_string)));
+ assert_string_equal(out.manufacturer_name, EDID_MANUFACTURER_NAME);
+
+ /* Mode */
+ assert_null(out.mode.name);
+ assert_int_equal(148500, out.mode.pixel_clock);
+ assert_int_equal(1, out.mode.lvds_dual_channel);
+ assert_int_equal(0, out.mode.refresh);
+ assert_int_equal(1920, out.mode.ha);
+ assert_int_equal(280, out.mode.hbl);
+ assert_int_equal(88, out.mode.hso);
+ assert_int_equal(44, out.mode.hspw);
+ assert_int_equal(0, out.mode.hborder);
+ assert_int_equal(1080, out.mode.va);
+ assert_int_equal(45, out.mode.vbl);
+ assert_int_equal(16, out.mode.vso);
+ assert_int_equal(0, out.mode.vborder);
+ assert_int_equal(43, out.mode.phsync);
+ assert_int_equal(43, out.mode.pvsync);
+ assert_int_equal(0, out.mode.x_mm);
+ assert_int_equal(0, out.mode.y_mm);
+
+ assert_int_equal(1, out.mode_is_supported[EDID_MODE_640x480_60Hz]);
+ assert_int_equal(0, out.mode_is_supported[EDID_MODE_720x480_60Hz]);
+ assert_int_equal(0, out.mode_is_supported[EDID_MODE_1280x720_60Hz]);
+ assert_int_equal(0, out.mode_is_supported[EDID_MODE_1920x1080_60Hz]);
+}
+
+
+/* Test decoding of EDID frame with one extension. Tested frame is modified
+ * example of base EDID frame with CEA861 extension for IT/DTV Display from
+ * VESA E-EDID Standard Release A2.
+ */
+static int setup_decode_edid_it_dtv_frame_with_extension(void **state)
+{
+ struct edid_raw raw = {
+ EDID_RAW_DEFAULT_PARAMS,
+ .video_input_type = EDID_DIGITAL_VSI
+ | EDID_INTERFACE_HDMI_A
+ | EDID_COLOR_BIT_DEPTH_8B,
+ .horizontal_size = 121, /* Aspect ratio 16:9 in landscape */
+ .vertical_size = 68, /* Landscape flag */
+ .display_gamma = 120, /* 220% */
+ .supported_features = EDID_STANDBY_MODE(0)
+ | EDID_SUSPEND_MODE(0)
+ | EDID_ACTIVE_OFF(0)
+ | EDID_COLOR_FORMAT_RGB444_YCRCB422_YCRCB422
+ | EDID_SRGB_SUPPORTED(1)
+ | EDID_PREFERRED_TIMING_EXTENDED_INFO
+ | EDID_DISPLAY_FREQUENCY_NON_CONTINUOUS,
+ .established_supported_timings = {
+ [0] = EDID_ESTABLISHED_TIMINGS_1_800x600_60Hz
+ | EDID_ESTABLISHED_TIMINGS_1_800x600_56Hz
+ | EDID_ESTABLISHED_TIMINGS_1_640x480_75Hz
+ | EDID_ESTABLISHED_TIMINGS_1_640x480_72Hz
+ | EDID_ESTABLISHED_TIMINGS_1_640x480_67Hz
+ | EDID_ESTABLISHED_TIMINGS_1_640x480_60Hz
+ | EDID_ESTABLISHED_TIMINGS_1_720x400_88Hz
+ | EDID_ESTABLISHED_TIMINGS_1_720x400_70Hz,
+ [1] = EDID_ESTABLISHED_TIMINGS_2_1280x1024_75Hz
+ | EDID_ESTABLISHED_TIMINGS_2_1024x768_75Hz
+ | EDID_ESTABLISHED_TIMINGS_2_1024x768_70Hz
+ | EDID_ESTABLISHED_TIMINGS_2_1024x768_60Hz
+ | EDID_ESTABLISHED_TIMINGS_2_832x624_75Hz
+ | EDID_ESTABLISHED_TIMINGS_2_800x600_75Hz
+ | EDID_ESTABLISHED_TIMINGS_2_800x600_72Hz,
+ },
+ .manufacturers_reserved_timing = EDID_MANUFACTURERS_TIMINGS_1152x870_75Hz,
+ .standard_timings_supported = {
+ [0] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1280),
+ [1] = EDID_ASPECT_RATIO_5_4 | EDID_FIELD_REFRESH_RATE(85),
+
+ [2] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1280),
+ [3] = EDID_ASPECT_RATIO_5_4 | EDID_FIELD_REFRESH_RATE(60),
+
+ [4] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1280),
+ [5] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(85),
+
+ [6] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1280),
+ [7] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(60),
+
+ [8] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(1024),
+ [9] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(85),
+
+ [10] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(848),
+ [11] = EDID_ASPECT_RATIO_16_9 | EDID_FIELD_REFRESH_RATE(60),
+
+ [12] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(800),
+ [13] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(60),
+
+ [14] = EDID_HORIZONTAL_ACCESSIBLE_PIXELS(640),
+ [15] = EDID_ASPECT_RATIO_4_3 | EDID_FIELD_REFRESH_RATE(60),
+ },
+ .descriptor_block_1 = {
+ [0] = EDID_PIXEL_CLOCK(85500000u) & 0xFF,
+ [1] = (EDID_PIXEL_CLOCK(85500000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1360px
+ * Horizontal Blanking is 432px
+ */
+ [2] = 0x50, [3] = 0xB0, [4] = 0x51,
+
+ /* Vertical Addressable Video is 768 lines
+ * Vertical Blanking is 27 lines
+ */
+ [5] = 0x00, [6] = 0x1B, [7] = 0x30,
+
+ [8] = 64u, /* Horizontal Front Porch in pixels */
+ [9] = 112u, /* Horizontal Pulse Sync Width in pixels */
+ [10] = 0x36, /* Vertical Front Porch is 3 lines */
+ [11] = 0u, /* Vertical Sync Pulse Width is 6 lines */
+
+ /* Horizontal Addressable Image Size is 1214mm
+ * Vertical Addressable Image Size is 683mm
+ */
+ [12] = 0xBE, [13] = 0xAB, [14] = 0x42,
+
+ [15] = 0x00, /* Horizontal border size is 0px*/
+ [16] = 0x00, /* Vertical Border Size is 0px */
+
+ /* Timing is Non-Interlaced Video,
+ * Stereo Video is not supported,
+ * Digital separate and syncs are requires.
+ */
+ [17] = 0x1E,
+ },
+ .descriptor_block_2 = {
+ [0] = EDID_PIXEL_CLOCK(74250000u) & 0xFF,
+ [1] = (EDID_PIXEL_CLOCK(74250000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1280px
+ * Horizontal Blanking is 370px
+ */
+ [2] = 0x00, [3] = 0x72, [4] = 0x51,
+
+ /* Vertical Addressable Video is 720 lines
+ * Vertical Blanking is 30 lines
+ */
+ [5] = 0xD0, [6] = 0x1E, [7] = 0x20,
+
+ [8] = 110u, /* Horizontal Front Porch in pixels */
+ [9] = 40u, /* Horizontal Pulse Sync Width in pixels */
+ [10] = 0x55, /* Vertical Front Porch is 5 lines */
+ [11] = 0x00, /* Vertical Sync Pulse Width is 5 lines */
+
+ /* Horizontal Addressable Image Size is 1214mm
+ * Vertical Addressable Image Size is 683mm
+ */
+ [12] = 0xBE, [13] = 0xAB, [14] = 0x42,
+
+ [15] = 0x00, /* Horizontal border size is 0px*/
+ [16] = 0x00, /* Vertical Border Size is 0px */
+
+ /* Timing is Non-Interlaced Video,
+ * Stereo Video is not supported,
+ * Digital separate and syncs are requires.
+ */
+ [17] = 0x1E,
+ },
+ .descriptor_block_3 = {
+ /* Established timings III Block Tag */
+ [0 ... 2] = 0u, [3] = 0xF7, [4] = 0u,
+
+ /*
+ * VESA DMT Standard Version #10
+ */
+ [5] = 10u,
+
+ /* 640x350@85Hz,
+ * 640x400@85Hz,
+ * 720x400@85Hz,
+ * 640x480@85Hz,
+ * 800x600@85Hz,
+ * 1024x768@85Hz,
+ * 1152x864@75Hz are supported.
+ */
+ [6] = 0x7F,
+
+ /* 1280x960@60Hz,
+ * 1280x960@85Hz,
+ * 1280x1024@60Hz,
+ * 1280x1024@85Hz
+ */
+ [7] = 0x0F,
+
+ /* 1400x1050@60Hz (Normal Blanking),
+ * 1400x1050@75Hz are supported.
+ */
+ [8] = 0x03,
+
+ /* 1400x1050@85Hz,
+ * 1600x1200@60Hz,
+ * 1600x1200@65Hz,
+ * 1600x1200@70Hz are supported.
+ */
+ [9] = 0x87,
+
+ /* 1600x1200@75Hz,
+ * 1600x1200@85Hz are supported.
+ */
+ [10] = 0xC0,
+
+ /* 1920 PC Timings are not supported. */
+ [11] = 0u,
+
+ /* Reserved */
+ [12 ... 17] = 0,
+ },
+ .descriptor_block_4 = {
+ /* Display Product Name Block Tag */
+ [0] = 0, [1] = 0, [2] = 0, [3] = 0xFC, [4] = 0,
+
+ /* Product name */
+ [5] = 'A',
+ [6] = 'B',
+ [7] = 'C',
+ [8] = ' ',
+ [9] = 'P',
+ [10] = 'L',
+ [11] = 'A',
+ [12] = '5',
+ [13] = '5',
+ [14] = '\n',
+ [15] = ' ',
+ [16] = ' ',
+ [17] = ' ',
+ },
+ .extension_flag = 0x0, /* No extensions */
+ };
+
+ edid_raw_calc_checksum(&raw);
+
+ unsigned char ext[128] = {
+ [0] = 0x02, /* CEA 861 Extension Block Tag Code */
+ [1] = 0x03, /* CEA 861 Block Version */
+ [2] = 0x17, /* Detail Timing Descriptors start 0x17 bytesfrom here */
+
+ /* Underscan is supported
+ * Basic Audio is supported
+ * YCbCr 4:4:4 & YCbCr 4:2:2 are supported
+ * Number of native formats: 0
+ */
+ [3] = 0xF0,
+
+ /* Video Data Block Tag Code is 2
+ * Number of Short Video Descriptor Bytes i 6
+ */
+ [4] = 0x46,
+
+ /* 1920x1080i 59.94/60 Hz 16 : 9 AR (CEA Format #5) is a supported format. */
+ [5] = 0x05,
+
+ /* 1280x720p 59.94/60 Hz 16 : 9 AR (CEA Format #4) is a supported format. */
+ [6] = 0x04,
+
+ /* 720x480p 59.94/60 Hz 16 : 9 AR (CEA Format #3) is a supported format. */
+ [7] = 0x03,
+
+ /* 720x480p 59.94/60 Hz 4 : 3 AR (CEA Format #2) is a supported format. */
+ [8] = 0x02,
+
+ /* 720x480i 59.94/60 Hz 16 : 9 AR (CEA Format #7) is a supported format. */
+ [9] = 0x07,
+
+ /* 720x480i 59.94/60 Hz 4 : 3 AR (CEA Format #6) is a supported format. */
+ [10] = 0x06,
+
+ /* Audio Data Block Tag Code is 1.
+ * Number of Short Audio Descriptor Bytes is 3.
+ */
+ [11] = 0x23,
+
+ /* Audio Format Tag Code is 1 --- LPCM is supported.
+ * Maximum number of audio channels is 2
+ */
+ [12] = 0x09,
+
+ /* Supported Sampling Frequencies include: 48kHz; 44.1kHz & 32kHz. */
+ [13] = 0x07,
+
+ /* Supported Sampling Bit Rates include: 24 bit; 20 bit & 16 bit. */
+ [14] = 0x07,
+
+ /* Speaker Allocation Block Tag Code is 4.
+ * Number of Speaker Allocation
+ * Descriptor Bytes is 3.
+ */
+ [15] = 0x83,
+
+ /* Speaker Allocation is Front-Left & Front-Right */
+ [16] = 0x01,
+
+ /* Reserved */
+ [17 ... 18] = 0,
+
+ /* Vendor Specific Data Block Tag Code is 3.
+ * Number of Vendor Specific Data Bytes is 5.
+ */
+ [19] = 0x65,
+
+ /* 24bit IEEE registration Identifier is 0x000C03 */
+ [20] = 0x03, [21] = 0x0C, [22] = 0x00,
+
+ /* Vendor Specific Data is 0x10000 */
+ [23] = 0x01, [24] = 0x00,
+
+ /* Descriptor Block 5 [18 Bytes] */
+
+ [25] = EDID_PIXEL_CLOCK(74250000u) & 0xFF,
+ [26] = (EDID_PIXEL_CLOCK(74250000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1920px.
+ * Horizontal Blanking is 280px.
+ */
+ [27] = 0x80, [28] = 0x18, [29] = 0x71,
+
+ /* Vertical Addressable Video is 540 lines.
+ * Vertical Blanking is 22 lines.
+ */
+ [30] = 0x1C, [31] = 0x16, [32] = 0x20,
+
+ [33] = 88u, /* Horizontal Front Porch in pixels */
+ [34] = 44u, /* Horizontal Sync Pulse Width in pixels */
+ [35] = 0x25, /* Vertical Front Porch is 2 lines */
+ [36] = 0x00, /* Vertical Sync Pulse Width is 5 lines */
+
+ /* Image size: 1039mm x 584mm */
+ [37] = 0x0F, [38] = 0x48, [39] = 0x42,
+
+ /* Horizontal and Vertical Border Size is 0 px */
+ [40] = 0u, [41] = 0u,
+
+ /* Timing is Interlaced Video
+ * Stereo Video is not supported
+ * Digital Separate Syncs are required
+ */
+ [42] = 0x9E,
+
+ /* Descriptor Block 6 [18 Bytes] */
+
+ [43] = EDID_PIXEL_CLOCK(74250000u) & 0xFF,
+ [44] = (EDID_PIXEL_CLOCK(74250000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1280px.
+ * Horizontal Blanking is 370 px.
+ */
+ [45] = 0x00, [46] = 0x72, [47] = 0x51,
+
+ /* Vertical Addressable Video is 720 lines.
+ * Vertical Blanking is 30 lines.
+ */
+ [48] = 0xD0, [49] = 0x1E, [50] = 0x20,
+
+ [51] = 110u, /* Horizontal Front Porch in pixels */
+ [52] = 40u, /* Horizontal Sync Pulse Width in pixels */
+ [53] = 0x55, /* Vertical Front Porch is 5 lines */
+ [54] = 0x00, /* Vertical Sync Pulse Width is 5 lines */
+
+ /* Image size: 1039mm x 584mm */
+ [55] = 0x0F, [56] = 0x48, [57] = 0x42,
+
+ /* Horizontal and Vertical Border Size is 0 px */
+ [58] = 0u, [59] = 0u,
+
+ /* Timing is Non-Interlaced Video
+ * Stereo Video is not supported
+ * Digital Separate Syncs are required
+ */
+ [60] = 0x1E,
+
+ /* Descriptor Block 7 [18 Bytes] */
+
+ [61] = EDID_PIXEL_CLOCK(27000000u) & 0xFF,
+ [62] = (EDID_PIXEL_CLOCK(27000000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1440px.
+ * Horizontal Blanking is 276 px.
+ */
+ [63] = 0xA0, [64] = 0x14, [65] = 0x51,
+
+ /* Vertical Addressable Video is 240 lines.
+ * Vertical Blanking is 23 lines.
+ */
+ [66] = 0xF0, [67] = 0x16, [68] = 0x00,
+
+ [69] = 38u, /* Horizontal Front Porch in pixels */
+ [70] = 124u, /* Horizontal Sync Pulse Width in pixels */
+ [71] = 0x43, /* Vertical Front Porch is 4 lines */
+ [72] = 0x00, /* Vertical Sync Pulse Width is 3 lines */
+
+ /* Image size: 1039mm x 584mm */
+ [73] = 0x0F, [74] = 0x48, [75] = 0x42,
+
+ /* Horizontal and Vertical Border Size is 0 px */
+ [76] = 0u, [77] = 0u,
+
+ /* Timing is Interlaced Video
+ * Stereo Video is not supported
+ * Digital Separate Syncs are required
+ */
+ [78] = 0x18,
+
+ /* Descriptor Block 8 [18 Bytes] */
+
+ [79] = EDID_PIXEL_CLOCK(27027000u) & 0xFF,
+ [80] = (EDID_PIXEL_CLOCK(27027000u) >> 8) & 0xFF,
+
+ /* Horizontal Addressable Video is 1440px.
+ * Horizontal Blanking is 276 px.
+ */
+ [81] = 0xA0, [82] = 0x14, [83] = 0x51,
+
+ /* Vertical Addressable Video is 240 lines.
+ * Vertical Blanking is 23 lines.
+ */
+ [84] = 0xF0, [85] = 0x16, [86] = 0x00,
+
+ [87] = 38u, /* Horizontal Front Porch in pixels */
+ [88] = 124u, /* Horizontal Sync Pulse Width in pixels */
+ [89] = 0x43, /* Vertical Front Porch is 4 lines */
+ [90] = 0x00, /* Vertical Sync Pulse Width is 3 lines */
+
+ /* Image size: 1039mm x 584mm */
+ [91] = 0x0F, [92] = 0x48, [93] = 0x42,
+
+ /* Horizontal and Vertical Border Size is 0 px */
+ [94] = 0u, [95] = 0u,
+
+ /* Timing is Interlaced Video
+ * Stereo Video is not supported
+ * Digital Separate Syncs are required
+ */
+ [96] = 0x98,
+
+ [97 ... 126] = 0,
+ };
+
+ ext[127] = get_raw_edid_checksum(ext);
+
+ *state = malloc(sizeof(struct test_state));
+
+ struct test_state ts = {
+ .data_size = sizeof(raw) + sizeof(ext),
+ .data = malloc(sizeof(raw) + sizeof(ext))
+ };
+
+ memcpy(ts.data, &raw, sizeof(raw));
+ memcpy(ts.data + sizeof(raw), &ext[0], sizeof(ext));
+
+ memcpy(*state, &ts, sizeof(ts));
+
+ return 0;
+}
+
+static void test_decode_edid_it_dtv_frame_with_extension(void **state)
+{
+ struct edid out;
+ struct test_state *ts = *state;
+
+ /* In real-life situations frames often are not 100% conformant,
+ * but are at least correct when it comes to key data fields.
+ */
+ assert_int_equal(EDID_CONFORMANT,
+ decode_edid((unsigned char *)ts->data, ts->data_size, &out));
+
+ assert_int_equal(32, out.framebuffer_bits_per_pixel);
+ assert_int_equal(8, out.panel_bits_per_color);
+ assert_int_equal(24, out.panel_bits_per_pixel);
+ assert_int_equal(0, out.link_clock);
+ assert_int_equal(1360, out.x_resolution);
+ assert_int_equal(768, out.y_resolution);
+ assert_int_equal(5440, out.bytes_per_line);
+ assert_int_equal(1, out.hdmi_monitor_detected);
+ assert_int_equal(0, strnlen(out.ascii_string, ARRAY_SIZE(out.ascii_string)));
+ assert_string_equal(out.manufacturer_name, EDID_MANUFACTURER_NAME);
+
+ /* Mode */
+ assert_null(out.mode.name);
+ assert_int_equal(85500, out.mode.pixel_clock);
+ assert_int_equal(0, out.mode.lvds_dual_channel);
+ assert_int_equal(0, out.mode.refresh);
+ assert_int_equal(1360, out.mode.ha);
+ assert_int_equal(432, out.mode.hbl);
+ assert_int_equal(64, out.mode.hso);
+ assert_int_equal(112, out.mode.hspw);
+ assert_int_equal(0, out.mode.hborder);
+ assert_int_equal(768, out.mode.va);
+ assert_int_equal(27, out.mode.vbl);
+ assert_int_equal(3, out.mode.vso);
+ assert_int_equal(0, out.mode.vborder);
+ assert_int_equal(43, out.mode.phsync);
+ assert_int_equal(43, out.mode.pvsync);
+ assert_int_equal(0, out.mode.x_mm);
+ assert_int_equal(0, out.mode.y_mm);
+
+ assert_int_equal(1, out.mode_is_supported[EDID_MODE_640x480_60Hz]);
+ assert_int_equal(0, out.mode_is_supported[EDID_MODE_720x480_60Hz]);
+ assert_int_equal(0, out.mode_is_supported[EDID_MODE_1280x720_60Hz]);
+ assert_int_equal(0, out.mode_is_supported[EDID_MODE_1920x1080_60Hz]);
+}
+
+static int teardown_edid_test(void **state)
+{
+ struct test_state *ts;
+
+ if (*state == NULL)
+ return 0;
+
+ ts = (struct test_state *)*state;
+
+ free(ts->data);
+ free(ts);
+
+ return 0;
+}
+
+static void test_edid_set_framebuffer_bits_per_pixel(void **state)
+{
+ struct edid out;
+ struct test_state *ts = *state;
+
+ decode_edid((unsigned char *)ts->data, ts->data_size, &out);
+
+ edid_set_framebuffer_bits_per_pixel(&out, 16, 2);
+
+ assert_int_equal(16, out.framebuffer_bits_per_pixel);
+ assert_int_equal(out.mode.ha * 2, out.bytes_per_line);
+ assert_int_equal(out.bytes_per_line / (16 / 8), out.x_resolution);
+ assert_int_equal(out.mode.va, out.y_resolution);
+
+ edid_set_framebuffer_bits_per_pixel(&out, 24, 4);
+
+ assert_int_equal(24, out.framebuffer_bits_per_pixel);
+ assert_int_equal(out.mode.ha * 3, out.bytes_per_line);
+ assert_int_equal(out.bytes_per_line / (24 / 8), out.x_resolution);
+ assert_int_equal(out.mode.va, out.y_resolution);
+
+ edid_set_framebuffer_bits_per_pixel(&out, 32, 4);
+
+ assert_int_equal(32, out.framebuffer_bits_per_pixel);
+ assert_int_equal(out.mode.ha * 4, out.bytes_per_line);
+ assert_int_equal(out.bytes_per_line / (32 / 8), out.x_resolution);
+ assert_int_equal(out.mode.va, out.y_resolution);
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_decode_edid_no_edid),
+ cmocka_unit_test(test_decode_edid_invalid_header),
+ cmocka_unit_test_setup_teardown(test_decode_edid_basic_frame,
+ setup_decode_edid_basic_frame,
+ teardown_edid_test),
+ cmocka_unit_test_setup_teardown(test_decode_edid_dtv_frame_with_extension,
+ setup_decode_edid_dtv_frame_with_extension,
+ teardown_edid_test),
+ cmocka_unit_test_setup_teardown(test_decode_edid_it_dtv_frame_with_extension,
+ setup_decode_edid_it_dtv_frame_with_extension,
+ teardown_edid_test),
+ cmocka_unit_test_setup_teardown(test_edid_set_framebuffer_bits_per_pixel,
+ setup_decode_edid_basic_frame,
+ teardown_edid_test),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
+