---
 src/Makefile.am      |   2 +
 src/compositor-drm.c | 180 +--------------------------------------------------
 src/compositor.c     |  21 ++++++
 src/compositor.h     |   5 ++
 src/edid.c           | 175 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/edid.h           |  48 ++++++++++++++
 6 files changed, 254 insertions(+), 177 deletions(-)
 create mode 100644 src/edid.c
 create mode 100644 src/edid.h

diff --git a/src/Makefile.am b/src/Makefile.am
index d33ebc5..1e8965c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,6 +18,8 @@ weston_SOURCES =                              \
        log.c                                   \
        compositor.c                            \
        compositor.h                            \
+       edid.c                                  \
+       edid.h                                  \
        filter.c                                \
        filter.h                                \
        screenshooter.c                         \
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index e4a1919..c507e72 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -29,7 +29,6 @@
 
 #include <errno.h>
 #include <stdlib.h>
-#include <ctype.h>
 #include <string.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -136,24 +135,6 @@ struct drm_fb {
        void *map;
 };
 
-struct drm_color_Yxy {
-       double Y;
-       double x;
-       double y;
-};
-
-struct drm_edid {
-       char eisa_id[13];
-       char monitor_name[13];
-       char pnp_id[5];
-       char serial_number[13];
-       struct drm_color_Yxy whitepoint;
-       struct drm_color_Yxy primary_red;
-       struct drm_color_Yxy primary_green;
-       struct drm_color_Yxy primary_blue;
-       double gamma;
-};
-
 struct drm_output {
        struct weston_output   base;
 
@@ -161,7 +142,6 @@ struct drm_output {
        int pipe;
        uint32_t connector_id;
        drmModeCrtcPtr original_crtc;
-       struct drm_edid edid;
 
        int vblank_pending;
        int page_flip_pending;
@@ -1529,146 +1509,6 @@ drm_output_fini_pixman(struct drm_output *output)
 }
 
 static void
-edid_parse_string(const uint8_t *data, char text[])
-{
-       int i;
-       int replaced = 0;
-
-       /* this is always 12 bytes, but we can't guarantee it's null
-        * terminated or not junk. */
-       strncpy(text, (const char *) data, 12);
-
-       /* remove insane chars */
-       for (i = 0; text[i] != '\0'; i++) {
-               if (text[i] == '\n' ||
-                   text[i] == '\r') {
-                       text[i] = '\0';
-                       break;
-               }
-       }
-
-       /* ensure string is printable */
-       for (i = 0; text[i] != '\0'; i++) {
-               if (!isprint(text[i])) {
-                       text[i] = '-';
-                       replaced++;
-               }
-       }
-
-       /* if the string is random junk, ignore the string */
-       if (replaced > 4)
-               text[0] = '\0';
-}
-
-#define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING       0xfe
-#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME           0xfc
-#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER  0xff
-#define EDID_OFFSET_DATA_BLOCKS                                0x36
-#define EDID_OFFSET_LAST_BLOCK                         0x6c
-#define EDID_OFFSET_PNPID                              0x08
-#define EDID_OFFSET_SERIAL                             0x0c
-
-static int
-edid_get_bit(int in, int bit)
-{
-       return (in & (1 << bit)) >> bit;
-}
-
-static int
-edid_get_bits(int in, int begin, int end)
-{
-       int mask = (1 << (end - begin + 1)) - 1;
-       return (in >> begin) & mask;
-}
-
-static double
-edid_decode_fraction(int high, int low)
-{
-       double result = 0.0;
-       int i;
-
-       high = (high << 2) | low;
-       for (i = 0; i < 10; ++i)
-               result += edid_get_bit(high, i) * pow(2, i - 10);
-       return result;
-}
-
-static int
-edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
-{
-       int i;
-       uint32_t serial_number;
-
-       /* check header */
-       if (length < 128)
-               return -1;
-       if (data[0] != 0x00 || data[1] != 0xff)
-               return -1;
-
-       /* decode the PNP ID from three 5 bit words packed into 2 bytes
-        * /--08--\/--09--\
-        * 7654321076543210
-        * |\---/\---/\---/
-        * R  C1   C2   C3 */
-       edid->pnp_id[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
-       edid->pnp_id[1] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) + 
((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
-       edid->pnp_id[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
-       edid->pnp_id[3] = '\0';
-
-       /* get native gamma */
-       if (data[0x17] == 0xff)
-               edid->gamma = -1.0;
-       else
-               edid->gamma = (data[0x17] + 100.0) / 100.0;
-
-       /* get primaries and whitepoint */
-       edid->primary_red.Y = 1.0f;
-       edid->primary_red.x = edid_decode_fraction(data[0x1b], 
edid_get_bits(data[0x19], 6, 7));
-       edid->primary_red.y = edid_decode_fraction(data[0x1c], 
edid_get_bits(data[0x19], 5, 4));
-       edid->primary_green.Y = 1.0f;
-       edid->primary_green.x = edid_decode_fraction(data[0x1d], 
edid_get_bits(data[0x19], 2, 3));
-       edid->primary_green.y = edid_decode_fraction(data[0x1e], 
edid_get_bits(data[0x19], 0, 1));
-       edid->primary_blue.Y = 1.0f;
-       edid->primary_blue.x = edid_decode_fraction(data[0x1f], 
edid_get_bits(data[0x1a], 6, 7));
-       edid->primary_blue.y = edid_decode_fraction(data[0x20], 
edid_get_bits(data[0x1a], 4, 5));
-       edid->whitepoint.Y = 1.0f;
-       edid->whitepoint.x = edid_decode_fraction(data[0x21], 
edid_get_bits(data[0x1a], 2, 3));
-       edid->whitepoint.y = edid_decode_fraction(data[0x22], 
edid_get_bits(data[0x1a], 0, 1));
-
-       /* maybe there isn't a ASCII serial number descriptor, so use this 
instead */
-       serial_number = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
-       serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
-       serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
-       serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
-       if (serial_number > 0)
-               sprintf(edid->serial_number, "%lu", (unsigned long) 
serial_number);
-
-       /* parse EDID data */
-       for (i = EDID_OFFSET_DATA_BLOCKS;
-            i <= EDID_OFFSET_LAST_BLOCK;
-            i += 18) {
-               /* ignore pixel clock data */
-               if (data[i] != 0)
-                       continue;
-               if (data[i+2] != 0)
-                       continue;
-
-               /* any useful blocks? */
-               if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME) {
-                       edid_parse_string(&data[i+5],
-                                         edid->monitor_name);
-               } else if (data[i+3] == 
EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) {
-                       edid_parse_string(&data[i+5],
-                                         edid->serial_number);
-               } else if (data[i+3] == 
EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING) {
-                       edid_parse_string(&data[i+5],
-                                         edid->eisa_id);
-               }
-       }
-       return 0;
-}
-
-static void
 find_and_parse_output_edid(struct drm_compositor *ec,
                           struct drm_output *output,
                           drmModeConnector *connector)
@@ -1676,7 +1516,6 @@ find_and_parse_output_edid(struct drm_compositor *ec,
        drmModePropertyBlobPtr edid_blob = NULL;
        drmModePropertyPtr property;
        int i;
-       int rc;
 
        for (i = 0; i < connector->count_props && !edid_blob; i++) {
                property = drmModeGetProperty(ec->drm.fd, connector->props[i]);
@@ -1691,22 +1530,9 @@ find_and_parse_output_edid(struct drm_compositor *ec,
        }
        if (!edid_blob)
                return;
-
-       rc = edid_parse(&output->edid,
-                       edid_blob->data,
-                       edid_blob->length);
-       if (!rc) {
-               weston_log("EDID data '%s', '%s', '%s'\n",
-                          output->edid.pnp_id,
-                          output->edid.monitor_name,
-                          output->edid.serial_number);
-               if (output->edid.pnp_id[0] != '\0')
-                       output->base.make = output->edid.pnp_id;
-               if (output->edid.monitor_name[0] != '\0')
-                       output->base.model = output->edid.monitor_name;
-               if (output->edid.serial_number[0] != '\0')
-                       output->base.serial_number = output->edid.serial_number;
-       }
+       weston_output_set_edid(&output->base,
+                              edid_blob->data,
+                              edid_blob->length);
        drmModeFreePropertyBlob(edid_blob);
 }
 
diff --git a/src/compositor.c b/src/compositor.c
index a6610e6..21caa7e 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -2975,6 +2975,27 @@ weston_output_compute_transform(struct weston_output 
*output)
 }
 
 WL_EXPORT void
+weston_output_set_edid(struct weston_output *output,
+                      const uint8_t *data, size_t length)
+{
+       int rc;
+
+       rc = weston_edid_parse(&output->edid, data, length);
+       if (!rc) {
+               weston_log("EDID data '%s', '%s', '%s'\n",
+                          output->edid.pnp_id,
+                          output->edid.monitor_name,
+                          output->edid.serial_number);
+               if (output->edid.pnp_id[0] != '\0')
+                       output->make = output->edid.pnp_id;
+               if (output->edid.monitor_name[0] != '\0')
+                       output->model = output->edid.monitor_name;
+               if (output->edid.serial_number[0] != '\0')
+                       output->serial_number = output->edid.serial_number;
+       }
+}
+
+WL_EXPORT void
 weston_output_update_matrix(struct weston_output *output)
 {
        float magnification;
diff --git a/src/compositor.h b/src/compositor.h
index 7da6c48..6f15350 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -34,6 +34,7 @@ extern "C" {
 
 #include "version.h"
 #include "matrix.h"
+#include "edid.h"
 #include "config-parser.h"
 
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
@@ -181,6 +182,7 @@ struct weston_output {
        int disable_planes;
 
        char *make, *model, *serial_number;
+       struct weston_edid_info edid;
        uint32_t subpixel;
        uint32_t transform;
        
@@ -766,6 +768,9 @@ weston_output_update_zoom(struct weston_output *output, 
uint32_t type);
 void
 weston_output_update_matrix(struct weston_output *output);
 void
+weston_output_set_edid(struct weston_output *output,
+                      const uint8_t *data, size_t length);
+void
 weston_output_move(struct weston_output *output, int x, int y);
 void
 weston_output_init(struct weston_output *output, struct weston_compositor *c,
diff --git a/src/edid.c b/src/edid.c
new file mode 100644
index 0000000..f591e74
--- /dev/null
+++ b/src/edid.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright © 2013 Richard Hughes
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "edid.h"
+
+static void
+weston_edid_parse_string(const uint8_t *data, char text[])
+{
+       int i;
+       int replaced = 0;
+
+       /* this is always 12 bytes, but we can't guarantee it's null
+        * terminated or not junk. */
+       strncpy(text, (const char *) data, 12);
+
+       /* remove insane chars */
+       for (i = 0; text[i] != '\0'; i++) {
+               if (text[i] == '\n' ||
+                   text[i] == '\r') {
+                       text[i] = '\0';
+                       break;
+               }
+       }
+
+       /* ensure string is printable */
+       for (i = 0; text[i] != '\0'; i++) {
+               if (!isprint(text[i])) {
+                       text[i] = '-';
+                       replaced++;
+               }
+       }
+
+       /* if the string is random junk, ignore the string */
+       if (replaced > 4)
+               text[0] = '\0';
+}
+
+#define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING       0xfe
+#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME           0xfc
+#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER  0xff
+#define EDID_OFFSET_DATA_BLOCKS                                0x36
+#define EDID_OFFSET_LAST_BLOCK                         0x6c
+#define EDID_OFFSET_PNPID                              0x08
+#define EDID_OFFSET_SERIAL                             0x0c
+
+static int
+edid_get_bit(int in, int bit)
+{
+       return (in & (1 << bit)) >> bit;
+}
+
+static int
+edid_get_bits(int in, int begin, int end)
+{
+       int mask = (1 << (end - begin + 1)) - 1;
+       return (in >> begin) & mask;
+}
+
+static double
+edid_decode_fraction(int high, int low)
+{
+       double result = 0.0;
+       int i;
+
+       high = (high << 2) | low;
+       for (i = 0; i < 10; ++i)
+               result += edid_get_bit(high, i) * pow(2, i - 10);
+       return result;
+}
+
+int
+weston_edid_parse(struct weston_edid_info *edid,
+                 const uint8_t *data, size_t length)
+{
+       int i;
+       uint32_t serial_number;
+
+       /* check header */
+       if (length < 128)
+               return -1;
+       if (data[0] != 0x00 || data[1] != 0xff)
+               return -1;
+
+       /* decode the PNP ID from three 5 bit words packed into 2 bytes
+        * /--08--\/--09--\
+        * 7654321076543210
+        * |\---/\---/\---/
+        * R  C1   C2   C3 */
+       edid->pnp_id[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
+       edid->pnp_id[1] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) + 
((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
+       edid->pnp_id[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
+       edid->pnp_id[3] = '\0';
+
+       /* get native gamma */
+       if (data[0x17] == 0xff)
+               edid->gamma = -1.0;
+       else
+               edid->gamma = (data[0x17] + 100.0) / 100.0;
+
+       /* get primaries and whitepoint */
+       edid->primary_red.Y = 1.0f;
+       edid->primary_red.x = edid_decode_fraction(data[0x1b], 
edid_get_bits(data[0x19], 6, 7));
+       edid->primary_red.y = edid_decode_fraction(data[0x1c], 
edid_get_bits(data[0x19], 5, 4));
+       edid->primary_green.Y = 1.0f;
+       edid->primary_green.x = edid_decode_fraction(data[0x1d], 
edid_get_bits(data[0x19], 2, 3));
+       edid->primary_green.y = edid_decode_fraction(data[0x1e], 
edid_get_bits(data[0x19], 0, 1));
+       edid->primary_blue.Y = 1.0f;
+       edid->primary_blue.x = edid_decode_fraction(data[0x1f], 
edid_get_bits(data[0x1a], 6, 7));
+       edid->primary_blue.y = edid_decode_fraction(data[0x20], 
edid_get_bits(data[0x1a], 4, 5));
+       edid->whitepoint.Y = 1.0f;
+       edid->whitepoint.x = edid_decode_fraction(data[0x21], 
edid_get_bits(data[0x1a], 2, 3));
+       edid->whitepoint.y = edid_decode_fraction(data[0x22], 
edid_get_bits(data[0x1a], 0, 1));
+
+       /* maybe there isn't a ASCII serial number descriptor, so use this 
instead */
+       serial_number = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
+       serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
+       serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
+       serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
+       if (serial_number > 0)
+               sprintf(edid->serial_number, "%lu", (unsigned long) 
serial_number);
+
+       /* parse EDID data */
+       for (i = EDID_OFFSET_DATA_BLOCKS;
+            i <= EDID_OFFSET_LAST_BLOCK;
+            i += 18) {
+               /* ignore pixel clock data */
+               if (data[i] != 0)
+                       continue;
+               if (data[i+2] != 0)
+                       continue;
+
+               /* any useful blocks? */
+               if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME) {
+                       weston_edid_parse_string(&data[i+5],
+                                         edid->monitor_name);
+               } else if (data[i+3] == 
EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) {
+                       weston_edid_parse_string(&data[i+5],
+                                         edid->serial_number);
+               } else if (data[i+3] == 
EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING) {
+                       weston_edid_parse_string(&data[i+5],
+                                         edid->eisa_id);
+               }
+       }
+       return 0;
+}
diff --git a/src/edid.h b/src/edid.h
new file mode 100644
index 0000000..f5f7603
--- /dev/null
+++ b/src/edid.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2013 Richard Hughes
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _WESTON_EDID_H_
+#define _WESTON_EDID_H_
+
+struct weston_edid_color_Yxy {
+       double Y;
+       double x;
+       double y;
+};
+
+struct weston_edid_info {
+       char eisa_id[13];
+       char monitor_name[13];
+       char pnp_id[5];
+       char serial_number[13];
+       struct weston_edid_color_Yxy whitepoint;
+       struct weston_edid_color_Yxy primary_red;
+       struct weston_edid_color_Yxy primary_green;
+       struct weston_edid_color_Yxy primary_blue;
+       double gamma;
+};
+
+int
+weston_edid_parse(struct weston_edid_info *edid,
+                 const uint8_t *data, size_t length);
+
+#endif
-- 
1.8.2.1

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to