<div dir="ltr">EDID parsing should probably be moved out of compositor-drm since other backends can provide EDIDs too.<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, May 2, 2013 at 10:38 PM, Richard Hughes <span dir="ltr"><<a href="mailto:hughsient@gmail.com" target="_blank">hughsient@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This code was originally written by Soren Sandmann <<a href="mailto:sandmann@redhat.com">sandmann@redhat.com</a>> and was<br>

found here: <a href="http://people.gnome.org/~ssp/randr/edid-parse.c" target="_blank">http://people.gnome.org/~ssp/randr/edid-parse.c</a><br>
<br>
The code has been in use in gnome-settings-daemon for a couple of years now and<br>
is used to generate an Auto-EDID ICC profile if the screen has not been profiled<br>
with a calibration device.<br>
<br>
This will be used by the CMS plugins in the future, and so it makes sense being<br>
common code in compositor-drm.<br>
---<br>
 src/compositor-drm.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++<br>
 1 file changed, 56 insertions(+)<br>
<br>
diff --git a/src/compositor-drm.c b/src/compositor-drm.c<br>
index f39096e..e4a1919 100644<br>
--- a/src/compositor-drm.c<br>
+++ b/src/compositor-drm.c<br>
@@ -136,11 +136,22 @@ struct drm_fb {<br>
        void *map;<br>
 };<br>
<br>
+struct drm_color_Yxy {<br>
+       double Y;<br>
+       double x;<br>
+       double y;<br>
+};<br>
+<br>
 struct drm_edid {<br>
        char eisa_id[13];<br>
        char monitor_name[13];<br>
        char pnp_id[5];<br>
        char serial_number[13];<br>
+       struct drm_color_Yxy whitepoint;<br>
+       struct drm_color_Yxy primary_red;<br>
+       struct drm_color_Yxy primary_green;<br>
+       struct drm_color_Yxy primary_blue;<br>
+       double gamma;<br>
 };<br>
<br>
 struct drm_output {<br>
@@ -1558,6 +1569,31 @@ edid_parse_string(const uint8_t *data, char text[])<br>
 #define EDID_OFFSET_SERIAL                             0x0c<br>
<br>
 static int<br>
+edid_get_bit(int in, int bit)<br>
+{<br>
+       return (in & (1 << bit)) >> bit;<br>
+}<br>
+<br>
+static int<br>
+edid_get_bits(int in, int begin, int end)<br>
+{<br>
+       int mask = (1 << (end - begin + 1)) - 1;<br>
+       return (in >> begin) & mask;<br>
+}<br>
+<br>
+static double<br>
+edid_decode_fraction(int high, int low)<br>
+{<br>
+       double result = 0.0;<br>
+       int i;<br>
+<br>
+       high = (high << 2) | low;<br>
+       for (i = 0; i < 10; ++i)<br>
+               result += edid_get_bit(high, i) * pow(2, i - 10);<br>
+       return result;<br>
+}<br>
+<br>
+static int<br>
 edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)<br>
 {<br>
        int i;<br>
@@ -1579,6 +1615,26 @@ edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)<br>
        edid->pnp_id[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;<br>
        edid->pnp_id[3] = '\0';<br>
<br>
+       /* get native gamma */<br>
+       if (data[0x17] == 0xff)<br>
+               edid->gamma = -1.0;<br>
+       else<br>
+               edid->gamma = (data[0x17] + 100.0) / 100.0;<br>
+<br>
+       /* get primaries and whitepoint */<br>
+       edid->primary_red.Y = 1.0f;<br>
+       edid->primary_red.x = edid_decode_fraction(data[0x1b], edid_get_bits(data[0x19], 6, 7));<br>
+       edid->primary_red.y = edid_decode_fraction(data[0x1c], edid_get_bits(data[0x19], 5, 4));<br>
+       edid->primary_green.Y = 1.0f;<br>
+       edid->primary_green.x = edid_decode_fraction(data[0x1d], edid_get_bits(data[0x19], 2, 3));<br>
+       edid->primary_green.y = edid_decode_fraction(data[0x1e], edid_get_bits(data[0x19], 0, 1));<br>
+       edid->primary_blue.Y = 1.0f;<br>
+       edid->primary_blue.x = edid_decode_fraction(data[0x1f], edid_get_bits(data[0x1a], 6, 7));<br>
+       edid->primary_blue.y = edid_decode_fraction(data[0x20], edid_get_bits(data[0x1a], 4, 5));<br>
+       edid->whitepoint.Y = 1.0f;<br>
+       edid->whitepoint.x = edid_decode_fraction(data[0x21], edid_get_bits(data[0x1a], 2, 3));<br>
+       edid->whitepoint.y = edid_decode_fraction(data[0x22], edid_get_bits(data[0x1a], 0, 1));<br>
+<br>
        /* maybe there isn't a ASCII serial number descriptor, so use this instead */<br>
        serial_number = (uint32_t) data[EDID_OFFSET_SERIAL + 0];<br>
        serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.2.1<br>
<br>
_______________________________________________<br>
wayland-devel mailing list<br>
<a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
</font></span></blockquote></div><br></div>