[igt-dev] [v4 i-g-t 1/3] tests/kms_color_helper: Read deep-color capability from EDID

Bhanuprakash Modem bhanuprakash.modem at intel.com
Tue Feb 1 09:05:28 UTC 2022


Add a helper function to read the panel's deep-color capability
from EDID.

For EDID 1.3, we need to read deep color capability from Vendor
Specific Data Block, and for EDID 1.4 read bit depth from Video
Input Definition.

Vendor Specific Data Block for "HDMI Licensing LLC":
---------------------------------------------------------
| Byte|  Bit  |        Description                      |
---------------------------------------------------------
|     | Bit 6 |   16-bit-per-channel deep color (48-bit)|
|  6  | Bit 5 |   12-bit-per-channel deep color (36-bit)|
|     | Bit 4 |   10-bit-per-channel deep color (30-bit)|
---------------------------------------------------------

Video Input Definition (1-byte):
    * Video Signal Interface: Bit 7 (1:Digital, 0:Analog)
    * Color Bit Depth: Bits 6 → 4
-----------------------------------------------------
| 7 | 6 5 4 | 3 2 1 0 | Color Bit Depth: Bits 6 → 4 |
|---|-------|---------|-----------------------------|
| 1 | 0 0 0 | x x x x | Color Bit Depth is undefined|
| 1 | 0 0 1 | x x x x | 6 Bits per Primary Color    |
| 1 | 0 1 0 | x x x x | 8 Bits per Primary Color    |
| 1 | 0 1 1 | x x x x | 10 Bits per Primary Color   |
| 1 | 1 0 0 | x x x x | 12 Bits per Primary Color   |
| 1 | 1 0 1 | x x x x | 14 Bits per Primary Color   |
| 1 | 1 1 0 | x x x x | 16 Bits per Primary Color   |
| 1 | 1 1 1 | x x x x | Reserved (Do Not Use)       |
-----------------------------------------------------
For deep-color we need atleast 10-bits.

V2:
* Add EDID 1.3 support
V3:
* Fix reading VSDB flags1 for deep-color
V4:
* Separate functions for EDID 1.3 & EDID 1.4
* Other minor cleanups

Cc: Uma Shankar <uma.shankar at intel.com>
Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
---
 lib/igt_edid.c           | 54 ++++++++++++++++++++++++++++++++++++++++
 lib/igt_edid.h           |  2 ++
 tests/kms_color_helper.c | 52 ++++++++++++++++++++++++++++++++++++++
 tests/kms_color_helper.h |  3 +++
 4 files changed, 111 insertions(+)

diff --git a/lib/igt_edid.c b/lib/igt_edid.c
index df346c4c8c..8fc3d453bf 100644
--- a/lib/igt_edid.c
+++ b/lib/igt_edid.c
@@ -349,6 +349,60 @@ size_t edid_get_size(const struct edid *edid)
 	       edid->extensions_len * sizeof(struct edid_ext);
 }
 
+/**
+ * edid_get_deep_color_from_vsdb: return the Deep Color info from Vender
+ * Specific Data Block (VSDB), if VSDB not found then return zero.
+ */
+uint8_t edid_get_deep_color_from_vsdb(const struct edid *edid)
+{
+	const uint8_t offset = offsetof(struct edid_cea, data);
+	uint8_t deep_color, i = 0;
+
+	/* Read from vendor specific data block first, if vsdb not found
+	 * return 0.
+	 */
+	for (i = 0; i < edid->extensions_len; i++) {
+		uint32_t index = 0;
+		uint8_t dtd_offset = edid->extensions[i].data.cea.dtd_start;
+
+		if (edid->extensions[i].tag != EDID_EXT_CEA)
+			continue;
+
+		do {
+			struct edid_cea_data_block * vsdb =
+				(struct edid_cea_data_block *) &edid->extensions[i].data.cea.data[index];
+			uint8_t vsdb_length = (vsdb->type_len & 0x1f);
+			uint8_t vsdb_type = (vsdb->type_len & (7 << 5)) >> 5;
+
+			if (vsdb_type == EDID_CEA_DATA_VENDOR_SPECIFIC)
+				deep_color = vsdb->data.vsdbs[0].data.hdmi.flags1;
+
+			if (deep_color & (7 << 4))
+				return deep_color;
+
+			index += (vsdb_length + sizeof(vsdb->type_len));
+		} while (index < dtd_offset - offset);
+	}
+
+	return 0;
+}
+
+/**
+ * edid_get_bit_depth: Read from the Video Input Definition and return the
+ * Color Bit Depth if Input is a Digital Video, else return zero.
+ */
+uint8_t edid_get_bit_depth_from_vid(const struct edid *edid)
+{
+	/*
+	 * Video Signal Interface: Bit 7 (1:Digital, 0:Analog)
+	 * Color Bit Depth: Bits 6 → 4
+	 */
+	if (!(edid->input & (1 << 7)))
+		return 0;
+
+	return ((edid->input & (7 << 4)) >> 4);
+}
+
 /**
  * cea_sad_init_pcm:
  * @channels: the number of supported channels (max. 8)
diff --git a/lib/igt_edid.h b/lib/igt_edid.h
index aac2f4a208..a9251d689e 100644
--- a/lib/igt_edid.h
+++ b/lib/igt_edid.h
@@ -377,6 +377,8 @@ void edid_update_checksum(struct edid *edid);
 void base_edid_update_checksum(struct edid *edid);
 size_t edid_get_size(const struct edid *edid);
 void edid_get_mfg(const struct edid *edid, char out[static 3]);
+uint8_t edid_get_deep_color_from_vsdb(const struct edid *edid);
+uint8_t edid_get_bit_depth_from_vid(const struct edid *edid);
 void detailed_timing_set_mode(struct detailed_timing *dt, drmModeModeInfo *mode,
 			      int width_mm, int height_mm);
 void detailed_timing_set_monitor_range_mode(struct detailed_timing *dt,
diff --git a/tests/kms_color_helper.c b/tests/kms_color_helper.c
index d71e7bb2e6..6b3af02b00 100644
--- a/tests/kms_color_helper.c
+++ b/tests/kms_color_helper.c
@@ -24,6 +24,58 @@
 
 #include "kms_color_helper.h"
 
+bool
+is_panel_supports_deep_color(int fd, drmModeConnector *connector)
+{
+	uint64_t edid_blob_id;
+	uint8_t bit_depth, rev;
+	const struct edid *edid;
+	bool result;
+	drmModePropertyBlobPtr edid_blob = NULL;
+
+	igt_assert(kmstest_get_property(fd, connector->connector_id,
+					DRM_MODE_OBJECT_CONNECTOR, "EDID", NULL,
+					&edid_blob_id, NULL));
+	edid_blob = drmModeGetPropertyBlob(fd, edid_blob_id);
+	igt_require_f(edid_blob, "EDID blob is NULL\n");
+
+	edid = (const struct edid *) edid_blob->data;
+	rev = edid->revision;
+
+	if (rev >= 4) {
+		bit_depth = edid_get_bit_depth_from_vid(edid);
+
+		if (bit_depth > 0 && bit_depth < 7)
+			igt_info("Max supported bit depth: %d\n", ((bit_depth << 1) + 4));
+		else
+			igt_info("Max supported bit depth: Undefined\n");
+
+		result = (bit_depth >= 3) && (bit_depth < 7);
+	} else {
+		bit_depth = edid_get_deep_color_from_vsdb(edid);
+
+		if (bit_depth &	HDMI_VSDB_DC_48BIT)
+			igt_info("Max supported bit depth: 16\n");
+		else if (bit_depth & HDMI_VSDB_DC_36BIT)
+			igt_info("Max supported bit depth: 12\n");
+		else if (bit_depth & HDMI_VSDB_DC_30BIT)
+			igt_info("Max supported bit depth: 10\n");
+		else
+			igt_info("Max supported bit depth: Undefined\n");
+
+		result = !!(bit_depth & (7 << 4));
+	}
+	drmModeFreePropertyBlob(edid_blob);
+
+	return result;
+}
+
+bool is_max_bpc_supported(igt_output_t *output)
+{
+	return igt_output_has_prop(output, IGT_CONNECTOR_MAX_BPC) &&
+		igt_output_get_prop(output, IGT_CONNECTOR_MAX_BPC);
+}
+
 void paint_gradient_rectangles(data_t *data,
 			       drmModeModeInfo *mode,
 			       color_t *colors,
diff --git a/tests/kms_color_helper.h b/tests/kms_color_helper.h
index bb6f0054f3..992087ac9c 100644
--- a/tests/kms_color_helper.h
+++ b/tests/kms_color_helper.h
@@ -36,6 +36,7 @@
 #include "drm.h"
 #include "drmtest.h"
 #include "igt.h"
+#include "igt_edid.h"
 
 
 /* Internal */
@@ -64,6 +65,8 @@ typedef struct {
 	color_t coeffs[];
 } gamma_lut_t;
 
+bool is_panel_supports_deep_color(int fd, drmModeConnector *connector);
+bool is_max_bpc_supported(igt_output_t *output);
 void paint_gradient_rectangles(data_t *data,
 			       drmModeModeInfo *mode,
 			       color_t *colors,
-- 
2.35.0



More information about the igt-dev mailing list