modesetting: fixup property setting and add connector property
authorDave Airlie <airlied@redhat.com>
Tue, 11 Dec 2007 05:56:48 +0000 (15:56 +1000)
committerDave Airlie <airlied@linux.ie>
Tue, 11 Dec 2007 05:56:48 +0000 (15:56 +1000)
libdrm/xf86drmMode.c
libdrm/xf86drmMode.h
linux-core/drm_crtc.c
linux-core/drm_crtc.h
linux-core/drm_drv.c
linux-core/intel_crt.c
linux-core/intel_lvds.c
linux-core/intel_sdvo.c
shared-core/drm.h
tests/mode/modetest.c

index 7e2683e..726c55a 100644 (file)
@@ -214,6 +214,8 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
 int drmModeRmFB(int fd, uint32_t bufferId)
 {
        return ioctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
+
+
 }
 
 drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
@@ -511,3 +513,19 @@ void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
        drmFree(ptr->data);
        drmFree(ptr);
 }
+
+int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id,
+                            uint64_t value)
+{
+       struct drm_mode_output_set_property osp;
+       int ret;
+
+       osp.output_id = output_id;
+       osp.prop_id = property_id;
+       osp.value = value;
+
+       if (ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp))
+               return ret;
+
+       return 0;
+}
index 6fcf6a1..05b61bc 100644 (file)
@@ -223,3 +223,5 @@ extern void drmModeFreeProperty(drmModePropertyPtr ptr);
 
 extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
 extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
+extern int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id,
+                                   uint64_t value);
index 871f899..e1b37c0 100644 (file)
 #include "drmP.h"
 #include "drm_crtc.h"
 
+struct drm_prop_enum_list {
+       int type;
+       char *name;
+};
+
+static struct drm_prop_enum_list drm_dpms_enum_list[] =
+{ { DPMSModeOn, "On" },
+  { DPMSModeStandby, "Standby" },
+  { DPMSModeSuspend, "Suspend" },
+  { DPMSModeOff, "Off" }
+};
+static struct drm_prop_enum_list drm_conn_enum_list[] = 
+{ { ConnectorVGA, "VGA" },
+  { ConnectorDVII, "DVI-I" },
+  { ConnectorDVID, "DVI-D" },
+  { ConnectorDVIA, "DVI-A" },
+  { ConnectorComposite, "Composite" },
+  { ConnectorSVIDEO, "SVIDEO" },
+  { ConnectorLVDS, "LVDS" },
+  { ConnectorComponent, "Component" },
+  { Connector9PinDIN, "9-pin DIN" },
+  { ConnectorDisplayPort, "DisplayPort" },
+  { ConnectorHDMIA, "HDMI Type A" },
+  { ConnectorHDMIB, "HDMI Type B" },
+};
+
+
 /**
  * drm_idr_get - allocate a new identifier
  * @dev: DRM device
@@ -709,6 +736,34 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
 }
 EXPORT_SYMBOL(drm_mode_destroy);
 
+static int drm_mode_create_standard_output_properties(struct drm_device *dev)
+{
+       int i;
+
+       dev->mode_config.edid_property =
+               drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE,
+                                   "EDID", 0);
+
+       dev->mode_config.dpms_property =
+               drm_property_create(dev, DRM_MODE_PROP_ENUM, "DPMS", 4);
+
+       for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++)
+               drm_property_add_enum(dev->mode_config.dpms_property, i, drm_dpms_enum_list[i].type, drm_dpms_enum_list[i].name);
+
+       dev->mode_config.connector_type_property =
+               drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE,
+                                   "Connector Type", 10);
+       for (i = 0; i < ARRAY_SIZE(drm_conn_enum_list); i++)
+               drm_property_add_enum(dev->mode_config.connector_type_property, i, drm_conn_enum_list[i].type, drm_conn_enum_list[i].name);
+
+       dev->mode_config.connector_num_property =
+               drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE,
+                                   "Connector ID", 2);
+       dev->mode_config.connector_num_property->values[0] = 0;
+       dev->mode_config.connector_num_property->values[1] = 20;
+       return 0;
+}
+
 /**
  * drm_mode_config_init - initialize DRM mode_configuration structure
  * @dev: DRM device
@@ -728,17 +783,8 @@ void drm_mode_config_init(struct drm_device *dev)
        INIT_LIST_HEAD(&dev->mode_config.property_list);
        INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
        idr_init(&dev->mode_config.crtc_idr);
-       dev->mode_config.edid_property = drm_property_create(dev,
-                                                            DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE,
-                                                            "EDID", 0);
-
-       dev->mode_config.dpms_property = drm_property_create(dev,
-                                                            DRM_MODE_PROP_ENUM,
-                                                            "DPMS", 4);
-       drm_property_add_enum(dev->mode_config.dpms_property, 0, DPMSModeOn, "On");
-       drm_property_add_enum(dev->mode_config.dpms_property, 1, DPMSModeStandby, "Standby");
-       drm_property_add_enum(dev->mode_config.dpms_property, 2, DPMSModeSuspend, "Suspend");
-       drm_property_add_enum(dev->mode_config.dpms_property, 3, DPMSModeOff, "Off");
+
+       drm_mode_create_standard_output_properties(dev);
        
 }
 EXPORT_SYMBOL(drm_mode_config_init);
@@ -2160,15 +2206,16 @@ int drm_mode_output_update_edid_property(struct drm_output *output, unsigned cha
 EXPORT_SYMBOL(drm_mode_output_update_edid_property);
 
 int drm_mode_output_property_set_ioctl(struct drm_device *dev,
-                          void *data, struct drm_file *file_priv)
+                                      void *data, struct drm_file *file_priv)
 {
        struct drm_mode_output_set_property *out_resp = data;
+       struct drm_property *property;
        struct drm_output *output;
        int ret = -EINVAL;
        int i;
 
        mutex_lock(&dev->mode_config.mutex);
-       output= idr_find(&dev->mode_config.crtc_idr, out_resp->output_id);
+       output = idr_find(&dev->mode_config.crtc_idr, out_resp->output_id);
        if (!output || (output->id != out_resp->output_id)) {
                goto out;
        }
@@ -2182,8 +2229,35 @@ int drm_mode_output_property_set_ioctl(struct drm_device *dev,
                goto out;
        }
        
+       property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id);
+       if (!property || (property->id != out_resp->prop_id)) {
+               goto out;
+       }
+
+       if (property->flags & DRM_MODE_PROP_IMMUTABLE)
+               goto out;
+
+       if (property->flags & DRM_MODE_PROP_RANGE) {
+               if (out_resp->value < property->values[0])
+                       goto out;
+
+               if (out_resp->value > property->values[1])
+                       goto out;
+       } else {
+               int found = 0;
+               for (i = 0; i < property->num_values; i++) {
+                       if (property->values[i] == out_resp->value) {
+                               found = 1;
+                               break;
+                       }
+               }
+               if (!found) {
+                       goto out;
+               }
+       }
+
        if (output->funcs->set_property)
-               ret = output->funcs->set_property(output, out_resp->prop_id, out_resp->value);
+               ret = output->funcs->set_property(output, property, out_resp->value);
 
 out:
        mutex_unlock(&dev->mode_config.mutex);
index ad5ecc5..6b6e1db 100644 (file)
@@ -142,11 +142,26 @@ struct drm_display_mode {
 #define V_CLKDIV2      (1<<13)
 
 #define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */
+
 #define DPMSModeOn 0
 #define DPMSModeStandby 1
 #define DPMSModeSuspend 2
 #define DPMSModeOff 3
 
+#define ConnectorUnknown 0
+#define ConnectorVGA 1
+#define ConnectorDVII 2
+#define ConnectorDVID 3
+#define ConnectorDVIA 4
+#define ConnectorComposite 5
+#define ConnectorSVIDEO 6
+#define ConnectorLVDS 7
+#define ConnectorComponent 8
+#define Connector9PinDIN 9
+#define ConnectorDisplayPort 10
+#define ConnectorHDMIA 11
+#define ConnectorHDMIB 12
+
 enum drm_output_status {
        output_status_connected = 1,
        output_status_disconnected = 2,
@@ -396,7 +411,8 @@ struct drm_output_funcs {
        enum drm_output_status (*detect)(struct drm_output *output);
        int (*get_modes)(struct drm_output *output);
        /* JJJ: type checking for properties via property value type */
-       bool (*set_property)(struct drm_output *output, int prop, uint64_t val);
+       bool (*set_property)(struct drm_output *output, struct drm_property *property,
+                            uint64_t val);
        void (*cleanup)(struct drm_output *output);
 };
 
@@ -504,6 +520,8 @@ struct drm_mode_config {
        struct list_head property_blob_list;
        struct drm_property *edid_property;
        struct drm_property *dpms_property;
+       struct drm_property *connector_type_property;
+       struct drm_property *connector_num_property;
 };
 
 struct drm_output *drm_output_create(struct drm_device *dev,
@@ -597,5 +615,7 @@ extern int drm_mode_getproperty_ioctl(struct drm_device *dev,
                                      void *data, struct drm_file *file_priv);
 extern int drm_mode_getblob_ioctl(struct drm_device *dev,
                                  void *data, struct drm_file *file_priv);
+extern int drm_mode_output_property_set_ioctl(struct drm_device *dev,
+                                             void *data, struct drm_file *file_priv);
 #endif /* __DRM_CRTC_H__ */
 
index f8665be..98fb9ac 100644 (file)
@@ -125,6 +125,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_ROOT_ONLY),
 
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_output_property_set_ioctl, DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY),
index 2ab6a27..722a62c 100644 (file)
@@ -204,6 +204,19 @@ static int intel_crt_get_modes(struct drm_output *output)
        return intel_ddc_get_modes(output);
 }
 
+static bool intel_crt_set_property(struct drm_output *output,
+                                 struct drm_property *property,
+                                 uint64_t value)
+{
+       struct drm_device *dev = output->dev;
+       int i;
+
+       if (property == dev->mode_config.dpms_property) {
+               intel_crt_dpms(output, (uint32_t)(value & 0xf));
+       }
+       return true;
+}
+
 /*
  * Routines for controlling stuff on the analog port
  */
@@ -219,6 +232,7 @@ static const struct drm_output_funcs intel_crt_output_funcs = {
        .detect = intel_crt_detect,
        .get_modes = intel_crt_get_modes,
        .cleanup = intel_crt_destroy,
+       .set_property = intel_crt_set_property,
 };
 
 void intel_crt_init(struct drm_device *dev)
@@ -246,4 +260,5 @@ void intel_crt_init(struct drm_device *dev)
        output->interlace_allowed = 0;
        output->doublescan_allowed = 0;
 
+       drm_output_attach_property(output, dev->mode_config.connector_type_property, ConnectorVGA);
 }
index e3e4b38..94232b9 100644 (file)
@@ -499,6 +499,7 @@ void intel_lvds_init(struct drm_device *dev)
 #endif
 
 out:
+       drm_output_attach_property(output, dev->mode_config.connector_type_property, ConnectorLVDS);
        return;
 
 failed:
index 51fe43c..0da57fa 100644 (file)
@@ -950,6 +950,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
        struct intel_output *intel_output;
        struct intel_sdvo_priv *sdvo_priv;
        struct intel_i2c_chan *i2cbus = NULL;
+       int connector_type;
        u8 ch[0x40];
        int i;
        char name[DRM_OUTPUT_LEN];
@@ -1019,24 +1020,28 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
                sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0;
                output->subpixel_order = SubPixelHorizontalRGB;
                name_prefix="RGB";
+               connector_type = ConnectorVGA;
        }
        else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
        {
                sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1;
                output->subpixel_order = SubPixelHorizontalRGB;
                name_prefix="RGB";
+               connector_type = ConnectorVGA;
        }
        else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
        {
                sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0;
                output->subpixel_order = SubPixelHorizontalRGB;
                name_prefix="TMDS";
+               connector_type = ConnectorDVID;
        }
        else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1)
        {
                sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1;
                output->subpixel_order = SubPixelHorizontalRGB;
                name_prefix="TMDS";
+               connector_type = ConnectorDVID;
        }
        else
        {
@@ -1084,4 +1089,6 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
                        (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
 
        intel_output->ddc_bus = i2cbus; 
+
+       drm_output_attach_property(output, dev->mode_config.connector_type_property, connector_type);
 }
index df43802..f13e36c 100644 (file)
@@ -1118,7 +1118,7 @@ struct drm_mode_mode_cmd {
 #define DRM_IOCTL_MODE_RMFB             DRM_IOWR(0xA5, unsigned int)
 #define DRM_IOCTL_MODE_GETFB            DRM_IOWR(0xA6, struct drm_mode_fb_cmd)
 
-#define DRM_IOCTL_MODE_SETPROPERTY     DRM_IOWR(0xAB, struct drm_mode_set_output_property)
+#define DRM_IOCTL_MODE_SETPROPERTY     DRM_IOWR(0xA7, struct drm_mode_output_set_property)
 #define DRM_IOCTL_MODE_GETPROPBLOB     DRM_IOWR(0xA8, struct drm_mode_get_blob)
 #define DRM_IOCTL_MODE_ATTACHMODE      DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
 #define DRM_IOCTL_MODE_DETACHMODE      DRM_IOWR(0xAA, struct drm_mode_mode_cmd)
index 4a8c6a1..f1fe64d 100644 (file)
@@ -3,10 +3,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <unistd.h>
+#include <string.h>
 
 #include "xf86drm.h"
 #include "xf86drmMode.h"
 
+int dpms_prop_id = 0;
 const char* getConnectionText(drmModeConnection conn)
 {
        switch (conn) {
@@ -72,7 +75,7 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
                        printf("\tflags:     %i\n", props->flags);
                        printf("\tvalues %d: ", props->count_values);
                        for (j = 0; j < props->count_values; j++)
-                               printf("%d ", props->values[j]);
+                               printf("%lld ", props->values[j]);
 
                        printf("\n\tenums %d: \n", props->count_enums);
                        
@@ -86,6 +89,9 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
                                }
 
                        } else {
+                               if (!strncmp(props->name, "DPMS", 4))
+                                       dpms_prop_id = props->prop_id;
+
                                for (j = 0; j < props->count_enums; j++) {
                                  printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name);
                                        if (output->prop_values[i] == props->enums[j].value)
@@ -96,7 +102,7 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
                                if (props->count_enums && name) {
                                        printf("\toutput property name %s %s\n", props->name, name);
                                } else {
-                                       printf("\toutput property id %s %i\n", props->name, output->prop_values[i]);
+                                       printf("\toutput property id %s %lli\n", props->name, output->prop_values[i]);
                                }
                        }
 
@@ -109,7 +115,7 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
                if (mode)
                        printMode(mode);
                else
-                       printf("\t\tmode: Invalid mode %i\n", output->modes[i]);
+                       printf("\t\tmode: Invalid mode %p\n", &output->modes[i]);
        }
 
        return 0;
@@ -123,7 +129,7 @@ int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id)
        printf("\ty            : %i\n", crtc->y);
        printf("\twidth        : %i\n", crtc->width);
        printf("\theight       : %i\n", crtc->height);
-       printf("\tmode         : %i\n", crtc->mode);
+       printf("\tmode         : %p\n", &crtc->mode);
        printf("\tnum outputs  : %i\n", crtc->count_outputs);
        printf("\toutputs      : %i\n", crtc->outputs);
        printf("\tnum possible : %i\n", crtc->count_possibles);
@@ -314,6 +320,21 @@ err:
        return 1;
 }
 
+int testDPMS(int fd, drmModeResPtr res)
+{
+       int output_id;
+       int i;
+
+       for (i = 0; i < res->count_outputs; i++) {
+               output_id = res->outputs[i];
+               /* turn output off */
+               drmModeOutputSetProperty(fd, output_id, dpms_prop_id, 3);
+               sleep(2);
+               drmModeOutputSetProperty(fd, output_id, dpms_prop_id, 0);
+       }
+       return 1;
+
+}
 
 int main(int argc, char **argv)
 {
@@ -343,6 +364,8 @@ int main(int argc, char **argv)
 
        testFrameBufferAdd(fd, res);
 
+       /* try dpms test */
+       testDPMS(fd, res);
        drmModeFreeResources(res);
        printf("Ok\n");