st/xorg: attach EDID to outputs
[mesa.git] / src / gallium / state_trackers / xorg / xorg_output.c
index 61206ed751ca9385c6d23e34c82b031c3f86f57c..b183cdf9dc1df8ca2085f0a3cd32d4f97b8d328c 100644 (file)
@@ -32,6 +32,7 @@
 #include <xf86.h>
 #include <xf86i2c.h>
 #include <xf86Crtc.h>
+#include <xf86DDC.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -54,7 +55,8 @@
 struct output_private
 {
     drmModeConnectorPtr drm_connector;
-
+    drmModePropertyBlobPtr edid_blob;
+    int fd;
     int c;
 };
 
@@ -122,13 +124,43 @@ output_get_modes(xf86OutputPtr output)
     struct output_private *priv = output->driver_private;
     drmModeConnectorPtr drm_connector = priv->drm_connector;
     drmModeModeInfoPtr drm_mode = NULL;
+    drmModePropertyPtr props = NULL;
+    xf86MonPtr ddc_mon = NULL;
     DisplayModePtr modes = NULL, mode = NULL;
     int i;
 
+       for (i = 0; i < drm_connector->count_props; i++) {
+               props = drmModeGetProperty(priv->fd, drm_connector->props[i]);
+               if (!props)
+                       continue;
+
+               if (!(props->flags & DRM_MODE_PROP_BLOB))
+                       goto out_free;
+
+               if (!strcmp(props->name, "EDID")) {
+                       if (priv->edid_blob)
+                               drmModeFreePropertyBlob(priv->edid_blob);
+                       priv->edid_blob = drmModeGetPropertyBlob(priv->fd,
+                                                         drm_connector->prop_values[i]);
+               }
+
+               out_free:
+               drmModeFreeProperty(props);
+       }
+
+       if (priv->edid_blob) {
+               ddc_mon = xf86InterpretEDID(output->scrn->scrnIndex,
+                                                                       priv->edid_blob->data);
+
+               if (ddc_mon && priv->edid_blob->length > 128)
+                       ddc_mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
+       }
+       xf86OutputSetEDID(output, ddc_mon);
+
     for (i = 0; i < drm_connector->count_modes; i++) {
        drm_mode = &drm_connector->modes[i];
        if (drm_mode) {
-           mode = xcalloc(1, sizeof(DisplayModeRec));
+           mode = calloc(1, sizeof(DisplayModeRec));
            if (!mode)
                continue;
            mode->Clock = drm_mode->clock;
@@ -194,8 +226,10 @@ static void
 output_destroy(xf86OutputPtr output)
 {
     struct output_private *priv = output->driver_private;
+    if (priv->edid_blob)
+               drmModeFreePropertyBlob(priv->edid_blob);
     drmModeFreeConnector(priv->drm_connector);
-    xfree(priv);
+    free(priv);
     output->driver_private = NULL;
 }
 
@@ -262,14 +296,14 @@ xorg_output_init(ScrnInfoPtr pScrn)
                 drm_connector->connector_type_id);
 
 
-       priv = xcalloc(sizeof(*priv), 1);
+       priv = calloc(sizeof(*priv), 1);
        if (!priv) {
            continue;
        }
 
        output = xf86OutputCreate(pScrn, &output_funcs, name);
        if (!output) {
-           xfree(priv);
+           free(priv);
            continue;
        }
 
@@ -283,6 +317,7 @@ xorg_output_init(ScrnInfoPtr pScrn)
        }
        priv->c = c;
        priv->drm_connector = drm_connector;
+       priv->fd = ms->fd;
        output->driver_private = priv;
        output->subpixel_order = SubPixelHorizontalRGB;
        output->interlaceAllowed = FALSE;